Storybook 9.0 ‘Mercury’ Removes @storybook/addon-docs Default — New Autodocs Flag Guide
10 mins read

Storybook 9.0 ‘Mercury’ Removes @storybook/addon-docs Default — New Autodocs Flag Guide

Event date: March 10, 2026 — storybookjs/storybook 9.0.0


Storybook 9.0 ‘Mercury’ ships without @storybook/addon-docs in the default install. If you run npx storybook@latest upgrade on an existing 8.x project and your MDX pages start 404-ing, this is why. The package was not deleted — it was decoupled. @storybook/addon-essentials, the umbrella that used to pull docs in automatically, has been retired in the Mercury release, and the autodocs configuration you used to write in main.js has moved elsewhere.

The replacement is a tag-based system: tags: ['autodocs'] lives in preview.js, and individual stories opt in by applying the same tag in the story’s meta. The storybook 9.0 mercury autodocs change is small in terms of lines of code, but the migration path bites teams who keep a lot of MDX around, especially design-system monorepos with deep dependency graphs on the old @storybook/addon-docs block components.

Official documentation for storybook 9.0 mercury autodocs

Straight from the source.

The snapshot above reflects the current state of the addon-docs migration guide on storybook.js.org. The package now installs through npx storybook add @storybook/addon-docs rather than arriving for free with @storybook/addon-essentials, and the block exports moved one directory deeper into the /blocks subpath.

Why the Mercury release pulled addon-docs out of core

The Storybook team’s 9.0 launch post emphasises a lighter manager bundle as one of the headline improvements. A big chunk of that weight came from addon-essentials, which was dragging MDX parsers, the docs blocks library, and the React-specific docgen generator into every install — even for teams who never wrote a single .mdx file. Mercury splits those responsibilities: the docs surface is now opt-in, the test runtime lives under storybook/test, and the controls/actions/toolbars addons were folded into core with paths like storybook/actions.

If your .storybook/main.js previously looked like this:

More detail in Storybook stories not loading.

// Storybook 8.x
export default {
  stories: ['../src/**/*.stories.@(js|jsx|mdx|ts|tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
  ],
  docs: {
    autodocs: 'tag',
  },
};

The 9.0 upgrade script rewrites it to drop the removed addons and update the autodocs configuration:

// Storybook 9.0 'Mercury'
export default {
  stories: ['../src/**/*.stories.@(js|jsx|mdx|ts|tsx)'],
  addons: [
    '@storybook/addon-docs', // only if you want MDX or Autodocs
  ],
};

The addon-essentials-remove-docs automigration shipped in the 9.0 CLI does most of this for you. It scans package.json and removes the consolidated packages. Teams running a custom CI wrapper around storybook upgrade should still read the diff — the script also touches preview.js, and if you have a shared config package exporting a preview object, the automigration can’t always follow the import chain.

How do I turn autodocs back on in 9.0?

Autodocs now lives in preview.js as a tag on the global preview object. Once @storybook/addon-docs is installed via npx storybook add @storybook/addon-docs, add this to enable it for every story in the project:

// .storybook/preview.ts
import type { Preview } from '@storybook/react-vite';

const preview: Preview = {
  tags: ['autodocs'],
  parameters: {
    controls: { matchers: { color: /(background|color)$/i } },
  },
};

export default preview;

Tags cascade from project to component to story, so the single-line change reproduces the old project-wide autodocs behaviour. If you preferred the opt-in pattern — only stories explicitly marked with the tag get a docs page — leave the project-level array empty and apply tags: ['autodocs'] in the meta object of specific stories:

A related write-up: build tool safety tradeoffs.

// Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  component: Button,
  tags: ['autodocs'], // only this component gets a docs page
};
export default meta;

export const Primary: StoryObj<typeof Button> = {
  args: { primary: true, label: 'Go' },
};

Per-component opt-out works by keeping the project-level tags array empty and only applying the autodocs tag to the specific components you want documented. This inverts the relationship compared with the old boolean flag: instead of turning the generator on globally and suppressing it per component, you turn it on per component. For the full list of tag behaviours supported by your installed version, consult the tags reference in the Storybook docs.

Block import paths changed — expect build failures

This is the part the automigration doesn’t always catch. In 8.x, you imported MDX blocks from the root of the package:

// 8.x
import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs';

In 9.0, every block export moved to a subpath:

Vite and Rolldown internals goes into the specifics of this.

// 9.0 Mercury
import { Meta, Story, Canvas, Controls } from '@storybook/addon-docs/blocks';

