In this article we'll wrap up our previous article on draft mode setup, by showing you how to configure on demand revalidation using SvelteKit, Vercel and Sanity.
This article assumes you'll be using all three technologies with TypeScript, if you're not using TypeScript, or your setup differs slightly, you might still find this useful.
We're going to do the following:
- Create a Sanity webhook
- Set up a new API route to handle revalidation
- Export ISR config from the routes to be revalidated
- Update or create our hooks.server.ts file
- Update our Sanity client
Creating a Sanity webhook
To create a new Sanity webhook for on demand revalidation, visit sanity.io and login. Click manage projects, then the project you're using, then click the API tab.
Create a new webhook, add the following settings.
- Name - Revalidation Webhook (or whatever you want to call it).
- Description - A description for the webhook.
- Url - Add your full site url with /api/revalidate as the path i.e. https://www.your-site.com/api/revalidate
- Dataset - Whichever dataset you want this to apply to.
- Trigger on - Create, Update and Delete.
- Projection - Set {_id, "slug": slug.current, _type}
- Status - Enable webhook
- Http Method - Post
- Secret - Add a secret here that matches your Vercel bypass token. If you don't already have a Bypass Token, visit Vercel and add a new Environment Variable for your app called BYPASS_TOKEN, add this to your .env.local file and set the same token value for your Secret here.
Create a revalidation endpoint
We now need to create a new revalidation endpoint, and for this article we're going to assume that we want to revalidate a main post listing page, when saving a document that matches the type post.
Create a file called src/routes/api/revalidate/+server.ts.
Here we check that the Sanity signature matches the content using our Bypass Token. If it doesn't, we return a 403.
We then check to see if the body value has a slug, if it does, then we proceed with a revalidation.
We're also checking here to see if the document type is a post, if it is, we'll also revalidate the post listing page.
To revalidate, we need to hit the original slug with a header of x-prerender-revalidate, with a value matching our bypass token, this will rebuild the page.
We also include the following line at the start of our revalidateSlug function:
This is to add a delay before revalidation, to make sure that the Sanity update has propagated to the document. Failure to add this can result in needing to save a page twice, and other unexpected behavior.
In our revalidation hook we also revalidate our main post listing page, if the document we are saving is a post.
Exporting ISR config from a route
We need to enable ISR mode for our pages, assuming we have the following routes
- src/routes/blog
- src/routes/blog/[slug]
Edit or create the +page.server.ts files for these routes, so we end up with the following files:
- src/routes/blog/+page.server.ts
- src/routes/blog/[slug]/+page.server.ts
This will enable ISR mode for the routes. The expiration value we have set here as 60 seconds, meaning after 60 seconds have passed, the page will be marked for a rebuild. We recommend using an environment variable for the expiration value and use a higher value in seconds for this, depending on the page type. You may want to revalidate once a day, or even once a week or month, if not triggering a manual update.
Creating or updating the hooks.server.ts file
Edit or create the following file src/hooks.server.ts
Here we're going to set a new local variable given the presence of an x-prerender-revalidate cookie matching the bypass token.
To create this new locals variable, edit the src/app.d.ts file and add the new variable:
Updating the Sanity Client
For this, we'll use a simple example, assuming we want to revalidate individual blog pages, edit the following page: src/routes/blog/[slug]/+page.server.ts
This also makes the assumption that your blog pages will also have a slug prefix of blog i.e. blog/your-article-slug.
Now edit or create the src/lib/sanity.ts file (or adjust the code above to match the file where you keep your Sanity functionality).
Next we add our getPost function to the src/lib/sanity.ts file:
With this we pass the revalidate variable we capture in our hook to the sanity client creation function, and also modify the caching option to our call based upon the presence of this variable.
Then we create (or update) our getSanityClient function:
Adjust this to match the environment variables you are using for your project id, dataset and sanity token values.
Summary
This should be enough to get you started, or to point you in the right direction. One of the main things that may throw you off is the fact that sometimes when running the Sanity webhook, stale content can still be pulled from Sanity during the page rebuild.
Because of this, we add the following code in our revalidation function.