Frameworks & Hosting8 min read

How to Integrate Netlify with Your Headless CMS

Connect Netlify to structured content so every publish can trigger a fresh build, preview, or deploy without copying content between tools.

Published April 29, 2026
01Overview

What is Netlify?

Netlify is a web development platform for building, deploying, and hosting sites and web apps from Git-based workflows. Teams use it for static sites, Jamstack apps, serverless functions, edge logic, deploy previews, branch deploys, and form handling. It’s widely used by frontend teams working with frameworks like Next.js, Astro, Gatsby, Remix, Nuxt, and Eleventy.


02The case for integration

Why integrate Netlify with a headless CMS?

If your site runs on Netlify but your content lives somewhere else, your build pipeline needs a reliable way to know when something changed. Without an integration, editors publish a page, developers manually trigger a deploy, someone waits for the build, and stale content can sit live for hours. That gets messy fast when you have multiple locales, product pages, author profiles, release notes, and campaign landing pages changing every day.

A headless CMS integration solves that by turning content events into Netlify actions. When an editor publishes, updates, or deletes content, a webhook can call a Netlify Build Hook or the Netlify API to start a new site build. With Sanity, structured content in the Content Lake means your frontend can fetch typed JSON during the build, not parse HTML or page blobs. GROQ lets the build request exactly the fields it needs, such as title, slug, hero image, author name, related products, and locale.

There are trade-offs. Triggering a full Netlify build on every small content update can waste build minutes on large sites. For high-change datasets, you’ll usually add filtering, batching, or selective rebuild patterns. Sanity webhooks and Functions help here because you can trigger Netlify only for specific document types, publish events, locales, or routes.


03Architecture

Architecture overview

A typical Sanity and Netlify integration starts when an editor publishes content in Sanity Studio. The mutation lands in the Content Lake as structured JSON. A Sanity webhook filters the event, for example only published `post`, `page`, or `product` documents, and sends the document ID and mutation type to a Netlify Function, an API route, or a Sanity Function. That server-side handler fetches the latest content from Sanity with GROQ. This is where you select only the fields Netlify’s build needs, such as `_id`, `_type`, `slug.current`, `title`, `language`, and referenced data like `author->name` or `category->slug.current`. The handler can then call Netlify in one of two common ways: `POST` to a Netlify Build Hook URL, or call the Netlify API with `createSiteBuild({ site_id })` using a Netlify personal access token. Netlify receives the build request, pulls the latest site code from Git, runs the configured build command, and your frontend fetches current Sanity content during build time or at request time, depending on your framework. The deployed result is served from Netlify’s hosting layer to visitors. For more advanced setups, Sanity Functions can run the server-side logic directly on content events, so you don’t need to host a separate webhook service.


04Use cases

Common use cases

🚀

Publish-triggered Netlify builds

Start a Netlify build the moment an editor publishes a page, post, product, or locale-specific document in Sanity.

🔍

Preview deploys for editorial review

Use Netlify deploy previews with Sanity draft content so editors can review real pages before publishing.

🌐

Multi-locale site rebuilds

Trigger Netlify only for affected language routes, such as `/en/pricing` or `/fr/tarifs`, when localized Sanity documents change.

Framework builds with structured data

Feed Astro, Gatsby, Next.js, Remix, or Nuxt builds on Netlify with typed JSON from Sanity’s Content Lake.


05Implementation

