Join live session: Top 8 Storybook myths holding your team back
Docs
Storybook Docs

Contributing a Storybook framework

A Storybook framework is a node package that enables out-of-the-box support for either a metaframework (Next.js, NuxtJS, SvelteKit) or a combination of builder (Webpack, Vite) plus renderer (React, Angular, Vue, web components, etc).

For metaframeworks, the Storybook framework also takes care of additional configuration necessary to make Storybook behave similarly to apps generated by the metaframework. For example, @storybook/nextjs recreates or mocks a number of features of Next.js apps inside Storybook.

For your reference, you can view all of the official Storybook frameworks, including their full source code and documentation.

How to make a framework

1. Decide on a package name

The name should start with storybook-framework- and then correspond to what your framework supports. For example, a framework targeting SvelteKit would be storybook-framework-svelte-kit and a framework targeting Stencil with Vite would be storybook-framework-stencil-vite. When not targeting a metaframework, the naming convention is storybook-framework-<renderer>-<builder>.

2. Consider what your framework will need to do

The goal is to make Storybook behave—out-of-the-box—as similarly as possible to the metaframework or builder-renderer combination you’re targeting.

For metaframeworks, this means attempting to recreate any builder or babel configuration provided by the metaframework. You should try to do so in a way that respects the user's existing project configuration as much as possible.

The library or libraries your framework supports may have different major versions available. Consider which versions of each library your framework will support. You will need to account for the changes within those different versions or split your framework into different versions/packages itself to support each library version. To speed up maintenance, please consider adding integration tests for the various library versions your framework supports.

3. Write the documentation

Before writing any code, write a helpful README that contains installation instructions and a list of available features. Use the README for @storybook/nextjs as a template. Writing the documentation first helps guide your other work.

4. Author the framework itself

A framework can contain the following parts:

package.json (example)

Because a framework is a node package, it must contain a package.json file. Here’s a template you can use to start:

package.json template
{
  "name": "<your-framework-name>",
  "version": "1.0.0",
  "description": "Storybook for <meta-framework-name> or <renderer> & <builder>",
  "keywords": [
    "Storybook",
    "<meta-framework-name>",
    "<renderer>",
    "<builder>",
    "<anything>",
    "<else>",
    "<relevant>"
  ],
  "homepage": "<your package's homepage>",
  "bugs": {
    "url": "https://github.com/<your-org>/<your-repo>/issues"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/<your-org>/<your-repo>.git",
    "directory": "<path/to/your/framework>"
  },
  "license": "MIT",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "require": "./dist/index.js",
      "import": "./dist/index.mjs"
    },
    "./preset": {
      "types": "./dist/preset.d.ts",
      "require": "./dist/preset.js",
      "import": "./dist/preset.mjs"
    },
    "./preview.js": {
      "types": "./dist/preview.d.ts",
      "require": "./dist/preview.js",
      "import": "./dist/preview.mjs"
    },
    "./package.json": "./package.json"
  },
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "files": ["dist/**/*", "types/**/*", "README.md", "*.js", "*.d.ts"],
  "scripts": {
    "check": "tsc --noEmit",
    "test": "..."
  },
  "dependencies": {
    "@storybook/addons": "^7.0.0",
    "@storybook/core-common": "^7.0.0",
    "@storybook/node-logger": "^7.0.0",
    "@storybook/<builder>": "^7.0.0",
    "@storybook/<renderer>": "^7.0.0"
  },
  "devDependencies": {
    "typescript": "x.x.x",
    "<meta-framework>": "^x.x.x",
    "<builder>": "^x.x.x"
  },
  "peerDependencies": {
    "@babel/core": "^x.x.x",
    "@storybook/addon-actions": "^7.0.0",
    "<meta-framework>": "^x.x.x || ^x.x.x",
    "<renderer>": "^x.x.x || ^x.x.x",
    "<builder>": "^x.x.x"
  },
  "engines": {
    "node": ">=16"
  },
  "publishConfig": {
    "access": "public"
  }
}

A few notes on some of those properties:

  • exports: The root, ./preset, and package.json exports are required. If your framework has a preview.js, then that is required as well.
  • types: We strongly encourage you to author your framework in TypeScript and distribute the types.
  • dependencies and devDependencies: These are just examples. Yours may look quite different.
  • peerDependencies: If your framework provides support for multiple versions of the libraries you’re targeting, be sure that is represented here.

preset.js (example)

The preset API is where you will configure the Storybook core (which builder and renderer are used by your framework), the builder (via either the webpackFinal or viteFinal export), babel (via the babel export), any necessary addons, and any available options for your framework.

preview.js (example)

The (optional) preview API is where you configure the rendering of stories, such as global decorators or initializing some runtime config needed for your framework to behave as expected. If your framework requires this file, note that you also need to configure the previewAnnotations in preset.js.

types.ts (example)

If you author your framework in TypeScript (recommended), you should export the type for StorybookConfig which reflects the available options of your framework.

5. Test your framework

Test it in a fresh project using a Storybook set up as close as possible to your framework. For example, for @storybook/nextjs, which uses React and Webpack5, start with a project that uses @storybook/react and @storybook/builder-webpack5. Follow the installation instructions from your README and ensure everything works as expected. Remember to test the various versions, configs, and options for the libraries you’re supporting.

6. Let us know!

Once it's fully tested and released, please let us know about your framework by either announcing it in the #showcase Discord channel or tweeting it and mentioning @storybookjs. It's our hope that well-made community frameworks can eventually move into the Storybook codebase and be considered "officially" supported.

Learn more about contributing to Storybook

  • RFC process for authoring feature requests
  • Code for features and bug fixes
  • Frameworks to get started with a new framework
  • Documentation for documentation improvements, typos, and clarifications
  • Examples for new snippets