Storybook Story Builder

Generate a Storybook CSF story file for a React or Vue component

Create a Storybook Component Story Format (CSF3) file with a typed Meta default export, a StoryObj type, and multiple named story exports each carrying args for common component states like primary, disabled, and large. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is CSF3 and how is it different from older formats?

Component Story Format 3 represents each story as an object with args rather than a render function. It is less boilerplate than CSF2, supports automatic controls from args, and is the recommended format in modern Storybook.

Storybook stories without retyping the boilerplate

Storybook documents a component by rendering it in different states, each one a “story”. In the modern Component Story Format (CSF3), a file exports a typed Meta default and then one object per state with args. The shape is mechanical, so this builder generates it from a component name and a list of states.

How it works

The tool writes a .stories.tsx file. It imports Meta and StoryObj types from the framework package (@storybook/react or @storybook/vue3), imports your component, and exports a const meta: Meta<typeof Component> default with the title and component set plus tags: ['autodocs']. It defines type Story = StoryObj<typeof Component> and then emits one export const Name: Story = { args: { ... } } per state you list. Common states (Primary, Secondary, Disabled, Large) get sensible default args; any custom names get an empty args object for you to fill.

Generated file structure

import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "./Button";

const meta: Meta<typeof Button> = {
  title: "Components/Button",
  component: Button,
  tags: ["autodocs"],
};
export default meta;

type Story = StoryObj<typeof Button>;

export const Primary: Story = { args: { variant: "primary", label: "Button" } };
export const Disabled: Story = { args: { disabled: true, label: "Button" } };
export const Large: Story = { args: { size: "large", label: "Button" } };

Drop this file next to your component as Button.stories.tsx and it appears in the Storybook sidebar immediately.

CSF3 vs earlier formats

In CSF2 (Storybook 6), stories were functions: export const Primary = (args) => <Button {...args} />. In CSF3, a story is just an object with an args property, and Storybook handles the rendering. This removes the render function boilerplate from every story, keeps files shorter, and enables Storybook’s Controls addon to auto-generate an interactive props panel — since the args are plain data, not embedded in a function.

The Meta default export changed in CSF3 to be typed directly as Meta<typeof Component>. This gives full TypeScript inference on argTypes and the component’s own prop types, catching errors when you reference a prop that does not exist.

Choosing your stories

Each story should represent a distinct, meaningful state of the component — not just every combination of props. A useful starting set for most components:

  • Primary / Default: The most common usage, as it appears in the app.
  • Disabled: The state when the component is non-interactive.
  • Loading / Pending: Relevant for async components.
  • Error / Invalid: The error state, for form inputs and similar.
  • Empty: For list components, the zero-items case.

Avoid stories that only change a colour or a label when the variant prop does not change behaviour — those are better covered by Controls, which lets you explore prop combinations interactively without separate named exports.

Organising the sidebar

The title string uses slashes to create a folder hierarchy. A consistent convention keeps a large component library navigable:

  • Components/Button — general UI primitives
  • Forms/TextField — form-specific components
  • Layouts/PageShell — layout wrappers
  • Features/PaymentCard — product-specific components

Put only the props that change per story in each story’s args; shared defaults belong in meta.args so they apply across every story without repetition.