Storybook for /design-sync — ready-to-paste agent prompt (TroveSnap apps/web)
A tightened version of the Storybook setup prompt, with the repo facts verified against the code
(React 19, no Tailwind, CSS-token globals.css, no next/font, the actual decoupled component
tier). Paste the block below into a coding agent. Tracked as WI-093.
Why Storybook over the package shape:
/design-syncdoes true screenshot verification against Storybook → higher fidelity than the package-shape rubric. Use the package shape (packages/trove-ui) only if you don't want a Storybook dep in the app — note it's the more durable artifact (reusable across web + future mobile/Trove Go), so the eventual best-of-both is Storybook pointed at a package. For a first high-fidelity import, Storybook alone is enough.
GOAL
Set up Storybook in apps/web so the /design-sync skill can import our UI into
claude.ai/design. Success = .storybook/main.* exists, `npm run storybook` boots,
`npm run build-storybook` completes, and a curated set of components render
correctly using ONLY props (no Next.js runtime, no Supabase, no data fetching).
claude.ai/design's runtime is browser-only React — no Next server, no Supabase.
REPO CONTEXT (verified — don't re-discover)
- apps/web: Next.js 15.3 App Router, React 19.1, npm (package-lock.json).
- Design system = CSS custom properties + plain class-based CSS in
src/app/globals.css. NO Tailwind, NO CSS-in-JS, NO next/font (the display font
is a self-contained CSS stack), so importing globals.css alone is fully
on-brand. Real token names: --bg/--surface/--surface-soft (parchment),
--accent/--accent-strong/--accent-soft (emerald), --gold/--gold-warm/--gold-soft
(brass), --purple, --danger, --ok, --warn, --text/--text-soft, --border,
--font-display (serif). Icons: lucide-react only.
- 37 components in src/components/{shared,layout,marketplace,seller,trovesnap,
garage-sale,notifications}. Coupling is via next/navigation hooks + next/link
and the supabase / troveSnapApi / troveMarketplaceApi clients — there are NO
inline server actions. 17 import next/*, 12 import a data client.
STORYBOOK SETUP
- Use @storybook/react-vite (NOT @storybook/nextjs) — portable, browser-renderable,
esbuild-bundleable. REACT 19: pin Storybook >= 8.4 (prefer 9.x) and keep
react/react-dom at 19 as peers, or the install will fail / mis-render.
- .storybook/preview.(ts|tsx): import "../src/app/globals.css" globally + a
decorator wrapping stories in a padded container using var(--bg)/var(--surface)
so they read like the real app. (No font shim needed — --font-display is pure CSS.)
- Add npm scripts "storybook" and "build-storybook".
- Shim Next-only imports via viteFinal resolve.alias so stories never pull the
Next runtime (put shims in .storybook/):
- next/link -> a plain <a> wrapper
- next/image -> a plain <img> wrapper
- next/navigation (useRouter/usePathname/useSearchParams) -> inert stubs
DECOUPLING RULES
- Components take ALL data via props. No fetch, no Supabase, no reading
cookies/headers at render. Event handlers are no-op props (Storybook actions
where useful). Use our real domain shapes for mock props (sales, listings,
tokens/treasure, wishlist matches) so previews look like production.
- For data-coupled components: extract the pure presentational part into a sibling
"*View" component that takes props; the original keeps the data wiring. Story
the View. Do NOT change the original component's runtime usage.
SCOPE
Round 1 — VERIFIED no View-extraction needed (story directly):
- shared/AppHeader.tsx (only next/link + usePathname; it imports
layout/SellerShell — story pulls both)
- layout/SellerShell.tsx (only next/link + usePathname; story chrome with
mock children)
These 13 import NO next/* and NO data client — trivial stories; prioritize the
card/badge/chip pieces first:
- marketplace/badges.tsx, marketplace/SellerBrandCard.tsx,
marketplace/ExternalListingLinks.tsx
- trovesnap/ItemCard.tsx, trovesnap/SummaryChips.tsx, trovesnap/PipelineProgress.tsx,
trovesnap/InventoryGrid.tsx, trovesnap/ReviewQueue.tsx,
trovesnap/AppraisePanel.tsx, trovesnap/SourceImportPanel.tsx
- seller/HarnessSetupCard.tsx, seller/CsvImportWizard.tsx
- notifications/NotificationCenter.tsx
Round 2 — the ~12 data-coupled components (import supabase/troveSnapApi/
troveMarketplaceApi): do these only after round 1 survives a /design-sync
import, via *View extraction.
Skip full pages and anything that is mostly data flow.
List every component you touch and whether you storied it directly or via an
extracted View (coverage tracking).
STORY FORMAT
- CSF3 (Meta + StoryObj), co-located as src/components/**/<Name>.stories.tsx.
- One Meta per component; multiple named stories for meaningful states (default,
loading-as-prop, empty, promoted, matched, danger, etc.). Realistic args; set
argTypes for key props.
ACCEPTANCE CRITERIA
- `npm run storybook` boots with zero console errors; every new story renders with
NO network calls and visibly uses the Trove tokens (parchment --bg, emerald
--accent, --font-display on headings).
- `npm run build-storybook` completes cleanly.
- No story imports a live Supabase client, a data client, or a Next server API.
CONSTRAINTS (TroveSnap repo)
- Follow CLAUDE.md / llminterchange.md. Do NOT edit generated tracker HTML
(docs/tracking/**). Do NOT change app behavior — only ADD Storybook, stories,
.storybook shims, and (round 2) extracted *View components without altering the
existing component's runtime usage.
- Start in PLAN MODE: propose the final component list, the shim approach, the
Storybook/React-19 version pins, and the round-2 View-extraction list BEFORE
writing code.
Package-shape fallback (only if no Storybook dep wanted)
Build packages/trove-ui: a framework-free, prop-only design-system package (tsup/esbuild → ESM
dist/ with exports/types), porting the round-1 components above; lift the :root tokens +
base CSS out of globals.css into a shared tokens.css that the package @imports; one
<Name>.example.tsx per component with realistic props; npm run build emits dist/ with no
Next/Supabase in the output. Then point /design-sync at packages/trove-ui. This is the more
durable artifact (reusable for web + future mobile/Trove Go) but skips Storybook's screenshot
verification.
Related
- Trove host vision · Web feature breakdown (the surfaces these components live on).