Skip to content

Publishing Storybook

Storybook is published as its own dedicated Netlify site, separate from the main Astro app, on the same GitHub repo (shawn-sandy/513). Every push to primary rebuilds and republishes the src/components/react/** stories at a dedicated URL via Git CI — there is no manual deploy step and no deploy:storybook script.

How publishing works — the shared-dist/ model

Section titled “How publishing works — the shared-dist/ model”

Netlify reads the same root netlify.toml for every site linked to the repo, and a publish value there overrides each site’s dashboard setting. Rather than fight that, both sites publish the same dist/ directory — each one’s own build command fills dist/ with its own artifact.

App site

Build command npm run build → Astro SSR + static output in dist/.

Storybook site

Build command npm run build-storybook:netlify (storybook build -o dist) → static component docs in dist/.

The two builds run in separate, isolated Netlify build environments, so they never collide. publish = "dist" stays pinned in netlify.toml exactly as it always has — so the app deploy is untouched, and no per-site dashboard publish pin is required.

  1. Author or edit a story under src/components/react/** (see below).

  2. Preview locally with the Storybook dev server:

    Terminal window
    npm run storybook # http://localhost:6006
  3. Verify the production build before pushing:

    Terminal window
    bash scripts/verify-storybook-build.sh
  4. Commit and push to primary. The Storybook Netlify site auto-builds npm run build-storybook:netlify and publishes dist/.

  5. Confirm it is live at the Storybook site URL — the manager loads with your stories in the sidebar.

Stories are discovered by this glob (from .storybook/main.ts):

  • Directorysrc/components/react/
    • DirectoryMyComponent/
      • MyComponent.tsx
      • MyComponent.stories.tsx ← discovered and published

Use the project’s CSF3 + @storybook/react-vite conventions:

src/components/react/MyComponent/MyComponent.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { MyComponent } from '#components/react/MyComponent/MyComponent'
const meta = {
title: 'React/MyComponent',
component: MyComponent,
} satisfies Meta<typeof MyComponent>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: { label: 'Hello' },
}

The Storybook site is unauthenticated. Anything a story imports at build time is baked into the static bundle and served publicly. Two rules:

No server-only imports

Do not import server-only modules in a story (Astro.locals, #libs/database, anything pulling getViteConfig). They will crash a headless build or leak into the bundle.

No secret values

Never import a module that embeds a real credential at module scope. Publishable Clerk keys (pk_*) are fine; secret keys, JWTs, Supabase/Turso credentials are not.

scripts/verify-storybook-build.sh enforces this: it builds Storybook and hard-fails if a secret value (Clerk sk_, Supabase sbp_, a JWT, a PEM private key, whsec_, chpt_, xaat-) is baked into the bundle. Run it before every publish — and it is the right thing to wire into CI as a status check.

The dedicated Storybook site is created once in the Netlify dashboard. The app site needs no changes.

SettingStorybook site
Build commandnpm run build-storybook:netlify
Publish directorydist (shared, from netlify.toml)
FrameworkNone / Other (disable Astro autodetect)
Production branchprimary
Node version22.12.0 (from root netlify.toml)

A guarded Playwright spec checks the deployed site renders real stories (skipped unless STORYBOOK_URL is set, so it never fails the app repo’s npm run test:e2e):

Terminal window
STORYBOOK_URL=https://<site>.netlify.app npx playwright test e2e/storybook-deploy.spec.ts

The site is publishing the Astro dist/. Its build command is wrong — set it to npm run build-storybook:netlify, not npm run build or plain npm run build-storybook.

  • Operational detail: .storybook/README.md → “Deploying Storybook”
  • Authoring & visual testing: Storybook & Chromatic
  • Verify script: scripts/verify-storybook-build.sh
  • Live-deploy E2E: e2e/storybook-deploy.spec.ts