Storybook lets you build, test, and review UI components in isolation, and Chromatic automates visual review of UI changes on every PR.
Storybook is not preinstalled in apps/web. It’s an opt-in addition — set it up with the official guide below, then follow the conventions on this page so stories sit naturally next to your components.
Setup
Storybook is stack-agnostic and works with the Vite-based apps/web out of the box. Initialise it from the web app:
cd apps/web
npx storybook@latest init
For visual review, follow the Chromatic GitHub Actions guide.
Conventions
Keep stories where Ship keeps components:
- shadcn/ui primitives —
src/components/ui/ (e.g. button.tsx, input.tsx, card.tsx)
- Shared app components —
src/components/
Point Storybook at both directories and label them so the sidebar mirrors the codebase:
stories: [
{
directory: '../src/components',
titlePrefix: 'Application Components',
},
{
directory: '../src/components/ui',
titlePrefix: 'UI Kit',
},
],
Example: a Button story
Colocate the story with the primitive and import it through the @/ alias. Mirror the component’s real variants — Ship’s Button exposes default, destructive, outline, secondary, ghost, and link, with default, sm, lg, and icon sizes:
src/components/ui/button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from '@/components/ui/button';
const meta = {
component: Button,
args: {
children: 'Button',
variant: 'default',
size: 'default',
},
argTypes: {
variant: {
options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'],
control: { type: 'radio' },
},
size: {
options: ['default', 'sm', 'lg', 'icon'],
control: { type: 'radio' },
},
},
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof Button>;
export const Basic: Story = {};
Stories render in isolation, so they pick up your Tailwind theme tokens only if the global stylesheet is loaded. Import src/globals.css in .storybook/preview.ts to get the same bg-background / text-foreground tokens you see in the app.