Questions about using Sanity.io with Next.js directory structure

1 replies
Last updated: Jun 10, 2023
Hi all! I'm using a Next.js app with a directory structure, and I have several questions regarding how to fetch data from Sanity.io . It seems that the documentation has changed because I can't find the getStaticProps and getServerSideProps functions. Has anyone successfully created a project using Sanity.io in Next.js?
AI Update

You're right that the documentation has changed! Next.js App Router (introduced in Next.js 13+) completely replaced the need for getStaticProps and getServerSideProps with a simpler, more powerful approach using React Server Components. Many people are successfully using Sanity with Next.js—it's actually one of the most popular stacks for content-driven applications.

The Modern Approach: React Server Components

With the App Router (the app/ directory), you fetch data directly inside your components. No special functions needed! Here's how it works:

// app/blog/page.tsx
import { createClient } from 'next-sanity'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'production',
  apiVersion: '2024-01-01',
  useCdn: true,
})

// Control caching behavior
export const revalidate = 60 // Revalidate every 60 seconds

export default async function BlogPage() {
  // Fetch data directly in the component
  const posts = await client.fetch(`*[_type == "post"]`)
  
  return (
    <div>
      {posts.map(post => (
        <article key={post._id}>{post.title}</article>
      ))}
    </div>
  )
}

Setting Up next-sanity with App Router

  1. Install the package:
npm install next-sanity @sanity/image-url
  1. Create a Sanity client (typically in lib/sanity.ts):
import { createClient } from 'next-sanity'

export const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
  apiVersion: '2024-01-01',
  useCdn: true, // Use CDN for faster reads in production
})

Cache Control Options

The App Router gives you several ways to control caching, replacing the old getStaticProps/getServerSideProps patterns:

Time-based revalidation (like ISR):

export const revalidate = 3600 // Revalidate every hour

Force dynamic rendering (like getServerSideProps):

export const dynamic = 'force-dynamic'

No caching for specific fetches:

const posts = await client.fetch(query, {}, { cache: 'no-store' })

Generating Static Paths

For dynamic routes, use generateStaticParams instead of getStaticPaths:

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await client.fetch(`*[_type == "post"]{ "slug": slug.current }`)
  
  return posts.map((post) => ({
    slug: post.slug,
  }))
}

export default async function BlogPost({ params }: { params: { slug: string } }) {
  const post = await client.fetch(
    `*[_type == "post" && slug.current == $slug][0]`,
    { slug: params.slug }
  )
  
  return <article>{post.title}</article>
}

Important: Next.js 15 Breaking Change

If you're using Next.js 15, params are now a Promise, so you need to await them:

export default async function BlogPost({ 
  params 
}: { 
  params: Promise<{ slug: string }> 
}) {
  const { slug } = await params // Must await!
  const post = await client.fetch(...)
  return <article>{post.title}</article>
}

Additional Resources

The next-sanity toolkit provides everything you need for building production-grade Next.js applications with Sanity, including utilities for live content updates and visual editing. There's also a comprehensive App Router course that walks through fetching Sanity content step-by-step.

The pattern is actually simpler once you understand that components themselves are async and can fetch data directly—no need for the old data-fetching functions!

getStaticProps and getServerSideProps are in the docs under the Pages Router. The default is now the Apps Router, and you won’t find them there.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?