Issues with new document types not showing up in Next.js app using Sanity

10 replies
Last updated: Mar 19, 2024
Using next js (14, app router) and sanity, I seem to be having issues when I create a new document type, add documents and then try to use it in my app straight away. Seems like they don't show up. Toggling on and off the "useCdn" property in the client fixed it when it happened before, but I'm having the same issues again. Anyone know what to do?
AI Update

This is a common frustration with Next.js 14 App Router and Sanity! The issue you're experiencing is actually caused by Next.js's aggressive data caching, not Sanity's CDN. Toggling useCdn seems to work temporarily because changing your client configuration forces Next.js to treat it as a "new" fetch, but the underlying caching problem remains.

The Root Cause: Next.js Data Cache

In Next.js App Router, all fetch requests (including those from client.fetch()) are automatically cached by Next.js's Data Cache. This is completely separate from Sanity's CDN caching. Even with useCdn: false, Next.js will still cache your query results indefinitely by default, which is why your new documents don't appear.

The Solution: Control Next.js Caching

You need to tell Next.js how to handle the cache for your Sanity queries. Here are your options:

Option 1: Disable caching during development

const data = await client.fetch(query, params, {
  next: { revalidate: 0 } // Don't cache at all
})

Option 2: Use cache: 'no-store'

const data = await client.fetch(query, params, {
  cache: 'no-store' // Skip the cache entirely
})

Option 3: Use the sanityFetch helper from next-sanity

The next-sanity package provides a sanityFetch helper that's designed specifically for App Router and handles caching configuration for you. You'll need to create this helper in your project:

// lib/sanity.fetch.ts
import { client } from './sanity.client'

export async function sanityFetch<QueryResponse>({
  query,
  params = {},
  tags,
}: {
  query: string
  params?: any
  tags?: string[]
}) {
  return client.fetch<QueryResponse>(query, params, {
    next: {
      revalidate: 0, // For development
      tags, // For production with tag-based revalidation
    },
  })
}

Then use it in your components:

const posts = await sanityFetch({
  query: POSTS_QUERY,
  tags: ['post'],
})

Another Potential Issue: Default Perspective

If you're using a recent API version (2025-02-19 or later), there's another possible culprit. The default perspective changed to published, which means you'll only see published documents by default.

If you're creating documents and they're staying in draft state (not clicking "Publish" in the Studio), they won't appear in your queries. To see drafts during development, configure your client:

const client = createClient({
  // ... other config
  perspective: 'previewDrafts', // Shows drafts with fallback to published
  useCdn: false, // CDN doesn't support draft content
})

Production Setup

For production, you'll want to use tag-based revalidation so your cache stays fresh when content changes. Combine sanityFetch with tags, then set up Sanity Functions to call Next.js's revalidateTag() when content changes. This gives you the performance benefits of caching without the staleness issues.

big ol' blocker right now which is sad
Is there no way to use something more dynamic when live developing with content?
some kind of "npx sanity-force-refresh"
next js cache issue πŸ™ƒ
//disable caching for development

export const revalidate = 0;
Hello
user N
, same issue here. On Vision I'm abled to query with the latest data, but unfortunatly from NextJs the data is outdated. I tried switching apiVersion and disabling cdn but is still getting old data.
if you're in a next.js app router component, try disabling the cache. worked for me.
is disabled: "useCdn: false,"
that won't disable the next js cache
// page.jsx/tsx
import { client } from "@/lib/client";
import Component from "@/components/component"
// ... other imports

// disable caching for development
export const revalidate = 0;
// ↑ ↑ ↑ ↑ this is what you need @Sergio Vergara 

async function Page() {
  const data = await client.fetch(`*[_type == "post"] | order(order asc)`);

  return (
    <div className="...">
      <Component data={data} />
    </div>
  );
}

export default Page;
It works! Thank you
user N

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?