How to Integrate SvelteKit with Your Headless CMS
Connect SvelteKit to a headless CMS so page data, preview routes, and cached endpoints update the moment editors publish.
What is SvelteKit?
SvelteKit is the official full-stack framework for building Svelte applications. It handles server-side rendering, static generation, client navigation, form actions, API routes, and deployment adapters in one project. Teams use it for marketing sites, documentation, dashboards, commerce front ends, and apps that need fast routing without a large client bundle.
Why integrate SvelteKit with a headless CMS?
SvelteKit gives you flexible rendering choices, but your content still has to come from somewhere. If product pages, docs, authors, localized copy, and campaign pages live in spreadsheets or hardcoded JSON files, every publish turns into a developer task. A headless CMS integration fixes that split by letting editors update structured content while SvelteKit handles routes, load functions, API endpoints, and hosting.
For Frameworks & Hosting projects, the big win is control over when and how content reaches the page. SvelteKit can fetch content in `+page.server.ts`, generate static pages at build time, serve dynamic routes from a Node adapter, or run at the edge depending on your host. With an AI Content Operating System like Sanity, content is structured in the Content Lake, selected with GROQ, and sent through webhooks the moment something is published, updated, or deleted.
The alternative is usually messy. You either rebuild the whole site for one typo, poll an API every few minutes, or ask developers to copy content into code. That can work for a five-page site. It breaks down when you have 400 docs pages, 12 locales, preview requirements, and editors publishing during a launch window.
Architecture overview
A typical SvelteKit integration starts with structured content in Sanity's Content Lake. Editors work in Sanity Studio, where schemas define fields like `title`, `slug`, `seo`, `body`, `author`, `locale`, and references to related documents. When an editor publishes a document, a Sanity webhook can POST to a SvelteKit endpoint such as `/api/sanity-sync`, or a Sanity Function can run first to enrich the payload, fetch related records, and call that endpoint without separate server infrastructure. Inside SvelteKit, the endpoint is a normal route handler, for example `src/routes/api/sanity-sync/+server.ts`. It validates a shared secret, reads the changed document ID from the webhook payload, and uses `@sanity/client` with a GROQ query to fetch exactly the fields the app needs. That query can resolve references in the same request, such as `author->name`, related articles, or localized variants. After SvelteKit receives the data, you decide what to do based on your rendering mode. A server-rendered page can read fresh content in `+page.server.ts` on the next request. A statically generated site can call a hosting API to trigger a targeted deploy or cache purge. A Node-hosted SvelteKit app can update a Redis, KV, or in-memory route cache, then the end user gets the updated route at `/blog/my-post`, `/docs/install`, or any route your app maps from the content slug.
Common use cases
Publish-triggered SvelteKit routes
When an editor publishes a page in Sanity Studio, a webhook hits a SvelteKit endpoint that refreshes only the affected slug.
Draft previews for editors
SvelteKit preview routes can load draft content from Sanity so editors review `/preview/blog/my-post` before publishing.
Localized marketing pages
GROQ queries can pull locale-specific fields and references, while SvelteKit maps them to routes like `/en/pricing` and `/fr/tarifs`.
Docs for users and AI agents
The same structured docs can render in SvelteKit and feed Agent Context for support agents, search bots, or internal tools.
Step-by-step integration
- 1
Create the SvelteKit app and add Sanity credentials
Run `npm create svelte@latest my-site`, choose TypeScript if your team uses it, then install the Sanity client with `npm install @sanity/client`. SvelteKit doesn't require its own account, but your host, such as Vercel, Netlify, Cloudflare, or Node, will need environment variables for `SANITY_PROJECT_ID`, `SANITY_DATASET`, `SANITY_READ_TOKEN`, and a webhook secret.
- 2
Model content in Sanity Studio
Create schemas that match your SvelteKit routes instead of modeling pages as one large rich text blob. For a blog route, use fields like `title`, `slug`, `excerpt`, `mainImage`, `body`, `author` as a reference, `publishedAt`, and `seo`. For docs, add `section`, `order`, `locale`, and `relatedArticles`.
- 3
Fetch content in SvelteKit load functions
Use `@sanity/client` in `+page.server.ts` for server-only tokens, or use public read settings for safe client-side queries when the dataset allows it. A dynamic route like `src/routes/blog/[slug]/+page.server.ts` can run a GROQ query with the incoming `params.slug` and return typed JSON to the page.
- 4
Create a publish sync endpoint
Add a SvelteKit route handler such as `src/routes/api/sanity-sync/+server.ts`. Configure a Sanity webhook to call it on publish, update, and delete events. For more processing, use a Sanity Function to fetch related records, normalize payloads, or call multiple SvelteKit deployments from one content event.
- 5
Connect cache, rebuild, or preview behavior
Decide what should happen after the endpoint receives a content event. Server-rendered pages may only need a cache purge. Static builds may call a host deploy hook. Preview routes should use draft-aware queries and a private token so editors can see unpublished changes without exposing drafts to visitors.
- 6
Test the full path
Publish a test document, inspect the webhook delivery in Sanity, check your SvelteKit server logs, and load the affected route. Test deletes, slug changes, reference updates, and locale changes because those are the cases that usually break first.
Code example
import { error, json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { createClient } from '@sanity/client';
import {
SANITY_PROJECT_ID,
SANITY_DATASET,
SANITY_READ_TOKEN,
SANITY_WEBHOOK_SECRET
} from '$env/static/private';
const sanity = createClient({
projectId: SANITY_PROJECT_ID,
dataset: SANITY_DATASET,
apiVersion: '2025-02-19',
token: SANITY_READ_TOKEN,
useCdn: false
});
export const POST: RequestHandler = async ({ request, fetch }) => {
if (request.headers.get('x-sanity-secret') !== SANITY_WEBHOOK_SECRET) {
throw error(401, 'Invalid webhook secret');
}
const { _id } = await request.json();
const page = await sanity.fetch(
`*[_id == $id][0]{
_id,
title,
"slug": slug.current,
excerpt,
"author": author->name
}`,
{ id: _id }
);
if (!page?.slug) return json({ ok: true, skipped: true });
await fetch('/api/cache/pages', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ path: `/${page.slug}`, page })
});
return json({ ok: true, path: `/${page.slug}` });
};How Sanity + SvelteKit works
Build your SvelteKit integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs you need to connect SvelteKit routes, previews, caches, and hosted deployments.
Start building free →CMS approaches to SvelteKit
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Route-ready structured content | Content often starts as rendered pages, shortcodes, or theme-bound fields, so SvelteKit needs cleanup code before rendering. | The Content Lake returns typed JSON, and GROQ can resolve references for a SvelteKit route in one query. |
| Publish-time sync | Teams often rebuild the full site, export static files, or rely on plugins that send broad payloads. | GROQ-filtered webhooks and Functions can react to publish, update, and delete events, then call the exact SvelteKit endpoint you define. |
| Field-level query control | SvelteKit may receive a full page body when it only needs a title, slug, and summary. | GROQ lets each `+page.server.ts` request only the fields needed for that route, including joined reference data. |
| Editorial preview | Preview is often tied to the original theme or admin UI, which makes SvelteKit routes harder to match. | Presentation Tool and Content Source Maps can connect rendered SvelteKit elements back to source fields in Sanity Studio. |
| Static, server-rendered, and edge deployments | The publishing flow is usually built around one rendering model. | SvelteKit can fetch from the Content Lake at build time, request time, or through a webhook-driven cache path. |
| Content reuse beyond the website | Content is usually shaped for web pages first, so reuse in apps or agents takes extra cleanup. | The same structured content can power SvelteKit, mobile apps, search, and Agent Context for production AI agents. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Next.js
Build React sites with server components, draft previews, and targeted content updates from Sanity.
Sanity + Nuxt
Connect Vue routes, server endpoints, and localized content workflows to Sanity's Content Lake.
Sanity + Astro
Ship content-heavy static sites that pull structured Sanity data at build time or through server routes.