Step-by-step integration

  1. 1

    Set up Netlify access

    Create or choose a Netlify site, connect it to your Git repository, and confirm the build command and publish directory. In Netlify, create a personal access token from User settings, Applications, Personal access tokens. You can also create a Build Hook under Site configuration, Build & deploy, Continuous deployment, Build hooks if you prefer a URL-based trigger.

  2. 2

    Install the packages

    In the project that will receive Sanity webhooks, install the Netlify API client and Sanity client: `npm install netlify @sanity/client`. If you’re using a Netlify Function, also install `@netlify/functions` for TypeScript types.

  3. 3

    Model the content in Sanity Studio

    Define schema fields your Netlify frontend can build from, such as `title`, `slug`, `seoTitle`, `description`, `heroImage`, `body`, `language`, and references like `author` or `category`. Keep route fields predictable. A `slug.current` value is easier to map to Netlify routes than a freeform URL string.

  4. 4

    Create the webhook or Function

    Create a Sanity webhook that fires on create, update, delete, or publish mutations for the document types your site uses. Send it to a Netlify Function endpoint, such as `https://your-site.netlify.app/.netlify/functions/sanity-publish`, or use a Sanity Function if you want the event handling to live inside Sanity.

  5. 5

    Call Netlify from the handler

    In the handler, verify the request, fetch the latest document with GROQ, decide whether the change should trigger a build, and call Netlify’s API with `createSiteBuild({ site_id })`. For large sites, add guards so typo fixes to internal-only documents don’t start a full rebuild.

  6. 6

    Test the full path

    Publish a test document in Sanity Studio, confirm the webhook delivery, check the Netlify deploy log, and verify the rendered page. Test update and delete cases too. Deleted content often needs route cleanup, redirects, or a 404 path check.


06Code

Code example

tsnetlify/functions/sanity-publish.ts
import type { Handler } from "@netlify/functions";
import NetlifyAPI from "netlify";
import { createClient } from "@sanity/client";

const sanity = createClient({
  projectId: process.env.SANITY_PROJECT_ID!,
  dataset: process.env.SANITY_DATASET!,
  apiVersion: "2025-01-01",
  useCdn: false,
  token: process.env.SANITY_READ_TOKEN
});

const netlify = new NetlifyAPI(process.env.NETLIFY_AUTH_TOKEN!);

export const handler: Handler = async (event) => {
  const payload = JSON.parse(event.body || "{}");
  const id = payload._id?.replace(/^drafts\./, "");

  const doc = await sanity.fetch(
    `*[_id == $id][0]{_id, _type, title, "slug": slug.current}`,
    { id }
  );

  if (!doc || !["page", "post", "product"].includes(doc._type)) {
    return { statusCode: 202, body: "No Netlify build needed" };
  }

  await netlify.createSiteBuild({
    site_id: process.env.NETLIFY_SITE_ID!
  });

  return {
    statusCode: 200,
    body: JSON.stringify({ queued: true, slug: doc.slug })
  };
};

07Why Sanity

How Sanity + Netlify works

Build your Netlify integration on Sanity

Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Netlify builds, previews, and deploys to your publishing workflow.

Start building free →

08Comparison

CMS approaches to Netlify

CapabilityTraditional CMSSanity
Content shape for Netlify buildsOften outputs rendered pages or mixed HTML, which makes static builds harder to map to clean routes and components.Uses schema-as-code and structured JSON in the Content Lake, so routes, components, and fields stay explicit.
Triggering Netlify deploysMay need plugins, scheduled jobs, or manual deploy buttons to refresh the hosted site.Uses GROQ-powered webhooks and Functions to trigger Netlify only for the content changes that matter.
Preview workflowsPreview is usually tied to the system’s own rendering layer, which can drift from the Netlify frontend.Sanity Studio, Presentation Tool, and Netlify deploy previews can show editors draft content in the real frontend.
Query control during buildsBuilds may need to fetch full pages or broad API responses, then filter data in application code.GROQ can filter, project, join references, sort, and slice content in one query for faster Netlify builds.
Handling large sitesFull rebuilds are common, and fine-grained invalidation can be hard to set up.Webhook filters, Functions, and Sync tags help you route changes to the right Netlify build, cache update, or frontend path.
Beyond the websiteContent is often page-first, so reuse in apps, agents, and external systems takes cleanup.The same structured back end can power Netlify, mobile apps, search, Agent Context, and AI content workflows.

09Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with Netlify and 200+ other tools.