---
title: Storybook
description: Learn how to use Storybook in a Turborepo.
product: turborepo
type: integration
summary: Set up Storybook for developing and documenting UI components in your monorepo.
related:
  - /docs/guides/tools/tailwind
  - /docs/guides/tools/shadcn-ui
  - /docs/guides/tools/typescript
---

# Storybook

<CopyPrompt
  title="Set up Storybook in a Turborepo"
  prompt={
  "Set up Storybook in this Turborepo.\n1) Create a Storybook app\n2) Connect it to the UI package\n3) Set up turbo.json tasks\n\nWalk me through each step."
}
/>

[Storybook](https://storybook.js.org/) is a popular way to build UI components in an isolated environment. By putting Storybook into your Turborepo, you can easily develop your design system right alongside your applications.

Quickstart [#quickstart]

If you'd rather use a template, this guide is walking through how to build [this Storybook/Turborepo template](https://vercel.com/templates/react/turborepo-design-system) on Vercel.

<PackageManagerTabs>
  <Tab value="pnpm">
    ```bash title="Terminal"
    pnpm dlx create-turbo@latest -e design-system
    ```
  </Tab>

  <Tab value="yarn">
    ```bash title="Terminal"
    yarn dlx create-turbo@latest -e design-system
    ```
  </Tab>

  <Tab value="npm">
    ```bash title="Terminal"
    npx create-turbo@latest -e design-system
    ```
  </Tab>

  <Tab value="bun">
    ```bash title="Terminal"
    bunx create-turbo@latest -e design-system
    ```
  </Tab>
</PackageManagerTabs>

Guide [#guide]

<Steps>
  <Step>
    Create a monorepo [#create-a-monorepo]

    If you don't have an existing project, use [create-turbo](/docs/getting-started/installation) to create a new monorepo:

    <PackageManagerTabs>
      <Tab value="pnpm">
        ```bash title="Terminal"
        pnpm dlx create-turbo@latest
        ```
      </Tab>

      <Tab value="yarn">
        ```bash title="Terminal"
        yarn dlx create-turbo@latest
        ```
      </Tab>

      <Tab value="npm">
        ```bash title="Terminal"
        npx create-turbo@latest
        ```
      </Tab>

      <Tab value="bun">
        ```bash title="Terminal"
        bunx create-turbo@latest
        ```
      </Tab>
    </PackageManagerTabs>
  </Step>

  <Step>
    Create a directory for the app [#create-a-directory-for-the-app]

    You'll need a directory for the Storybook application:

    ```bash title="Terminal"
    mkdir apps/storybook
    cd apps/storybook
    ```
  </Step>

  <Step>
    Add the Storybook application [#add-the-storybook-application]

    In the `apps/storybook` directory, initialize a new Storybook application:

    <PackageManagerTabs>
      <Tab value="pnpm">
        ```bash title="Terminal"
        pnpm create storybook@latest
        ```
      </Tab>

      <Tab value="yarn">
        ```bash title="Terminal"
        yarn create storybook@latest
        ```
      </Tab>

      <Tab value="npm">
        ```bash title="Terminal"
        npm create storybook@latest
        ```
      </Tab>

      <Tab value="bun">
        ```bash title="Terminal"
        bun create storybook@latest
        ```
      </Tab>
    </PackageManagerTabs>

    Follow the prompts to create an application. For the rest of this guide, we'll assume React and TypeScript.

    <Callout type="info">
      After going through Storybook's onboarding, you can [uninstall the onboarding
      addon](https://github.com/storybookjs/addon-onboarding/blob/main/README.md).
    </Callout>
  </Step>

  <Step>
    Add your UI kit to Storybook [#add-your-ui-kit-to-storybook]

    Now, install your UI package into Storybook.

    <PackageManagerTabs>
      <Tab value="pnpm">
        ```bash title="Terminal"
        pnpm add @repo/ui --filter=storybook
        ```
      </Tab>

      <Tab value="yarn">
        ```bash title="Terminal"
        yarn workspace storybook add @repo/ui
        ```
      </Tab>

      <Tab value="npm">
        ```bash title="Terminal"
        npm install @repo/ui --workspace=storybook
        ```
      </Tab>

      <Tab value="bun">
        ```bash title="Terminal"
        cd apps/storybook && bun install @repo/ui
        ```
      </Tab>
    </PackageManagerTabs>
  </Step>

  <Step>
    Set up a story for your Button component [#set-up-a-story-for-your-button-component]

    Delete the stories and components found in `src/stories` that were created by the Storybook scaffolding tool. You will be making your own.

    As an example, here is a story for the `Button` component from `@repo/ui/button`.

    ```tsx title="./apps/storybook/src/stories/Button.stories.tsx"
    import type { Meta, StoryObj } from "@storybook/react";
    import { Button } from "@repo/ui/button";

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

    export default meta;
    type Story = StoryObj<typeof meta>;

    export const Primary: Story = {
      args: {
        appName: "Button",
        children: "I am a primary button.",
      },
    };
    ```
  </Step>

  <Step>
    Align scripts to your tasks [#align-scripts-to-your-tasks]

    Last, integrate the new Storybook application into your Turborepo:

    ```json title="apps/storybook/package.json"
    {
      "scripts": {
        "dev": "storybook dev -p 6006", // [!code highlight]
        "build": "storybook build" // [!code highlight]
      }
    }
    ```

    These scripts will now run with the `turbo dev` and `turbo build` tasks in your `turbo.json`.

    To ensure file outputs are cached when you run `build`, add `storybook-static` to the outputs of your `turbo.json` build task:

    ```diff title="turbo.json"
    {
      "tasks": {
        "build": {
          "outputs": [
            ".next/**",
            "!.next/cache/**"
    +       "storybook-static/**"
          ]
        }
      }
    }
    ```

    <Step>
      Add Storybook build outputs to .gitignore [#add-storybook-build-outputs-to-gitignore]

      Ensure that the build outputs for Storybook are not committed to source control

      ```diff title=".gitignore"
      + storybook-static
      ```
    </Step>

    <Step>
      Verify your configuration [#verify-your-configuration]

      Run `turbo build` to build the Storybook application alongside the rest of your applications.

      You can also run `turbo build` again to see cache hits for your builds.
    </Step>
  </Step>
</Steps>

More tips [#more-tips]

Co-locating stories [#co-locating-stories]

If you'd prefer to co-locate your stories to their source code (rather than having them in the Storybook application), you'll need some extra configuration.

<Steps>
  <Step>
    Re-configure Storybook sources [#re-configure-storybook-sources]

    In `.storybook/main.ts`, change the `stories` paths in `config` to the directories you'd like to capture. For instance, if you'd like to write stories in the UI package:

    ```diff title="./apps/storybook/.storybook/main.ts"

    const config = {
      stories: [
    -   "../src/**/*.mdx",
    -   "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
    +   "../../../packages/ui/src/**/*.stories.@(js|jsx|mjs|ts|tsx)",
    };
    ```
  </Step>

  <Step>
    Move story files to the UI package [#move-story-files-to-the-ui-package]

    Following along with [the guide above](/docs/guides/tools/storybook#set-up-a-story-for-your-button-component), move the `./apps/storybook/src/stories/Button.stories.tsx` file to `./packages/ui/src/Button.stories.tsx`.

    Update components imports so that they reference the now co-located modules. For instance, in the story's imports:

    ```diff title="./packages/ui/src/Button.stories.tsx"
    - import { Button } from "@repo/ui/button";
    + import { Button } from "./button";
    ```

    <Callout type="info">
      You may also need to update [absolute
      imports](/docs/guides/tools/typescript#use-nodejs-subpath-imports-instead-of-typescript-compiler-paths)
      according to your changes and usage.
    </Callout>

    You'll also need to install any Storybook packages required for writing stories. For example, moving the story from above would require that you install `@storybook/react` into your `@repo/ui` package.

    <PackageManagerTabs>
      <Tab value="pnpm">
        ```bash title="Terminal"
        pnpm add @storybook/react --filter=@repo/ui --save-dev
        ```
      </Tab>

      <Tab value="yarn">
        ```bash title="Terminal"
        yarn workspace @repo/ui add @storybook/react --dev
        ```
      </Tab>

      <Tab value="npm">
        ```bash title="Terminal"
        npm install @storybook/react --workspace=@repo/ui --save-dev
        ```
      </Tab>

      <Tab value="bun">
        ```bash title="Terminal"
        cd packages/ui && bun install @storybook/react --dev
        ```
      </Tab>
    </PackageManagerTabs>
  </Step>

  <Step>
    Configure caching [#configure-caching]

    Because stories are now in the UI package, changes to those stories can cause cache misses for any builds that depend on your UI package. However, changing a story doesn't mean your production applications should miss cache.

    To prevent this, exclude stories from the inputs to your `build` task in your root `turbo.json`. You'll also need to create a `build:storybook` task, which you'll need in a moment:

    ```json title="./turbo.json"
    {
      "tasks": {
        "build": {
          "dependsOn": ["^build"],
          "inputs": ["$TURBO_DEFAULT$", "!**/*.stories.{tsx,jsx,mdx}"], // [!code highlight]
          "outputs": [".next/**", "!.next/cache/**"]
        },
        "build:storybook": {} // [!code highlight]
      }
    }
    ```

    Additionally, create a [Package Configuration](/docs/reference/package-configurations) in the `storybook` application so stories are **accounted for in building the Storybook application, specifically**:

    ```json title="./apps/storybook/turbo.json"
    {
      "extends": ["//"],
      "tasks": {
        "build:storybook": {
          "dependsOn": ["^build:storybook"],
          "outputs": ["storybook-static/**"]
        }
      }
    }
    ```

    <Callout type="info">
      If you are using the [Compiled Package
      pattern](/docs/core-concepts/internal-packages#compiled-packages), you may
      also need to add `^build` to your `dependsOn`.
    </Callout>
  </Step>

  <Step>
    Rename the build script [#rename-the-build-script]

    Last, make sure your script to build Storybook uses the configuration we just wrote by renaming it to the name of the task:

    ```json title="apps/storybook/package.json"
    {
      "scripts": {
        "dev": "storybook dev -p 6006",
        "build:storybook": "storybook build" // [!code highlight]
      }
    }
    ```

    The script that was once `"build"` is now `"build:storybook"` to ensure the stories are included in hashes for caching.
  </Step>

  <Step>
    Verify your configuration [#verify-your-configuration-1]

    To ensure your setup is correct:

    1. Run `turbo build:storybook build`. You should see cache misses.
    2. Run `turbo build:storybook build` again. You should see all cache hits.
    3. Make a code change **to a story** in your `@repo/ui` package.
    4. Run `turbo build:storybook build` again. You should **only** see a cache miss for the Storybook application. All others should hit cache.
  </Step>
</Steps>

Adding CSS [#adding-css]

If your UI package exports its own CSS, you'll need to add it to the renders in the Storybook app, similar to how you would add it to your applications. [The Storybook documentation](https://storybook.js.org/docs/configure/styling-and-css#css) recommends you add it to the `.storybook/preview.ts` file.

---

[View full sitemap](/sitemap.md)