How to publish a Storybook addon
Share your Storybook addon with the community
In the last post, you got an overview of the addon APIs and built your first addon. To share this addon with other Storybook users, you need to package and publish it.
The Addon Catalog is the home of all Storybook addons. Itβs where we showcase your addons and how developers discover new ones. This post shows you how to prepare your addon for release, package it up, and publish it to the catalog.
Preparing your addon for release
Storybook addons, like most packages in the JavaScript ecosystem, are distributed via npm. However, they have certain criteria:
- Have a
dist
directory containing transpiled ES5 code - A
preset.js
file at the root level, written as an ES5 module - A
package.json
file that declares:- Peer-dependencies
- Module related info
- Catalog metadata
Letβs go through and tackle these one by one.
Build system
Youβre likely to write your addon code using ES6 and rely on features like JSX. Therefore, the addon code needs to be transpiled down to ES5. There are many ways to do this. My recommendation is to set up a build system using the Babel CLI. You can install it by running:
npm install --save-dev @babel/core @babel/cli
Babel is a flexible tool. It transpiles all kinds of new JavaScript features or framework specific features into ES5. We rely on predefined and community managed Babel presets to manage all these features for us.
npm install --save-dev @babel/preset-env @babel/preset-react
Here, preset-env
is responsible for the latest JavaScript features and preset-react
manages React specific features such as transforming JSX. Add a .babelrc.js
at the root of your project and configure it to use these presets.
// .babelrc.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
};
And letβs define a few build related scripts.
// package.json
"scripts": {
"clean": "rimraf ./dist",
"build": "babel ./src --out-dir ./dist",
"storybook": "start-storybook -p 6006",
"start": "concurrently \"npm run storybook\" \"npm run build -- --watch\"",
...
},
Running npm run build
will output the ES5 code to the dist
directory. While running npm start
will run the Babel CLI in watch mode and simultaneously start Storybook. The watch mode is super handy for local development. On every save itβll rebuild the addon and refresh Storybook.
Root level preset
The second requirement is to have a root level preset. Our addon uses a preset, defined at src/preset.js
. Letβs create a preset.js
file at the root of the project which uses the dist
output instead:
// preset.js
module.exports = require('./dist/preset');
You should also update the Storybook config to use this root level preset.
// .storybook/main.js
module.exports = {
stories: [
'../stories/**/*.stories.mdx',
'../stories/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: ['@storybook/addon-essentials', '../preset.js'],
};
Module Metadata
Next, we need to declare a few key pieces of information about the addon in the package.json
file. This includes the main entry point for the module and which files to include when you publish the addon. And any peer-dependencies that you might have β at the very least react
and react-dom
.
// package.json
"main": "dist/preset.js",
"files": [
"dist/**/*",
"README.md",
"*.js"
],
"dependencies": {
"@storybook/addons": "^6.0.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0",
"react-dom": "^16.8.0 || ^17.0.0"
}
Why peer-dependencies? Letβs say you are building a form library that works with React. If you include React as a dependency then the React code will be packaged along with your library. Your users already install React within their codebase. If that happens to be a different version then, itβll cause their app to break. Itβs the same idea here.
Catalog Metadata
Along with the module related info you also need to specify some metadata for the Storybook Addon Catalog.
Some of this info might already be available in package.json
since you need to provide that to npm. For example, the addon name, description, author info. The rest is provided via the storybook property. Things like a display name, icon or a list of supported or unsupported frameworks. For the complete specification of the metadata API check out the Addon metadata documentation.
// package.json
"name": "storybook-addon-outline",
"version": "1.0.0",
"description": "A storybook addon for visually debugging CSS layout and alignment",
"author": "winkerVSbecks",
"storybook": {
"displayName": "Outline",
"unsupportedFrameworks": ["react-native"],
"icon": "https://yoursite.com/outline-icon.png",
},
"keywords": [
"storybook-addons",
"style",
"outline",
"css",
"layout",
"debug"
],
The keywords property here maps to catalog tags. For example, the storybook-addons
tag ensures that your addon will get into the catalog. And appearance
is a top-level category. The rest help with searchability of your addon.
Publishing to NPM
Letβs quickly review what weβve done so far. We set up a build system to transpile the addon code to ES5. Added a root level preset. And defined module and catalog related info in the package.json file. The last step is to actually publish the addon.
The addon will be published to the npm registry. Ensure that you have signed up for an npm user account and run:
npm version 1.0.0 -m "Created first version of the Outline addon: %s"
npm publish
There you have it! Weβve successfully published our package to npm and released our first Storybook Addon. You can check out the official Outline addon in the catalog.
Conclusion
Addons help the community customize and automate Storybook. Publish your addon to share it with thousands of devs. Iβm excited to see what you build!
Note, there may be a delay in your addon showing up in the catalog because it crawls npm. If your addon isnβt showing up, please file an issue on the catalog repo.
For a deep dive into package publishing, checkout the Distribute UI across an organization chapter from Design Systems for Developers. It covers topics such as generating changelogs and automating releases.