Developer Tools8 min read

How to Integrate Chromatic with Your Headless CMS

Connect Chromatic to your headless CMS so content changes trigger Storybook visual tests and catch layout regressions before they ship.

Published April 30, 2026
01 β€” Overview

What is Chromatic?

Chromatic is a cloud service for Storybook that runs visual regression tests, publishes Storybooks, and adds UI review to pull requests. It was created by the Storybook team and is used by frontend teams that ship component libraries, design systems, and product UI across many routes, states, and breakpoints.


02 β€” The case for integration

Why integrate Chromatic with a headless CMS?

Your components can pass every unit test and still break when real content lands. A 22-character CTA becomes 48 characters in German, a product card gets a missing image, or an editorial team publishes a campaign title that wraps into three lines on mobile. Chromatic catches those UI changes by comparing rendered Storybook snapshots, but it only sees what your stories render.

Connecting Chromatic to a headless CMS lets you test components against current content, not stale mock data from last quarter. For developer tools teams, that means Storybook stories can use real docs, release notes, product cards, navigation labels, localization strings, and campaign content. When Sanity sends a publish webhook, your integration can fetch exactly the fields needed from the Content Lake with GROQ, update a Storybook fixture, build Storybook, and run Chromatic.

There’s a trade-off. Chromatic doesn’t ingest content records directly. It tests rendered UI, so you need a small bridge that turns structured content into stories, fixtures, or preview routes. The alternative is manual QA, screenshots in Slack, or waiting until production analytics tells you a page is broken.


03 β€” Architecture

Architecture overview

A typical setup starts with a Sanity webhook that fires when a document is published, updated, or deleted. Use a GROQ-powered webhook filter such as _type in ["landingPage", "product", "releaseNote"] so Chromatic doesn’t run for unrelated edits. The webhook sends the document ID to a small handler or a Sanity Function. The handler verifies the request, fetches the latest document from the Content Lake with @sanity/client, and uses GROQ to select only the fields Storybook needs, for example title, hero image URL, CTA label, slug, locale, and referenced theme tokens. That data is written to a JSON fixture or passed to a CI job. Chromatic is usually called from CI with its CLI, not by pushing content records to a content API. The workflow builds Storybook, then runs npx chromatic with your CHROMATIC_PROJECT_TOKEN. The Chromatic CLI uploads the Storybook build and snapshots to Chromatic, where reviewers see visual diffs in the Chromatic app and PR checks. A Sanity Function can route and filter the event without external infrastructure, but a full Storybook build usually belongs in GitHub Actions, GitLab CI, CircleCI, or another build runner.


04 β€” Use cases

Common use cases

πŸ§ͺ

Content-driven visual regression

Run Chromatic when Sanity content changes so components are tested with current headlines, images, CTAs, and references.

🌍

Localization overflow checks

Snapshot translated content in Storybook to catch text wrapping, clipped buttons, and broken card grids before release.

🧩

Design system QA with real examples

Feed Storybook stories with structured Sanity fixtures so design system reviewers see components in realistic content states.

🚦

Campaign release review

Test upcoming launch pages, banners, and product modules in Chromatic before a scheduled publish goes live.


05 β€” Implementation

Step-by-step integration

  1. 1

    Set up Chromatic

    Create a Chromatic project, connect your Git provider, copy the project token, and install the CLI with npm install --save-dev chromatic. Add a CI command such as npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN.

  2. 2

    Model the content in Sanity Studio

    Define schema fields that map to rendered components, for example title, dek, heroImage, ctaLabel, locale, slug, and references to product, theme, or author documents.

  3. 3

    Create Storybook stories that read content fixtures

    Build stories for the components Chromatic should snapshot, then load Sanity-derived JSON fixtures instead of hard-coded lorem ipsum.

  4. 4

    Create the Sanity webhook or Function

    Add a publish webhook with a GROQ filter for the document types that affect UI. Send a small payload, usually _id and _type, to your listener or Function.

  5. 5

    Fetch Sanity content and run Chromatic

    Use @sanity/client and GROQ to fetch the current document, write the fields to a Storybook fixture, build Storybook, and call the Chromatic CLI with your project token.

  6. 6

    Test the review loop

    Publish a safe test document in Sanity, confirm that the webhook starts the workflow, review the Chromatic diff, and decide whether visual changes should block the PR or only notify the team.


06 β€” Code

Code example

typescriptsanity-to-chromatic.ts
import express from "express";
import {createClient} from "@sanity/client";
import {mkdir, writeFile} from "node:fs/promises";
import {execFile} from "node:child_process";
import {promisify} from "node:util";

const exec = promisify(execFile);
const app = express();
app.use(express.json());

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

const query = `*[_id == $id][0]{
  _id,
  _type,
  title,
  dek,
  ctaLabel,
  "slug": slug.current,
  "imageUrl": heroImage.asset->url,
  "theme": theme->name
}`;

app.post("/sanity/chromatic", async (req, res) => {
  const doc = await sanity.fetch(query, {id: req.body._id});
  if (!doc) return res.status(202).send("No document to snapshot");

  await mkdir(".storybook/fixtures", {recursive: true});
  await writeFile(
    ".storybook/fixtures/sanity-current.json",
    JSON.stringify(doc, null, 2)
  );

  await exec("npm", ["run", "build-storybook"]);
  await exec("npx", [
    "chromatic",
    "--project-token",
    process.env.CHROMATIC_PROJECT_TOKEN!,
    "--storybook-build-dir",
    "storybook-static"
  ]);

  res.status(202).send("Chromatic build uploaded");
});

app.listen(3000);

07 β€” Why Sanity

How Sanity + Chromatic works

Build your Chromatic integration on Sanity

Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Chromatic to the content changes that affect your UI.

Start building free β†’

08 β€” Comparison

CMS approaches to Chromatic

CapabilityTraditional CMSSanity
Content shape for visual testsContent often renders as pages or HTML blocks, so teams copy examples into Storybook by hand.Typed JSON in the Content Lake can be queried with GROQ and shaped into Storybook-ready fixtures in one request.
Triggering Chromatic on publishVisual checks usually happen during code deploys, not when editors change live content.GROQ-powered webhooks and Functions can filter content events, route them, and start a Chromatic workflow.
Field-level controlTemplates decide what data is available, which makes small fixture payloads hard to produce.GROQ projects only the fields Chromatic needs, including joined references, image URLs, and localized values.
Testing content variantsTeams often rely on screenshots, preview links, or manual checks for long copy and missing media.Schema-as-code keeps content fields versioned with the app, and Storybook fixtures can be generated from the same schema.
Where the work runsThe safest path is usually a scheduled job or manual QA because publish events are tied to the platform.Functions can handle event logic without external infrastructure, while CI runs the full Storybook build for Chromatic.
Setup trade-offInitial setup can be familiar, but visual testing stays disconnected from content changes.You need to define schemas, webhooks, and fixtures, then Chromatic can test real content changes consistently.

09 β€” Next 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 Chromatic and 200+ other tools.