Troubleshooting changes not reflecting in live website for Next JS + Sanity project

13 replies
Last updated: Jun 14, 2023
Hello. I have a Next JS + Sanity project. Some thank you/error messages also come from Sanity in this project. But there is one problem. Although I change the information in Sanity, the changes only take effect locally. This is the case even though there is dataset production. On the live website, the changes are not visible. What could be the reason for this and how do I solve it?
"
https://www.sanity.io/answers/changes-made-in-my-production-studio-arent-affecting-my-website " The link here mentions editing the revalidate values.
"`export async function getStaticProps({ preview = false }) {`

const data = await getClient().fetch(query);


return {

props: { preview, data },

revalidate: 10,

};

}

`export default HomePage;`"

But as you can see in these codes, it is already set to a very short time in the project. Why aren't the changes visible on the live site though?
AI Update

Based on your issue, the problem is likely that you have multiple caching layers working against each other. Even though you've set revalidate: 10, you're probably still using the Sanity CDN (useCdn: true) in your client configuration, which can serve cached content independently of your Next.js ISR settings.

Here's what's happening: When Next.js revalidates and fetches "fresh" data from Sanity, the Sanity CDN may still serve cached content from its own cache layer. This means your ISR revalidation is working, but it's just fetching stale data from Sanity's CDN.

The Solution

In your Sanity client configuration, set useCdn: false for production queries:

import { createClient } from 'next-sanity'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'production',
  apiVersion: '2023-01-01',
  useCdn: false, // Critical: disable Sanity's CDN for ISR
})

Or if you're using the getClient() pattern, make sure it's configured properly:

export function getClient(preview) {
  return createClient({
    projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
    dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
    apiVersion: '2023-01-01',
    useCdn: false, // Disable for production to work with ISR
    token: preview ? process.env.SANITY_API_TOKEN : undefined,
  })
}

Why This Works

As explained in the ISR documentation, when using ISR with external APIs that have their own CDN (like Sanity), it's recommended to disable the external CDN (useCdn: false) to ensure fresh data during revalidation. The Sanity CDN and Next.js ISR can work at cross-purposes, potentially serving stale data. By setting useCdn: false, you query Sanity's API directly, ensuring you get the latest published content during revalidation.

Alternative: On-Demand Revalidation

For instant updates (like fixing typos in those thank you/error messages), consider implementing on-demand ISR with webhooks. This triggers revalidation immediately when content changes in Sanity:

  1. Create an API route in Next.js:
// pages/api/revalidate.js
export default async function handler(req, res) {
  // Validate the request (check for a secret token)
  if (req.query.secret !== process.env.REVALIDATE_SECRET) {
    return res.status(401).json({ message: 'Invalid token' })
  }

  try {
    await res.revalidate('/your-page-path')
    return res.json({ revalidated: true })
  } catch (err) {
    return res.status(500).send('Error revalidating')
  }
}
  1. Set up a webhook in Sanity Studio to call this endpoint when documents change

Modern Alternative: Sanity Functions

Even better than webhooks, you could use Sanity Functions which provide serverless compute directly within Sanity. Functions can listen to document changes and trigger your revalidation endpoint without needing external webhook infrastructure. This is the modern, recommended approach for reacting to content changes.

This gives you both the performance benefits of static generation and instant content updates when needed. The useCdn: false change should fix your immediate issue, while on-demand revalidation (via webhooks or Functions) provides instant updates for critical content changes.

Hello, Nice to meet you. I am very interest in your project
Hello. Thanks for your interest. But this project is my client's project. Unfortunately, I couldn't figure out the cause of the problem. Do you have an idea?
Do you have useCdn as true in your sanity client config?
user L
Hello. Thanks for your response. The value of useCdn in the project is false.
If you open your Network tab, select the request for your home page, and then view the response headers, are you seeing a hit against the Vercel cache? What if you refresh after 10 seconds, and then again after another 10 seconds? If you don’t ever see STALE, I’m not sure Next.js will revalidate. If you do see STALE, wait another 15 seconds and refresh. If it’s still the old data, then presumably the Next.js validation is working and the data being sourced is stale.
user A
Hello. Thank you for your response. I think these should be the values you are talking about.
1.
age: 862.
cache-control: public, max-age=0, must-revalidate3.
content-encoding: br4.
content-type: text/html; charset=utf-85.
date: Sun, 11 Jun 2023 17:22:16 GMT6.
etag: "myetag"7.
server: Netlify8.
strict-transport-security: max-age=31536000; includeSubDomains; preload9.
vary: Accept-Encoding10.
x-nextjs-cache: STALE11.
x-nf-render-mode: odb ttl=6012.
x-nf-request-id: 01H2NQNQ6N59FJ6ZSYV51YXD0Y13.
x-powered-by: Next.jsAnd when you refresh it again after 15 seconds, the results are as follows.

1.
age: 18482.
cache-control: public, max-age=0, must-revalidate3.
content-encoding: br4.
content-type: text/html; charset=utf-85.
date: Sun, 11 Jun 2023 17:53:03 GMT6.
etag: "myetag"7.
server: Netlify8.
strict-transport-security: max-age=31536000; includeSubDomains; preload9.
vary: Accept-Encoding10.
x-nextjs-cache: STALE11.
x-nf-render-mode: odb ttl=6012.
x-nf-request-id: 01H2NSE2ZHQ0AYAJPND0T5DEKE13.
x-powered-by: Next.js
I haven’t tried using ISR on Netlify, but have you confirmed you’ve followed their configuration steps ?
user A
Hello again. As far as I can see in my experiment, these changes are only valid in Vercel. Changes are not visible in Netlify without redeploying. Even though I made the changes in the ISR document, the result is the same. Of course if I did it right. The changes I made are as follows:"`[[redirects]]`

from = "/studio/*"

to = "/studio/index.html"

status = 200

force = false

[functions]
`included_files = ["studio/**"]`".
(I added the Functions part.)

My client uses Netlify. Do you think there is a way I can solve this?
Your content won’t be stored in the
studio
directory (I assume that’s where your Sanity Studio files are), so I don’t believe this is where you want to point
included_files
at. You might instead want to use the
.next
directory or something similar.
Do you think there is a way I can solve this?
I hope so. Even if you don’t use ISR, there are alternatives like running a build when content updates. This can be automated by using webhooks .
user A
Thanks. Netlify now automatically redeploys when data is updated. This solved my problem in the short term.
But in the long run, I guess there should be a way to do this with ISR. In Vercel I can do this without redeploying, constantly deploying in Netlify will cause it to waste build minutes. Do you think there is a way to solve this?
I’m glad to hear it! 🎉
I’m not sure how well ISR works with Netlify nor what their plans are going forward. ISR changes with the new Apps Router in Next.js, but it would be up to Netlify whether to support that. Getting ISR working on Netlify may be best asked in their community support forum, though others here are of course welcome to chime in if they have input.
😀
user A
I got it. Thank you very much again. 🙂

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?