Developer Tools8 min read

How to Integrate Storybook with Your Headless CMS

Connect Storybook to structured content so designers, engineers, and reviewers can test UI states with real copy, images, and reference data before code ships.

Published April 30, 2026
01Overview

What is Storybook?

Storybook is an open-source workshop for building, testing, and documenting UI components in isolation. Frontend teams use it with React, Vue, Angular, Svelte, Web Components, and other frameworks to create stories that show specific component states. It’s a common tool in design systems, component libraries, and product teams that need repeatable UI review outside the full app.


02The case for integration

Why integrate Storybook with a headless CMS?

Component stories are only useful if they reflect the content your UI actually handles. A hero component with "Lorem ipsum" won’t catch a 92-character headline, a missing image alt value, or a referenced author object that changes the layout. When Storybook reads structured content from a headless CMS category tool, your stories can cover real editorial states instead of hand-written mock data that drifts after two sprints.


03Architecture

Architecture overview

A typical integration starts when an editor publishes or updates content in Sanity Studio. A Sanity webhook fires on the matching mutation, often filtered to types like landingPage, hero, productCard, or testimonial. The webhook calls a Next.js route, serverless function, CI endpoint, or Sanity Function. That handler uses @sanity/client and GROQ to fetch the full shape Storybook needs, including references, image metadata, and only published fields. The handler then converts the result into Storybook-friendly args, usually JSON files under src/stories/__fixtures__ or a small internal endpoint consumed by Storybook loaders. If your Storybook is published through CI or Chromatic, the same handler can call GitHub, GitLab, or a build webhook to rebuild the static Storybook. End users then open Storybook and see components rendered with current structured content, not stale mocks.


04Use cases

Common use cases

🧩

Real-content component states

Render Button, Hero, Card, and Navigation stories with published Sanity content so long labels, missing images, and nested references are tested early.

📚

Design system documentation

Show approved editorial examples beside design tokens and component props, giving designers and engineers one place to review usage.

Content-driven visual review

Trigger a Storybook or Chromatic rebuild after a publish event so reviewers can catch layout regressions caused by real content changes.

🧪

Fixture generation for tests

Generate stable JSON fixtures from GROQ queries and reuse them in Storybook, unit tests, and visual snapshots.


05Implementation

Step-by-step integration

  1. 1

    Set up Storybook

    In your frontend repo, run npx storybook@latest init and choose the framework builder that matches your app, such as @storybook/react-vite or @storybook/nextjs. Storybook itself doesn’t require an account or API key. If you publish visual reviews with Chromatic, create a Chromatic project token and add it to CI.

  2. 2

    Install Sanity and helper packages

    Add @sanity/client to the repo or to the webhook service that will prepare Storybook data. If you commit generated fixtures back to GitHub, add @octokit/rest. Keep SANITY_PROJECT_ID, SANITY_DATASET, SANITY_API_TOKEN, and any CI or Git provider tokens in environment variables.

  3. 3

    Model Storybook-ready content in Sanity Studio

    Create schemas that match real UI inputs, not page blobs. For a Hero story, fields might include eyebrow, title, subtitle, image, image.alt, cta.label, cta.href, and theme. Add validation for required component inputs so Storybook doesn’t hide bad content with fallback strings.

  4. 4

    Create a publish-triggered sync

    Add a Sanity webhook filtered to publish events and relevant document types. Point it at a webhook listener, Sanity Function, or middleware route. In the handler, fetch the canonical document with GROQ, expand references, and map the result to Storybook args.

  5. 5

    Connect the data to Storybook

    Use Storybook args, loaders, or imported JSON fixtures. For stable visual tests, generated fixtures are usually better than live fetches because every screenshot uses the same input. For internal preview stories, loaders can read directly from a local API endpoint.

  6. 6

    Test the frontend experience

    Run npm run storybook locally, verify the content-driven stories, and add at least three edge cases, such as a long headline, no CTA, and a portrait image. Then run npm run build-storybook in CI and, if you use Chromatic, publish the build for visual review.


06Code

Code example

A minimal Next.js webhook route that receives a Sanity publish event, fetches content with GROQ, and updates a JSON fixture consumed by a Storybook story. Storybook has no content-ingest API, so this pushes data into the Storybook project instead.

typescript
import {createClient} from '@sanity/client';
import {Octokit} from '@octokit/rest';
import type {NextRequest} from 'next/server';

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

const github = new Octokit({auth: process.env.GITHUB_TOKEN!});

export async function POST(req: NextRequest) {
  const {_id} = await req.json();

  const hero = await sanity.fetch(`
    *[_id == $id][0]{
      title,
      subtitle,
      "imageUrl": image.asset->url,
      "imageAlt": image.alt,
      cta{label, href}
    }
  `, {id: _id.replace('drafts.', '')});

  const path = 'src/stories/__fixtures__/hero.json';
  const repo = {owner: 'acme', repo: 'web'};
  const current = await github.repos.getContent({...repo, path});

  await github.repos.createOrUpdateFileContents({
    ...repo,
    path,
    message: `Update Storybook hero fixture from ${_id}`,
    content: Buffer.from(JSON.stringify(hero, null, 2)).toString('base64'),
    sha: Array.isArray(current.data) ? undefined : current.data.sha,
  });

  return Response.json({ok: true});
}

// Hero.stories.tsx
import type {Meta, StoryObj} from '@storybook/react';
import hero from './__fixtures__/hero.json';
import {Hero} from '../components/Hero';

export default {component: Hero} satisfies Meta<typeof Hero>;
export const Published: StoryObj<typeof Hero> = {args: hero};

07Why Sanity

How Sanity + Storybook works

Build your Storybook integration on Sanity

Sanity’s AI Content Operating System gives you structured content, real-time publish events, GROQ, and flexible APIs for connecting Storybook to the same source your products use.

Start building free →

08Comparison

CMS approaches to Storybook

CapabilityTraditional CMSSanity
Component-ready data shapeOften outputs page HTML or template-specific fields, so teams create separate mock data for Storybook.Content Lake stores structured JSON, and GROQ can return the exact args shape a Storybook component expects.
Publish-triggered updatesStorybook updates usually depend on manual exports, scheduled jobs, or someone copying content into fixtures.Webhooks can filter publish events with GROQ, while Functions can run sync logic without extra infrastructure.
Reference handlingAuthors, categories, media, and related entries are often tied to templates, which makes isolated component testing harder.GROQ can join references, project image URLs, and flatten nested fields into one fixture for Storybook.
Visual testing stabilityLive page content can change outside the test flow, causing noisy screenshots.You can generate pinned fixtures on publish and reuse them in Storybook, unit tests, and Chromatic runs.
Schema changesField definitions may live in an admin UI, making review and version control harder.Sanity Studio uses schema-as-code, so component prop changes and content schema changes can be reviewed in the same pull request.

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 Storybook and 200+ other tools.