If you skip this, the build fails with a cryptic error because the root of @storybook/addon-docs is now a preset — not a module that exports React components. The failure surfaces at MDX compile time, not at storybook dev startup, which makes it easy to miss in CI if you only smoke-test the dev server. A fast ripgrep-plus-sed pass across your .mdx files and any *.stories.@(ts|tsx) files that import blocks directly covers the common case:

rg -l "from '@storybook/addon-docs'" -g '!node_modules' \
  | xargs sed -i '' "s|from '@storybook/addon-docs'|from '@storybook/addon-docs/blocks'|g"

(Drop the empty string after -i on GNU sed.) If you’re in a monorepo with a shared MDX toolkit package, the export path also changed in any re-export file — grep those separately, because a re-export like export * from '@storybook/addon-docs' in a workspace package will silently produce an empty module in 9.0 and break every consumer.

Topic diagram for Storybook 9.0 'Mercury' Removes @storybook/addon-docs Default — New Autodocs Flag Guide
Purpose-built diagram for this article — Storybook 9.0 ‘Mercury’ Removes @storybook/addon-docs Default — New Autodocs Flag Guide.

The diagram above sketches the 9.0 package layout: storybook as the core runtime at the centre, @storybook/addon-docs as an opt-in peer with its /blocks subpath for MDX components, and the retired @storybook/addon-essentials replaced by direct imports to storybook/actions, storybook/test, and the controls runtime folded into core. The shape is flatter than 8.x and reflects how the Mercury release moved from a bundle-everything-by-default model to a pay-for-what-you-use model.

What does turning Autodocs on cost at build time?

Autodocs is not free. Every component carrying the tag gets a generated MDX page at build time, which runs react-docgen (or react-docgen-typescript for TS projects), parses the component, and renders a full interactive Canvas for each story under that component. On a design system with a few dozen components that cost is invisible. On a large monorepo with 400+ tagged stories it shows up clearly in storybook build wall-clock time.

Benchmark: Storybook Build Time: Autodocs Off vs On
Results across Storybook Build Time: Autodocs Off vs On.

The benchmark chart above captures a typical pattern: build times with autodocs off stay roughly flat with component count, while build times with autodocs on grow close to linearly as the docs generator works through each tagged component. For teams that only need docs for public-facing design-system primitives, the practical recommendation is: keep the project-level tag empty, apply tags: ['autodocs'] in the meta of the components you actually want documented, and keep implementation-detail stories (story fixtures, visual regression setups, accessibility permutations) out of the generated docs. That bounds the Canvas renders to a small set and keeps CI times predictable.

A related write-up: build performance deep dive.

When build time is dominated by docgen rather than the render itself, consult the official migration guide for the currently supported configuration keys in main.js that control how component props are parsed. Most projects don’t need the TypeScript-aware parser for autodocs pages to look right — the default handling infers enough from plain interface declarations for props.

Community reaction and the rough edges worth knowing

Migration-week Reddit and GitHub traffic on the storybook 9.0 mercury autodocs change has clustered around two recurring issues: teams hitting the block import path failure in production CI, and edge cases where external preview objects imported from a shared package don’t have their tags field picked up.

Reddit top posts about storybook 9.0 mercury autodocs
Live data: top Reddit posts about “storybook 9.0 mercury autodocs” by upvotes.

The Reddit snapshot above shows the mix — the highest-voted threads are practical migration posts (“what the automigration missed”), not complaints about the direction of the change. For the external-preview case, the workaround that teams have converged on is to inline the tags array in preview.js itself rather than spreading it from an import, because Storybook’s static analyser reads preview.js directly and does not always follow import chains for the tags field. Check the storybookjs/storybook issue tracker for the current status of any open reports matching your symptoms before filing a new one.

Related: maintainable JavaScript habits.

The other rough edge worth flagging: if you had autodocs disabled globally in 8.x, the automigration removes the old key but doesn’t add an equivalent suppression at the project level in 9.0, because the default tag set is empty and the result is generally equivalent. That’s correct, but some teams have a shared preview module that pre-populates tags: ['autodocs'], and the removal of the old suppression can silently re-enable the generator. After running the 9.0 automigration, grep every shared preview export for tags: and verify the cascade is what you expected.

The short version for anyone upgrading this week: install @storybook/addon-docs explicitly, move autodocs control from main.js to tags: ['autodocs'] in preview.js, rewrite every import of MDX blocks to @storybook/addon-docs/blocks, and re-run storybook build in CI rather than trusting a local storybook dev pass. The whole migration is usually under an hour for a single-package project and a half day for a monorepo — the failure modes are loud once you actually exercise the build.

For a different angle, see ESM migration pain.

You might also find modern JavaScript patterns useful.

Leave a Reply

Your email address will not be published. Required fields are marked *