{"owner":"storybookjs","repo":"storybook","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".cursorrules"],"skills":{"AGENTS.md":"# Storybook Agent Instructions\n\nKeep this file, `AGENTS.md`, up to date when Storybook's architecture, tooling, workflows, or contributor guidance changes.\n\nThis file is the canonical instruction source for coding agents. Files like `CLAUDE.md` should point here instead of duplicating instructions.\n\n## Repository Overview\n\nStorybook is a large TypeScript monorepo. The git root is the repo root, the main code lives in `code/`, and build tooling lives in `scripts/`. The default branch is `next`.\n\n- **Base branch**: `next` (all PRs should target `next`, not `main`)\n- **Node.js**: `22.22.3` (see `.nvmrc`) — supports `.ts` natively via type stripping (no loader needed)\n- **Package Manager**: Yarn Berry\n- **Task orchestration**: NX plus the custom `yarn task` runner\n- **Linting**: oxlint (root `.oxlintrc.json`, extended by `code/.oxlintrc.json` and `scripts/.oxlintrc.json`; custom rules load via `jsPlugins`). ESLint is no longer used for repo linting — `code/lib/eslint-plugin` remains as the published `eslint-plugin-storybook` package.\n- **Formatting**: oxfmt (root `.oxfmtrc.json`)\n- **CI environment**: Linux and Windows\n- **TS execution**: Migrating from `jiti` to native `node` for running `.ts` files. New scripts should use `node ./path/file.ts` with explicit `.ts` import extensions (enabled by `allowImportingTsExtensions` in tsconfig). Legacy scripts still use `jiti` but should be migrated over time.\n- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).\n\n## Repository Structure\n\n```text\nstorybook/\n├── .github/                      # GitHub configs and workflows\n├── .nx/                          # NX workflow state\n├── code/                         # Main codebase\n│   ├── .storybook/               # Internal Storybook UI config\n│   ├── core/                     # Core package published as \"storybook\"\n│   ├── addons/                   # Core addons\n│   ├── builders/                 # Builder integrations\n│   ├── renderers/                # Renderer integrations\n│   ├── frameworks/               # Framework integrations\n│   ├── lib/                      # Supporting libraries\n│   ├── presets/                  # Webpack-oriented presets\n│   └── sandbox/                  # Internal build artifacts\n├── scripts/                      # Build and development scripts\n├── docs/                         # Documentation\n├── test-storybooks/              # Test repos\n└── ../storybook-sandboxes/       # Generated sandboxes outside repo\n```\n\n## Architecture\n\n### Renderer vs builder vs framework\n\n| Concept   | Role                                  | Example                   |\n| --------- | ------------------------------------- | ------------------------- |\n| Renderer  | Mounts UI framework to the DOM        | `@storybook/react`        |\n| Builder   | Bundles and serves Storybook          | `@storybook/builder-vite` |\n| Framework | Renderer + builder + framework config | `@storybook/react-vite`   |\n\n### Core package\n\nThe main package is `code/core/src/`. The most important areas are:\n\n- `core-server/` for dev server, static build, and presets\n- `manager/` and `manager-api/` for the Storybook UI\n- `preview/` and `preview-api/` for story rendering\n- `channels/` for manager <-> preview communication\n- `csf-tools/` for AST-based story indexing\n- `common/` for shared Node.js utilities\n- `test/` and `instrumenter/` for testing support\n\nPublic exports include:\n\n- `storybook/actions`\n- `storybook/preview-api`\n- `storybook/manager-api`\n- `storybook/theming`\n- `storybook/test`\n\nInternal exports include:\n\n- `storybook/internal/core-server`\n- `storybook/internal/csf-tools`\n- `storybook/internal/common`\n- `storybook/internal/channels`\n\n### Key flow\n\n- `.storybook/main.ts` is loaded at startup\n- `.storybook/preview.ts` is bundled into preview (TSX for React-based frameworks)\n- `.storybook/manager.ts` is bundled into manager\n- `*.stories.*` files are indexed by AST before runtime\n- Story selection loads the module, prepares the story, and renders it\n\nAST indexing keeps the sidebar fast and prevents one broken story file from breaking the whole UI.\n\n### Open services and toolsets\n\n- Open services own internal state, synchronization, queries, commands, and loading. Toolsets expose\n  capabilities to agents through MCP and the `storybook tools` CLI.\n- Definitions live under `code/core/src/shared/open-service/`; addons may own and register their own\n  toolsets, as addon-vitest does for `test`.\n- Register services and toolsets from the same `services` preset hook and behind the same feature\n  gate. Missing or duplicate registrations fail loudly.\n- Read `code/core/src/shared/open-service/README.md` before changing the contract, adapters,\n  registration, docs access, transport rendering, or tools CLI.\n\n### Agent-facing skills\n\n- `storybook skills` serves the `stories`, `write-story`, and `setup` documents as Markdown.\n- Pure content lives in `code/core/src/cli/skills/content/` and is exported through\n  `storybook/internal/skills`; addon-mcp consumes the same builders.\n- Keep `cli/skills/**` independent of `cli/ai/**`, and keep `cli/skills/content/**` independent of\n  `core-server`. Lint rules enforce both boundaries.\n\n## Common Commands\n\nRun commands from the repository root unless stated otherwise.\n\nFor routine agent work, prefer the faster non-production commands first. Add `-c production` only when you need sandbox-related NX tasks or you are explicitly matching CI behavior.\n\n### Install and compile\n\n```bash\nyarn\nyarn task compile\nyarn nx run-many -t compile\nyarn nx compile <nx-project-name>\n```\n\n### Lint and typecheck\n\n```bash\nyarn lint\nyarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix\nyarn task check\nyarn nx run-many -t check\n```\n\n### Development and tests\n\n```bash\ncd code && yarn storybook:ui\ncd code && yarn storybook:ui:build\nyarn test\nyarn test:watch\nyarn storybook:vitest\n```\n\n### Common task scenarios\n\n| Scenario                        | Command                                                                        |\n| ------------------------------- | ------------------------------------------------------------------------------ |\n| Compile everything quickly      | `yarn nx run-many -t compile`                                                  |\n| Compile one project             | `yarn nx compile <nx-project-name>`                                            |\n| Check TypeScript errors quickly | `yarn nx run-many -t check`                                                    |\n| Start the internal Storybook UI | `cd code && yarn storybook:ui`                                                 |\n| Build the internal Storybook UI | `cd code && yarn storybook:ui:build`                                           |\n| Run unit tests                  | `yarn test`                                                                    |\n| Run Storybook Vitest tests      | `yarn storybook:vitest`                                                        |\n| Generate a sandbox              | `yarn task sandbox --template react-vite/default-ts --start-from auto`         |\n| Run sandbox E2E tests           | `yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto`   |\n| Run sandbox test-runner tests   | `yarn task test-runner-dev --template react-vite/default-ts --start-from auto` |\n| Run the docgen perf bench       | `yarn workspace @storybook/docgen-harness bench:docgen-perf`                   |\n| Run the docgen memory gate      | `yarn workspace @storybook/docgen-harness bench:docgen-memory`                 |\n| Verify sandbox docgen baselines | `yarn workspace @storybook/docgen-harness baselines:sandbox`                   |\n\n## NX and `yarn task`\n\nUse NX when you want better caching and dependency tracking. Prefer these faster defaults first, and only add `-c production` or `--no-link` when you specifically need sandbox parity or CI-like behavior.\n\n```bash\n# Compile all packages\nyarn task compile\nyarn nx run-many -t compile\n\n# Check all packages\nyarn task check\nyarn nx run-many -t check\n\n# Run E2E tests for a template\nyarn task e2e-tests-dev --template react-vite/default-ts --start-from auto\nyarn nx e2e-tests-dev react-vite/default-ts -c production\n\n# Jump to a later step\nyarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts\nyarn nx e2e-tests-dev -c production --exclude-task-dependencies\n```\n\nKey points:\n\n- `-c production` is required for sandbox-related NX commands and CI-parity runs\n- `react-vite/default-ts` is the default sandbox template\n- `--no-link` is opt-in, not the default\n- NX handles task dependencies via `nx.json`\n- NX target commands use Nx project names (from `project.json` / Nx graph), not `package.json` names\n- Example: `yarn nx compile core` (project `core` is published as package `storybook`)\n- NX Cloud remote-cache auth failures (e.g. HTTP 401 \"insufficient access\") degrade to the local cache, so they are expected on local runs where `NX_CLOUD_ACCESS_TOKEN` is unset. CI always sets that token, so a 401 there means an invalid or expired token and should be investigated rather than ignored. A read-only token enables cache reads but cannot store artifacts, so the \"wasn't able to store\" warning is still expected with one\n\n## Sandbox Notes\n\nSandboxes are generated outside the repository at `../storybook-sandboxes/` by default.\n\n- `STORYBOOK_SANDBOX_ROOT=./sandbox` forces local output, but is usually not preferred\n- `./sandbox` inside the repo mainly exists for NX outputs, not CI sandboxes\n- If sandbox generation fails, fall back to `cd code && yarn storybook:ui`\n\nGenerate and use a sandbox with the same `sandbox` command shape used elsewhere in this file:\n\n```bash\nyarn task sandbox --template react-vite/default-ts --start-from auto\n# Same sandbox step via NX\nyarn nx sandbox react-vite/default-ts -c production\ncd ../storybook-sandboxes/react-vite-default-ts\nyarn install\nyarn storybook\n```\n\nCommon templates:\n\n- `react-vite/default-ts`\n- `react-webpack/default-ts`\n- `angular-cli/default-ts`\n- `svelte-vite/default-ts`\n- `vue3-vite/default-ts`\n- `nextjs/default-ts`\n\n## How To Work In This Repo\n\n### For normal code changes\n\n1. Install if needed: `yarn`\n2. Compile with NX: `yarn nx run-many -t compile`\n3. Make changes\n4. Recompile affected packages\n5. Validate there are no TypeScript errors with `yarn nx run-many -t check`\n6. Run relevant lint and tests\n7. Validate behavior in the internal Storybook UI first, then switch to sandbox or `-c production` flows only if you need template or CI parity\n\n### For addon, framework, or renderer work\n\n1. Edit the relevant package under `code/addons/`, `code/frameworks/`, or `code/renderers/`\n2. Recompile with NX, starting without `-c production`\n3. Generate a matching sandbox\n4. Run the relevant test-runner, E2E, or Storybook UI validation flow\n\n## Testing Expectations\n\n> [!IMPORTANT]\n> **For React components, write Storybook stories with `play` functions — do NOT write `*.test.tsx` unit tests.** Behavior, accessibility, and interaction assertions belong in `*.stories.tsx` co-located with the component, executed via the Storybook Vitest project (`yarn storybook:vitest` or `vitest run --config code/vitest.config.storybook.ts`). Unit tests (`*.test.ts(x)`) are reserved for pure utilities, hooks, and non-React modules where rendering is not involved.\n\n- Use `yarn storybook:vitest` to run Storybook story tests (the primary test path for components)\n- Use `yarn test` for unit tests of utilities, hooks, and non-React modules\n- Prefer focused unit-test runs during iteration — the full suite is large: `yarn test <pattern>` (e.g. `yarn test csf-tools`)\n- Use Storybook UI or Chromatic for visual validation\n- Use `yarn task e2e-tests --start-from auto` or `yarn task e2e-tests-dev --start-from auto` for E2E coverage\n- Use `yarn task test-runner --start-from auto` or `yarn task test-runner-dev --start-from auto` for test-runner scenarios\n- Use `yarn task smoke-test --start-from auto` for smoke checks\n\nWatch-mode commands:\n\n```bash\nyarn test:watch\nyarn storybook:vitest\n```\n\nWhen writing tests for components:\n\n- Add or update `<Component>.stories.tsx` with stories covering each behavior; use `play` functions with `expect`, `userEvent`, `within` from `storybook/test`\n- Mock external context (e.g. `ManagerContext.Provider`) inside story decorators or `beforeEach`\n- Run `vitest --config code/vitest.config.storybook.ts <story-file>` to verify play assertions\n\nWhen writing unit tests (utilities, hooks, non-React modules):\n\n- Export functions that need direct tests\n- Test real behavior, not just syntax patterns\n- Use coverage when useful: `yarn vitest run --coverage <test-file>`\n- Mock external dependencies like file system access and loggers\n- Use Node's path.resolve to wrap expected FS paths when writing path-related tests, so they work on Windows\n\n### Filesystem tests with `memfs`\n\nFor unit tests that touch `node:fs` / `node:fs/promises`, use [`memfs`](https://github.com/streamich/memfs) instead of real temp directories or wholesale `node:fs` mocks:\n\n- Import `vol` from `memfs` and call `vol.reset()` in `beforeEach`\n- Seed virtual files with `vol.fromNestedJSON({ '/absolute/path/file.json': '...' })` or memfs `writeFile` after redirecting spies\n- Use `vi.mock('node:fs/promises', { spy: true })` and, in `beforeEach`, point `mkdir` / `writeFile` / `readFile` at `memfs.fs.promises` (see `code/core/src/shared/open-service/server.test.ts`)\n- Assert disk state with `vol.toJSON()` when helpful\n\nDo **not** use `/tmp` paths or replace `node:fs/promises` with a full async factory mock unless a test file already standardizes on the spy redirect pattern above.\n\n### Globals in tests: never assign `globalThis.*` directly\n\n> [!IMPORTANT]\n> Under no circumstances may a test mutate a global by assigning it directly (e.g. `globalThis.FEATURES = {...}`, `globalThis.window = ...`, `global.fetch = ...`). Direct assignment leaks across tests and files — Vitest does not restore it — so it silently changes behavior in unrelated tests and creates order-dependent flakiness.\n\nUse Vitest's global stubbing instead, which is tracked and restorable:\n\n- Set a global with `vi.stubGlobal('FEATURES', { experimentalDocgenServer: true })`.\n- Restore in `afterEach(() => vi.unstubAllGlobals())` (or enable `unstubGlobals: true` in the Vitest config so it resets before each test automatically).\n- For a value used by every test in a file, stub it in `beforeEach` and unstub in `afterEach`; for a one-off override, call `vi.stubGlobal` inside that single test.\n- Never capture-and-restore by hand (`const original = globalThis.X; ... globalThis.X = original`); `vi.stubGlobal` + `vi.unstubAllGlobals()` does this correctly, including deleting keys that did not previously exist.\n\nThis applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).\n\n## Quality and Logging\n\nAfter changing files:\n\n1. **Always** format with `yarn fmt:write`, run from the `code/` directory (`cd code && yarn fmt:write`), once you are done editing. The repo uses `oxfmt`, so hand-written formatting will frequently be wrong — do not skip this step.\n2. Lint with `yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix` or `cd code && yarn lint:js:cmd <file-relative-to-code-folder>`\n3. Run relevant tests before submitting a PR\n\nUse Storybook loggers instead of raw `console.*` in normal code paths:\n\n- Server-side: `storybook/internal/node-logger`\n- Client-side: `storybook/internal/client-logger`\n\nFor TypeScript source in the repo, prefer explicit file extensions for relative code imports and exports such as `./foo.ts` or `./bar.tsx` when the target is another TS/JS module in this repository. Keep framework-specific component imports like `.vue` and `.svelte` in the form already expected by their package tooling.\n\nThe pre-commit hook automatically detects AI agents (via `std-env`) and switches from check-only to write mode, so formatting is auto-fixed when agents commit.\n\nAvoid `console.log`, `console.warn`, and `console.error` unless the file is isolated enough that importing the logger is not reasonable.\n\n## Troubleshooting\n\n- Build failures are often fixed by rerunning `yarn` and `yarn nx run-many -t compile`\n- Storybook UI uses port `6006` by default\n- Large compiles may require more Node.js memory\n- Sandbox paths are `../storybook-sandboxes/`, not `./sandbox` or `code/sandbox/`\n- Use `--debug` for verbose CLI output\n- Check generated sandbox directories and `.cache/` for build artifacts\n\n## Environment Variables\n\n| Variable                      | Purpose                                         |\n| ----------------------------- | ----------------------------------------------- |\n| `IN_STORYBOOK_SANDBOX`        | Set during sandbox creation                     |\n| `STORYBOOK_DISABLE_TELEMETRY` | Disable telemetry                               |\n| `STORYBOOK_TELEMETRY_DEBUG`   | Log telemetry events                            |\n| `DEBUG`                       | Enable debug logging                            |\n| `FIX_ON_COMMIT`               | Force autofix for fmt & lint in pre-commit hook |\n| `NX_CLOUD_ACCESS_TOKEN`       | Authenticate the NX Cloud remote cache          |\n\n## Commands To Avoid\n\n- **DO NOT RUN** `yarn task dev` without an explicit sandbox template\n- **DO NOT RUN** `yarn start`\n\nThese usually start long-running development servers and are the wrong default for agents.\n\n## Code Authoring Principles\n\nThese are recurring failure modes in agent-authored changes to this repo. Apply them when writing or reviewing code, not just when asked.\n\n- **Write comments only for the two reasons in [Comments and JSDoc](#comments-and-jsdoc).** That section is the rule; this list does not restate it.\n- **Verify environment assumptions empirically before encoding them.** If a design rests on \"the bundler strips X\" or \"this metadata is empty here\", prove it with a throwaway probe before building on it (and before writing it into a comment as fact). A 10-line experiment is cheaper than a wrong architecture.\n- **Encode assumptions with static checks first.** If an assumption is expected to always hold, prefer making it impossible via TypeScript types and existing lint rules. When static checks are not practical, add a cheap runtime assertion close to the boundary so violations fail loudly at the source.\n- **Avoid redundant tests already covered elsewhere.** Do not add tests for code patterns already guaranteed by TypeScript or linting, and do not duplicate coverage that already exists in Storybook `play` functions or Playwright tests.\n- **Test contracts (including side effects), not private implementation details.** It is valid to assert side effects when they are part of the public contract. Avoid assertions about internals that are not part of an exported contract, user-visible DOM output, or externally observable behavior.\n- **Bias toward broader coverage for security and migrations.** For security-sensitive code paths and legacy data migration logic, prefer handling more edge cases and documenting evidence for the chosen safeguards. Migration compatibility code should be explicitly version-scoped so it can be removed once the support window ends.\n- **Prefer deletion and simplicity over speculative generality.** No abstraction, fallback, or \"flexibility\" for a consumer or scenario that does not exist in this codebase today. If a change adds many lines, check whether the right change removes them.\n- **Don't commit accidental overrides to generated code.** Files like `code/core/src/manager/globals/exports.ts` are auto-generated, as stated in their JSDoc header. Only commit changes if they match changes you made on your PR, otherwise leave them untouched and flag flaky generated files in the PR description.\n\n## Comments and JSDoc\n\nCode should be self-explanatory. A comment is only justified when the code cannot explain itself (a non-obvious *why*) or when a public API needs explanation. Never comment to record that you did x, y, z.\n\nBefore writing or editing any code file, read [`.agents/guidelines/comments-and-jsdoc.md`](.agents/guidelines/comments-and-jsdoc.md) and follow it. Read it once per session, not once per file.\n\n## Maintenance Rules For Agents\n\n- Use this file as the canonical instruction source\n- Update `AGENTS.md` when architecture, commands, versions, release flows, or contributor guidance changes\n- Keep `CLAUDE.md` and other agent entrypoints as thin references to `AGENTS.md`\n- Do not reintroduce duplicated instruction files when a reference will do\n\n## Learned User Preferences\n\n- Prefer git worktrees for parallel or experimental work; keep the primary workspace clean and base feature branches on `origin/next`, not a dirty local `next`.\n- Prefer simplicity: avoid premature helpers and one-off abstractions; implement small logic inline when a shared helper is not clearly reused.\n- Keep e2e and long interaction tests as a readable continuous flow; do not force DRY with loops or heavy helpers when repetition is clearer.\n- For Storybook stories, put human-facing description in JSDoc above the `meta` const rather than a `description` parameter.\n- When renaming tools or APIs that emit telemetry, keep historical telemetry string names stable across Storybook versions unless the field is brand-new and has no existing data.\n",".cursorrules":"## Test Configuration\n\nThis Storybook repository uses Vitest as the test runner. Here are the key commands and configuration:\n\n### Test Scripts\n\n- `yarn test` - Run all tests (from root directory, delegates to `cd code; yarn test`)\n- `yarn test <test-name>` - Run focused tests matching the pattern\n- `yarn test:watch` - Run tests in watch mode\n- `yarn test:watch <test-name>` - Run focused tests in watch mode\n\n### Test Directory Structure\n\n- Tests are located in the `code/` directory\n- Vitest configuration is in `code/vitest.workspace.ts`\n- Test files typically follow the pattern `*.test.ts`, `*.test.tsx`, `*.spec.ts`, or `*.spec.tsx`\n\n### Running Tests in Cursor\n\n1. Use Cmd+Shift+P (or Ctrl+Shift+P) and search for \"Tasks: Run Task\"\n2. Select from the available test tasks:\n   - \"Run All Tests\" - Runs all tests\n   - \"Run Test (Watch Mode)\" - Runs tests in watch mode\n   - \"Run Focused Test\" - Prompts for test name/pattern to run specific tests\n   - \"Run Focused Test (Watch Mode)\" - Runs specific tests in watch mode\n\n### Vitest Configuration\n\n- Workspace configuration: `./code/vitest.workspace.ts`\n- Command line: `yarn --cwd code test`\n- Root directory for tests: `./code/`\n\n### Test Execution Context\n\n- Tests run from the `code/` directory\n- Use `NODE_OPTIONS=--max_old_space_size=4096` for memory optimization\n- Supports both watch mode and single-run execution\n\n### Focused Test Patterns\n\nWhen running focused tests, you can use:\n\n- File names: `Button.test.ts`\n- Test descriptions: `\"should render correctly\"`\n- Directory patterns: `components/`\n- Vitest patterns: `-t \"pattern\"` for test name matching\n\n### Test Mocking Rules\n\nFollow the spy mocking rules defined in `.cursor/rules/spy-mocking.mdc` for consistent mocking patterns with Vitest.\n"},"files":{"AGENTS.md":"# Storybook Agent Instructions\n\nKeep this file, `AGENTS.md`, up to date when Storybook's architecture, tooling, workflows, or contributor guidance changes.\n\nThis file is the canonical instruction source for coding agents. Files like `CLAUDE.md` should point here instead of duplicating instructions.\n\n## Repository Overview\n\nStorybook is a large TypeScript monorepo. The git root is the repo root, the main code lives in `code/`, and build tooling lives in `scripts/`. The default branch is `next`.\n\n- **Base branch**: `next` (all PRs should target `next`, not `main`)\n- **Node.js**: `22.22.3` (see `.nvmrc`) — supports `.ts` natively via type stripping (no loader needed)\n- **Package Manager**: Yarn Berry\n- **Task orchestration**: NX plus the custom `yarn task` runner\n- **Linting**: oxlint (root `.oxlintrc.json`, extended by `code/.oxlintrc.json` and `scripts/.oxlintrc.json`; custom rules load via `jsPlugins`). ESLint is no longer used for repo linting — `code/lib/eslint-plugin` remains as the published `eslint-plugin-storybook` package.\n- **Formatting**: oxfmt (root `.oxfmtrc.json`)\n- **CI environment**: Linux and Windows\n- **TS execution**: Migrating from `jiti` to native `node` for running `.ts` files. New scripts should use `node ./path/file.ts` with explicit `.ts` import extensions (enabled by `allowImportingTsExtensions` in tsconfig). Legacy scripts still use `jiti` but should be migrated over time.\n- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).\n\n## Repository Structure\n\n```text\nstorybook/\n├── .github/                      # GitHub configs and workflows\n├── .nx/                          # NX workflow state\n├── code/                         # Main codebase\n│   ├── .storybook/               # Internal Storybook UI config\n│   ├── core/                     # Core package published as \"storybook\"\n│   ├── addons/                   # Core addons\n│   ├── builders/                 # Builder integrations\n│   ├── renderers/                # Renderer integrations\n│   ├── frameworks/               # Framework integrations\n│   ├── lib/                      # Supporting libraries\n│   ├── presets/                  # Webpack-oriented presets\n│   └── sandbox/                  # Internal build artifacts\n├── scripts/                      # Build and development scripts\n├── docs/                         # Documentation\n├── test-storybooks/              # Test repos\n└── ../storybook-sandboxes/       # Generated sandboxes outside repo\n```\n\n## Architecture\n\n### Renderer vs builder vs framework\n\n| Concept   | Role                                  | Example                   |\n| --------- | ------------------------------------- | ------------------------- |\n| Renderer  | Mounts UI framework to the DOM        | `@storybook/react`        |\n| Builder   | Bundles and serves Storybook          | `@storybook/builder-vite` |\n| Framework | Renderer + builder + framework config | `@storybook/react-vite`   |\n\n### Core package\n\nThe main package is `code/core/src/`. The most important areas are:\n\n- `core-server/` for dev server, static build, and presets\n- `manager/` and `manager-api/` for the Storybook UI\n- `preview/` and `preview-api/` for story rendering\n- `channels/` for manager <-> preview communication\n- `csf-tools/` for AST-based story indexing\n- `common/` for shared Node.js utilities\n- `test/` and `instrumenter/` for testing support\n\nPublic exports include:\n\n- `storybook/actions`\n- `storybook/preview-api`\n- `storybook/manager-api`\n- `storybook/theming`\n- `storybook/test`\n\nInternal exports include:\n\n- `storybook/internal/core-server`\n- `storybook/internal/csf-tools`\n- `storybook/internal/common`\n- `storybook/internal/channels`\n\n### Key flow\n\n- `.storybook/main.ts` is loaded at startup\n- `.storybook/preview.ts` is bundled into preview (TSX for React-based frameworks)\n- `.storybook/manager.ts` is bundled into manager\n- `*.stories.*` files are indexed by AST before runtime\n- Story selection loads the module, prepares the story, and renders it\n\nAST indexing keeps the sidebar fast and prevents one broken story file from breaking the whole UI.\n\n### Open services and toolsets\n\n- Open services own internal state, synchronization, queries, commands, and loading. Toolsets expose\n  capabilities to agents through MCP and the `storybook tools` CLI.\n- Definitions live under `code/core/src/shared/open-service/`; addons may own and register their own\n  toolsets, as addon-vitest does for `test`.\n- Register services and toolsets from the same `services` preset hook and behind the same feature\n  gate. Missing or duplicate registrations fail loudly.\n- Read `code/core/src/shared/open-service/README.md` before changing the contract, adapters,\n  registration, docs access, transport rendering, or tools CLI.\n\n### Agent-facing skills\n\n- `storybook skills` serves the `stories`, `write-story`, and `setup` documents as Markdown.\n- Pure content lives in `code/core/src/cli/skills/content/` and is exported through\n  `storybook/internal/skills`; addon-mcp consumes the same builders.\n- Keep `cli/skills/**` independent of `cli/ai/**`, and keep `cli/skills/content/**` independent of\n  `core-server`. Lint rules enforce both boundaries.\n\n## Common Commands\n\nRun commands from the repository root unless stated otherwise.\n\nFor routine agent work, prefer the faster non-production commands first. Add `-c production` only when you need sandbox-related NX tasks or you are explicitly matching CI behavior.\n\n### Install and compile\n\n```bash\nyarn\nyarn task compile\nyarn nx run-many -t compile\nyarn nx compile <nx-project-name>\n```\n\n### Lint and typecheck\n\n```bash\nyarn lint\nyarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix\nyarn task check\nyarn nx run-many -t check\n```\n\n### Development and tests\n\n```bash\ncd code && yarn storybook:ui\ncd code && yarn storybook:ui:build\nyarn test\nyarn test:watch\nyarn storybook:vitest\n```\n\n### Common task scenarios\n\n| Scenario                        | Command                                                                        |\n| ------------------------------- | ------------------------------------------------------------------------------ |\n| Compile everything quickly      | `yarn nx run-many -t compile`                                                  |\n| Compile one project             | `yarn nx compile <nx-project-name>`                                            |\n| Check TypeScript errors quickly | `yarn nx run-many -t check`                                                    |\n| Start the internal Storybook UI | `cd code && yarn storybook:ui`                                                 |\n| Build the internal Storybook UI | `cd code && yarn storybook:ui:build`                                           |\n| Run unit tests                  | `yarn test`                                                                    |\n| Run Storybook Vitest tests      | `yarn storybook:vitest`                                                        |\n| Generate a sandbox              | `yarn task sandbox --template react-vite/default-ts --start-from auto`         |\n| Run sandbox E2E tests           | `yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto`   |\n| Run sandbox test-runner tests   | `yarn task test-runner-dev --template react-vite/default-ts --start-from auto` |\n| Run the docgen perf bench       | `yarn workspace @storybook/docgen-harness bench:docgen-perf`                   |\n| Run the docgen memory gate      | `yarn workspace @storybook/docgen-harness bench:docgen-memory`                 |\n| Verify sandbox docgen baselines | `yarn workspace @storybook/docgen-harness baselines:sandbox`                   |\n\n## NX and `yarn task`\n\nUse NX when you want better caching and dependency tracking. Prefer these faster defaults first, and only add `-c production` or `--no-link` when you specifically need sandbox parity or CI-like behavior.\n\n```bash\n# Compile all packages\nyarn task compile\nyarn nx run-many -t compile\n\n# Check all packages\nyarn task check\nyarn nx run-many -t check\n\n# Run E2E tests for a template\nyarn task e2e-tests-dev --template react-vite/default-ts --start-from auto\nyarn nx e2e-tests-dev react-vite/default-ts -c production\n\n# Jump to a later step\nyarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts\nyarn nx e2e-tests-dev -c production --exclude-task-dependencies\n```\n\nKey points:\n\n- `-c production` is required for sandbox-related NX commands and CI-parity runs\n- `react-vite/default-ts` is the default sandbox template\n- `--no-link` is opt-in, not the default\n- NX handles task dependencies via `nx.json`\n- NX target commands use Nx project names (from `project.json` / Nx graph), not `package.json` names\n- Example: `yarn nx compile core` (project `core` is published as package `storybook`)\n- NX Cloud remote-cache auth failures (e.g. HTTP 401 \"insufficient access\") degrade to the local cache, so they are expected on local runs where `NX_CLOUD_ACCESS_TOKEN` is unset. CI always sets that token, so a 401 there means an invalid or expired token and should be investigated rather than ignored. A read-only token enables cache reads but cannot store artifacts, so the \"wasn't able to store\" warning is still expected with one\n\n## Sandbox Notes\n\nSandboxes are generated outside the repository at `../storybook-sandboxes/` by default.\n\n- `STORYBOOK_SANDBOX_ROOT=./sandbox` forces local output, but is usually not preferred\n- `./sandbox` inside the repo mainly exists for NX outputs, not CI sandboxes\n- If sandbox generation fails, fall back to `cd code && yarn storybook:ui`\n\nGenerate and use a sandbox with the same `sandbox` command shape used elsewhere in this file:\n\n```bash\nyarn task sandbox --template react-vite/default-ts --start-from auto\n# Same sandbox step via NX\nyarn nx sandbox react-vite/default-ts -c production\ncd ../storybook-sandboxes/react-vite-default-ts\nyarn install\nyarn storybook\n```\n\nCommon templates:\n\n- `react-vite/default-ts`\n- `react-webpack/default-ts`\n- `angular-cli/default-ts`\n- `svelte-vite/default-ts`\n- `vue3-vite/default-ts`\n- `nextjs/default-ts`\n\n## How To Work In This Repo\n\n### For normal code changes\n\n1. Install if needed: `yarn`\n2. Compile with NX: `yarn nx run-many -t compile`\n3. Make changes\n4. Recompile affected packages\n5. Validate there are no TypeScript errors with `yarn nx run-many -t check`\n6. Run relevant lint and tests\n7. Validate behavior in the internal Storybook UI first, then switch to sandbox or `-c production` flows only if you need template or CI parity\n\n### For addon, framework, or renderer work\n\n1. Edit the relevant package under `code/addons/`, `code/frameworks/`, or `code/renderers/`\n2. Recompile with NX, starting without `-c production`\n3. Generate a matching sandbox\n4. Run the relevant test-runner, E2E, or Storybook UI validation flow\n\n## Testing Expectations\n\n> [!IMPORTANT]\n> **For React components, write Storybook stories with `play` functions — do NOT write `*.test.tsx` unit tests.** Behavior, accessibility, and interaction assertions belong in `*.stories.tsx` co-located with the component, executed via the Storybook Vitest project (`yarn storybook:vitest` or `vitest run --config code/vitest.config.storybook.ts`). Unit tests (`*.test.ts(x)`) are reserved for pure utilities, hooks, and non-React modules where rendering is not involved.\n\n- Use `yarn storybook:vitest` to run Storybook story tests (the primary test path for components)\n- Use `yarn test` for unit tests of utilities, hooks, and non-React modules\n- Prefer focused unit-test runs during iteration — the full suite is large: `yarn test <pattern>` (e.g. `yarn test csf-tools`)\n- Use Storybook UI or Chromatic for visual validation\n- Use `yarn task e2e-tests --start-from auto` or `yarn task e2e-tests-dev --start-from auto` for E2E coverage\n- Use `yarn task test-runner --start-from auto` or `yarn task test-runner-dev --start-from auto` for test-runner scenarios\n- Use `yarn task smoke-test --start-from auto` for smoke checks\n\nWatch-mode commands:\n\n```bash\nyarn test:watch\nyarn storybook:vitest\n```\n\nWhen writing tests for components:\n\n- Add or update `<Component>.stories.tsx` with stories covering each behavior; use `play` functions with `expect`, `userEvent`, `within` from `storybook/test`\n- Mock external context (e.g. `ManagerContext.Provider`) inside story decorators or `beforeEach`\n- Run `vitest --config code/vitest.config.storybook.ts <story-file>` to verify play assertions\n\nWhen writing unit tests (utilities, hooks, non-React modules):\n\n- Export functions that need direct tests\n- Test real behavior, not just syntax patterns\n- Use coverage when useful: `yarn vitest run --coverage <test-file>`\n- Mock external dependencies like file system access and loggers\n- Use Node's path.resolve to wrap expected FS paths when writing path-related tests, so they work on Windows\n\n### Filesystem tests with `memfs`\n\nFor unit tests that touch `node:fs` / `node:fs/promises`, use [`memfs`](https://github.com/streamich/memfs) instead of real temp directories or wholesale `node:fs` mocks:\n\n- Import `vol` from `memfs` and call `vol.reset()` in `beforeEach`\n- Seed virtual files with `vol.fromNestedJSON({ '/absolute/path/file.json': '...' })` or memfs `writeFile` after redirecting spies\n- Use `vi.mock('node:fs/promises', { spy: true })` and, in `beforeEach`, point `mkdir` / `writeFile` / `readFile` at `memfs.fs.promises` (see `code/core/src/shared/open-service/server.test.ts`)\n- Assert disk state with `vol.toJSON()` when helpful\n\nDo **not** use `/tmp` paths or replace `node:fs/promises` with a full async factory mock unless a test file already standardizes on the spy redirect pattern above.\n\n### Globals in tests: never assign `globalThis.*` directly\n\n> [!IMPORTANT]\n> Under no circumstances may a test mutate a global by assigning it directly (e.g. `globalThis.FEATURES = {...}`, `globalThis.window = ...`, `global.fetch = ...`). Direct assignment leaks across tests and files — Vitest does not restore it — so it silently changes behavior in unrelated tests and creates order-dependent flakiness.\n\nUse Vitest's global stubbing instead, which is tracked and restorable:\n\n- Set a global with `vi.stubGlobal('FEATURES', { experimentalDocgenServer: true })`.\n- Restore in `afterEach(() => vi.unstubAllGlobals())` (or enable `unstubGlobals: true` in the Vitest config so it resets before each test automatically).\n- For a value used by every test in a file, stub it in `beforeEach` and unstub in `afterEach`; for a one-off override, call `vi.stubGlobal` inside that single test.\n- Never capture-and-restore by hand (`const original = globalThis.X; ... globalThis.X = original`); `vi.stubGlobal` + `vi.unstubAllGlobals()` does this correctly, including deleting keys that did not previously exist.\n\nThis applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).\n\n## Quality and Logging\n\nAfter changing files:\n\n1. **Always** format with `yarn fmt:write`, run from the `code/` directory (`cd code && yarn fmt:write`), once you are done editing. The repo uses `oxfmt`, so hand-written formatting will frequently be wrong — do not skip this step.\n2. Lint with `yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix` or `cd code && yarn lint:js:cmd <file-relative-to-code-folder>`\n3. Run relevant tests before submitting a PR\n\nUse Storybook loggers instead of raw `console.*` in normal code paths:\n\n- Server-side: `storybook/internal/node-logger`\n- Client-side: `storybook/internal/client-logger`\n\nFor TypeScript source in the repo, prefer explicit file extensions for relative code imports and exports such as `./foo.ts` or `./bar.tsx` when the target is another TS/JS module in this repository. Keep framework-specific component imports like `.vue` and `.svelte` in the form already expected by their package tooling.\n\nThe pre-commit hook automatically detects AI agents (via `std-env`) and switches from check-only to write mode, so formatting is auto-fixed when agents commit.\n\nAvoid `console.log`, `console.warn`, and `console.error` unless the file is isolated enough that importing the logger is not reasonable.\n\n## Troubleshooting\n\n- Build failures are often fixed by rerunning `yarn` and `yarn nx run-many -t compile`\n- Storybook UI uses port `6006` by default\n- Large compiles may require more Node.js memory\n- Sandbox paths are `../storybook-sandboxes/`, not `./sandbox` or `code/sandbox/`\n- Use `--debug` for verbose CLI output\n- Check generated sandbox directories and `.cache/` for build artifacts\n\n## Environment Variables\n\n| Variable                      | Purpose                                         |\n| ----------------------------- | ----------------------------------------------- |\n| `IN_STORYBOOK_SANDBOX`        | Set during sandbox creation                     |\n| `STORYBOOK_DISABLE_TELEMETRY` | Disable telemetry                               |\n| `STORYBOOK_TELEMETRY_DEBUG`   | Log telemetry events                            |\n| `DEBUG`                       | Enable debug logging                            |\n| `FIX_ON_COMMIT`               | Force autofix for fmt & lint in pre-commit hook |\n| `NX_CLOUD_ACCESS_TOKEN`       | Authenticate the NX Cloud remote cache          |\n\n## Commands To Avoid\n\n- **DO NOT RUN** `yarn task dev` without an explicit sandbox template\n- **DO NOT RUN** `yarn start`\n\nThese usually start long-running development servers and are the wrong default for agents.\n\n## Code Authoring Principles\n\nThese are recurring failure modes in agent-authored changes to this repo. Apply them when writing or reviewing code, not just when asked.\n\n- **Write comments only for the two reasons in [Comments and JSDoc](#comments-and-jsdoc).** That section is the rule; this list does not restate it.\n- **Verify environment assumptions empirically before encoding them.** If a design rests on \"the bundler strips X\" or \"this metadata is empty here\", prove it with a throwaway probe before building on it (and before writing it into a comment as fact). A 10-line experiment is cheaper than a wrong architecture.\n- **Encode assumptions with static checks first.** If an assumption is expected to always hold, prefer making it impossible via TypeScript types and existing lint rules. When static checks are not practical, add a cheap runtime assertion close to the boundary so violations fail loudly at the source.\n- **Avoid redundant tests already covered elsewhere.** Do not add tests for code patterns already guaranteed by TypeScript or linting, and do not duplicate coverage that already exists in Storybook `play` functions or Playwright tests.\n- **Test contracts (including side effects), not private implementation details.** It is valid to assert side effects when they are part of the public contract. Avoid assertions about internals that are not part of an exported contract, user-visible DOM output, or externally observable behavior.\n- **Bias toward broader coverage for security and migrations.** For security-sensitive code paths and legacy data migration logic, prefer handling more edge cases and documenting evidence for the chosen safeguards. Migration compatibility code should be explicitly version-scoped so it can be removed once the support window ends.\n- **Prefer deletion and simplicity over speculative generality.** No abstraction, fallback, or \"flexibility\" for a consumer or scenario that does not exist in this codebase today. If a change adds many lines, check whether the right change removes them.\n- **Don't commit accidental overrides to generated code.** Files like `code/core/src/manager/globals/exports.ts` are auto-generated, as stated in their JSDoc header. Only commit changes if they match changes you made on your PR, otherwise leave them untouched and flag flaky generated files in the PR description.\n\n## Comments and JSDoc\n\nCode should be self-explanatory. A comment is only justified when the code cannot explain itself (a non-obvious *why*) or when a public API needs explanation. Never comment to record that you did x, y, z.\n\nBefore writing or editing any code file, read [`.agents/guidelines/comments-and-jsdoc.md`](.agents/guidelines/comments-and-jsdoc.md) and follow it. Read it once per session, not once per file.\n\n## Maintenance Rules For Agents\n\n- Use this file as the canonical instruction source\n- Update `AGENTS.md` when architecture, commands, versions, release flows, or contributor guidance changes\n- Keep `CLAUDE.md` and other agent entrypoints as thin references to `AGENTS.md`\n- Do not reintroduce duplicated instruction files when a reference will do\n\n## Learned User Preferences\n\n- Prefer git worktrees for parallel or experimental work; keep the primary workspace clean and base feature branches on `origin/next`, not a dirty local `next`.\n- Prefer simplicity: avoid premature helpers and one-off abstractions; implement small logic inline when a shared helper is not clearly reused.\n- Keep e2e and long interaction tests as a readable continuous flow; do not force DRY with loops or heavy helpers when repetition is clearer.\n- For Storybook stories, put human-facing description in JSDoc above the `meta` const rather than a `description` parameter.\n- When renaming tools or APIs that emit telemetry, keep historical telemetry string names stable across Storybook versions unless the field is brand-new and has no existing data.\n",".cursorrules":"## Test Configuration\n\nThis Storybook repository uses Vitest as the test runner. Here are the key commands and configuration:\n\n### Test Scripts\n\n- `yarn test` - Run all tests (from root directory, delegates to `cd code; yarn test`)\n- `yarn test <test-name>` - Run focused tests matching the pattern\n- `yarn test:watch` - Run tests in watch mode\n- `yarn test:watch <test-name>` - Run focused tests in watch mode\n\n### Test Directory Structure\n\n- Tests are located in the `code/` directory\n- Vitest configuration is in `code/vitest.workspace.ts`\n- Test files typically follow the pattern `*.test.ts`, `*.test.tsx`, `*.spec.ts`, or `*.spec.tsx`\n\n### Running Tests in Cursor\n\n1. Use Cmd+Shift+P (or Ctrl+Shift+P) and search for \"Tasks: Run Task\"\n2. Select from the available test tasks:\n   - \"Run All Tests\" - Runs all tests\n   - \"Run Test (Watch Mode)\" - Runs tests in watch mode\n   - \"Run Focused Test\" - Prompts for test name/pattern to run specific tests\n   - \"Run Focused Test (Watch Mode)\" - Runs specific tests in watch mode\n\n### Vitest Configuration\n\n- Workspace configuration: `./code/vitest.workspace.ts`\n- Command line: `yarn --cwd code test`\n- Root directory for tests: `./code/`\n\n### Test Execution Context\n\n- Tests run from the `code/` directory\n- Use `NODE_OPTIONS=--max_old_space_size=4096` for memory optimization\n- Supports both watch mode and single-run execution\n\n### Focused Test Patterns\n\nWhen running focused tests, you can use:\n\n- File names: `Button.test.ts`\n- Test descriptions: `\"should render correctly\"`\n- Directory patterns: `components/`\n- Vitest patterns: `-t \"pattern\"` for test name matching\n\n### Test Mocking Rules\n\nFollow the spy mocking rules defined in `.cursor/rules/spy-mocking.mdc` for consistent mocking patterns with Vitest.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Storybook Agent Instructions\n\nKeep this file, `AGENTS.md`, up to date when Storybook's architecture, tooling, workflows, or contributor guidance changes.\n\nThis file is the canonical instruction source for coding agents. Files like `CLAUDE.md` should point here instead of duplicating instructions.\n\n## Repository Overview\n\nStorybook is a large TypeScript monorepo. The git root is the repo root, the main code lives in `code/`, and build tooling lives in `scripts/`. The default branch is `next`.\n\n- **Base branch**: `next` (all PRs should target `next`, not `main`)\n- **Node.js**: `22.22.3` (see `.nvmrc`) — supports `.ts` natively via type stripping (no loader needed)\n- **Package Manager**: Yarn Berry\n- **Task orchestration**: NX plus the custom `yarn task` runner\n- **Linting**: oxlint (root `.oxlintrc.json`, extended by `code/.oxlintrc.json` and `scripts/.oxlintrc.json`; custom rules load via `jsPlugins`). ESLint is no longer used for repo linting — `code/lib/eslint-plugin` remains as the published `eslint-plugin-storybook` package.\n- **Formatting**: oxfmt (root `.oxfmtrc.json`)\n- **CI environment**: Linux and Windows\n- **TS execution**: Migrating from `jiti` to native `node` for running `.ts` files. New scripts should use `node ./path/file.ts` with explicit `.ts` import extensions (enabled by `allowImportingTsExtensions` in tsconfig). Legacy scripts still use `jiti` but should be migrated over time.\n- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).\n\n## Repository Structure\n\n```text\nstorybook/\n├── .github/                      # GitHub configs and workflows\n├── .nx/                          # NX workflow state\n├── code/                         # Main codebase\n│   ├── .storybook/               # Internal Storybook UI config\n│   ├── core/                     # Core package published as \"storybook\"\n│   ├── addons/                   # Core addons\n│   ├── builders/                 # Builder integrations\n│   ├── renderers/                # Renderer integrations\n│   ├── frameworks/               # Framework integrations\n│   ├── lib/                      # Supporting libraries\n│   ├── presets/                  # Webpack-oriented presets\n│   └── sandbox/                  # Internal build artifacts\n├── scripts/                      # Build and development scripts\n├── docs/                         # Documentation\n├── test-storybooks/              # Test repos\n└── ../storybook-sandboxes/       # Generated sandboxes outside repo\n```\n\n## Architecture\n\n### Renderer vs builder vs framework\n\n| Concept   | Role                                  | Example                   |\n| --------- | ------------------------------------- | ------------------------- |\n| Renderer  | Mounts UI framework to the DOM        | `@storybook/react`        |\n| Builder   | Bundles and serves Storybook          | `@storybook/builder-vite` |\n| Framework | Renderer + builder + framework config | `@storybook/react-vite`   |\n\n### Core package\n\nThe main package is `code/core/src/`. The most important areas are:\n\n- `core-server/` for dev server, static build, and presets\n- `manager/` and `manager-api/` for the Storybook UI\n- `preview/` and `preview-api/` for story rendering\n- `channels/` for manager <-> preview communication\n- `csf-tools/` for AST-based story indexing\n- `common/` for shared Node.js utilities\n- `test/` and `instrumenter/` for testing support\n\nPublic exports include:\n\n- `storybook/actions`\n- `storybook/preview-api`\n- `storybook/manager-api`\n- `storybook/theming`\n- `storybook/test`\n\nInternal exports include:\n\n- `storybook/internal/core-server`\n- `storybook/internal/csf-tools`\n- `storybook/internal/common`\n- `storybook/internal/channels`\n\n### Key flow\n\n- `.storybook/main.ts` is loaded at startup\n- `.storybook/preview.ts` is bundled into preview (TSX for React-based frameworks)\n- `.storybook/manager.ts` is bundled into manager\n- `*.stories.*` files are indexed by AST before runtime\n- Story selection loads the module, prepares the story, and renders it\n\nAST indexing keeps the sidebar fast and prevents one broken story file from breaking the whole UI.\n\n### Open services and toolsets\n\n- Open services own internal state, synchronization, queries, commands, and loading. Toolsets expose\n  capabilities to agents through MCP and the `storybook tools` CLI.\n- Definitions live under `code/core/src/shared/open-service/`; addons may own and register their own\n  toolsets, as addon-vitest does for `test`.\n- Register services and toolsets from the same `services` preset hook and behind the same feature\n  gate. Missing or duplicate registrations fail loudly.\n- Read `code/core/src/shared/open-service/README.md` before changing the contract, adapters,\n  registration, docs access, transport rendering, or tools CLI.\n\n### Agent-facing skills\n\n- `storybook skills` serves the `stories`, `write-story`, and `setup` documents as Markdown.\n- Pure content lives in `code/core/src/cli/skills/content/` and is exported through\n  `storybook/internal/skills`; addon-mcp consumes the same builders.\n- Keep `cli/skills/**` independent of `cli/ai/**`, and keep `cli/skills/content/**` independent of\n  `core-server`. Lint rules enforce both boundaries.\n\n## Common Commands\n\nRun commands from the repository root unless stated otherwise.\n\nFor routine agent work, prefer the faster non-production commands first. Add `-c production` only when you need sandbox-related NX tasks or you are explicitly matching CI behavior.\n\n### Install and compile\n\n```bash\nyarn\nyarn task compile\nyarn nx run-many -t compile\nyarn nx compile <nx-project-name>\n```\n\n### Lint and typecheck\n\n```bash\nyarn lint\nyarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix\nyarn task check\nyarn nx run-many -t check\n```\n\n### Development and tests\n\n```bash\ncd code && yarn storybook:ui\ncd code && yarn storybook:ui:build\nyarn test\nyarn test:watch\nyarn storybook:vitest\n```\n\n### Common task scenarios\n\n| Scenario                        | Command                                                                        |\n| ------------------------------- | ------------------------------------------------------------------------------ |\n| Compile everything quickly      | `yarn nx run-many -t compile`                                                  |\n| Compile one project             | `yarn nx compile <nx-project-name>`                                            |\n| Check TypeScript errors quickly | `yarn nx run-many -t check`                                                    |\n| Start the internal Storybook UI | `cd code && yarn storybook:ui`                                                 |\n| Build the internal Storybook UI | `cd code && yarn storybook:ui:build`                                           |\n| Run unit tests                  | `yarn test`                                                                    |\n| Run Storybook Vitest tests      | `yarn storybook:vitest`                                                        |\n| Generate a sandbox              | `yarn task sandbox --template react-vite/default-ts --start-from auto`         |\n| Run sandbox E2E tests           | `yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto`   |\n| Run sandbox test-runner tests   | `yarn task test-runner-dev --template react-vite/default-ts --start-from auto` |\n| Run the docgen perf bench       | `yarn workspace @storybook/docgen-harness bench:docgen-perf`                   |\n| Run the docgen memory gate      | `yarn workspace @storybook/docgen-harness bench:docgen-memory`                 |\n| Verify sandbox docgen baselines | `yarn workspace @storybook/docgen-harness baselines:sandbox`                   |\n\n## NX and `yarn task`\n\nUse NX when you want better caching and dependency tracking. Prefer these faster defaults first, and only add `-c production` or `--no-link` when you specifically need sandbox parity or CI-like behavior.\n\n```bash\n# Compile all packages\nyarn task compile\nyarn nx run-many -t compile\n\n# Check all packages\nyarn task check\nyarn nx run-many -t check\n\n# Run E2E tests for a template\nyarn task e2e-tests-dev --template react-vite/default-ts --start-from auto\nyarn nx e2e-tests-dev react-vite/default-ts -c production\n\n# Jump to a later step\nyarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts\nyarn nx e2e-tests-dev -c production --exclude-task-dependencies\n```\n\nKey points:\n\n- `-c production` is required for sandbox-related NX commands and CI-parity runs\n- `react-vite/default-ts` is the default sandbox template\n- `--no-link` is opt-in, not the default\n- NX handles task dependencies via `nx.json`\n- NX target commands use Nx project names (from `project.json` / Nx graph), not `package.json` names\n- Example: `yarn nx compile core` (project `core` is published as package `storybook`)\n- NX Cloud remote-cache auth failures (e.g. HTTP 401 \"insufficient access\") degrade to the local cache, so they are expected on local runs where `NX_CLOUD_ACCESS_TOKEN` is unset. CI always sets that token, so a 401 there means an invalid or expired token and should be investigated rather than ignored. A read-only token enables cache reads but cannot store artifacts, so the \"wasn't able to store\" warning is still expected with one\n\n## Sandbox Notes\n\nSandboxes are generated outside the repository at `../storybook-sandboxes/` by default.\n\n- `STORYBOOK_SANDBOX_ROOT=./sandbox` forces local output, but is usually not preferred\n- `./sandbox` inside the repo mainly exists for NX outputs, not CI sandboxes\n- If sandbox generation fails, fall back to `cd code && yarn storybook:ui`\n\nGenerate and use a sandbox with the same `sandbox` command shape used elsewhere in this file:\n\n```bash\nyarn task sandbox --template react-vite/default-ts --start-from auto\n# Same sandbox step via NX\nyarn nx sandbox react-vite/default-ts -c production\ncd ../storybook-sandboxes/react-vite-default-ts\nyarn install\nyarn storybook\n```\n\nCommon templates:\n\n- `react-vite/default-ts`\n- `react-webpack/default-ts`\n- `angular-cli/default-ts`\n- `svelte-vite/default-ts`\n- `vue3-vite/default-ts`\n- `nextjs/default-ts`\n\n## How To Work In This Repo\n\n### For normal code changes\n\n1. Install if needed: `yarn`\n2. Compile with NX: `yarn nx run-many -t compile`\n3. Make changes\n4. Recompile affected packages\n5. Validate there are no TypeScript errors with `yarn nx run-many -t check`\n6. Run relevant lint and tests\n7. Validate behavior in the internal Storybook UI first, then switch to sandbox or `-c production` flows only if you need template or CI parity\n\n### For addon, framework, or renderer work\n\n1. Edit the relevant package under `code/addons/`, `code/frameworks/`, or `code/renderers/`\n2. Recompile with NX, starting without `-c production`\n3. Generate a matching sandbox\n4. Run the relevant test-runner, E2E, or Storybook UI validation flow\n\n## Testing Expectations\n\n> [!IMPORTANT]\n> **For React components, write Storybook stories with `play` functions — do NOT write `*.test.tsx` unit tests.** Behavior, accessibility, and interaction assertions belong in `*.stories.tsx` co-located with the component, executed via the Storybook Vitest project (`yarn storybook:vitest` or `vitest run --config code/vitest.config.storybook.ts`). Unit tests (`*.test.ts(x)`) are reserved for pure utilities, hooks, and non-React modules where rendering is not involved.\n\n- Use `yarn storybook:vitest` to run Storybook story tests (the primary test path for components)\n- Use `yarn test` for unit tests of utilities, hooks, and non-React modules\n- Prefer focused unit-test runs during iteration — the full suite is large: `yarn test <pattern>` (e.g. `yarn test csf-tools`)\n- Use Storybook UI or Chromatic for visual validation\n- Use `yarn task e2e-tests --start-from auto` or `yarn task e2e-tests-dev --start-from auto` for E2E coverage\n- Use `yarn task test-runner --start-from auto` or `yarn task test-runner-dev --start-from auto` for test-runner scenarios\n- Use `yarn task smoke-test --start-from auto` for smoke checks\n\nWatch-mode commands:\n\n```bash\nyarn test:watch\nyarn storybook:vitest\n```\n\nWhen writing tests for components:\n\n- Add or update `<Component>.stories.tsx` with stories covering each behavior; use `play` functions with `expect`, `userEvent`, `within` from `storybook/test`\n- Mock external context (e.g. `ManagerContext.Provider`) inside story decorators or `beforeEach`\n- Run `vitest --config code/vitest.config.storybook.ts <story-file>` to verify play assertions\n\nWhen writing unit tests (utilities, hooks, non-React modules):\n\n- Export functions that need direct tests\n- Test real behavior, not just syntax patterns\n- Use coverage when useful: `yarn vitest run --coverage <test-file>`\n- Mock external dependencies like file system access and loggers\n- Use Node's path.resolve to wrap expected FS paths when writing path-related tests, so they work on Windows\n\n### Filesystem tests with `memfs`\n\nFor unit tests that touch `node:fs` / `node:fs/promises`, use [`memfs`](https://github.com/streamich/memfs) instead of real temp directories or wholesale `node:fs` mocks:\n\n- Import `vol` from `memfs` and call `vol.reset()` in `beforeEach`\n- Seed virtual files with `vol.fromNestedJSON({ '/absolute/path/file.json': '...' })` or memfs `writeFile` after redirecting spies\n- Use `vi.mock('node:fs/promises', { spy: true })` and, in `beforeEach`, point `mkdir` / `writeFile` / `readFile` at `memfs.fs.promises` (see `code/core/src/shared/open-service/server.test.ts`)\n- Assert disk state with `vol.toJSON()` when helpful\n\nDo **not** use `/tmp` paths or replace `node:fs/promises` with a full async factory mock unless a test file already standardizes on the spy redirect pattern above.\n\n### Globals in tests: never assign `globalThis.*` directly\n\n> [!IMPORTANT]\n> Under no circumstances may a test mutate a global by assigning it directly (e.g. `globalThis.FEATURES = {...}`, `globalThis.window = ...`, `global.fetch = ...`). Direct assignment leaks across tests and files — Vitest does not restore it — so it silently changes behavior in unrelated tests and creates order-dependent flakiness.\n\nUse Vitest's global stubbing instead, which is tracked and restorable:\n\n- Set a global with `vi.stubGlobal('FEATURES', { experimentalDocgenServer: true })`.\n- Restore in `afterEach(() => vi.unstubAllGlobals())` (or enable `unstubGlobals: true` in the Vitest config so it resets before each test automatically).\n- For a value used by every test in a file, stub it in `beforeEach` and unstub in `afterEach`; for a one-off override, call `vi.stubGlobal` inside that single test.\n- Never capture-and-restore by hand (`const original = globalThis.X; ... globalThis.X = original`); `vi.stubGlobal` + `vi.unstubAllGlobals()` does this correctly, including deleting keys that did not previously exist.\n\nThis applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).\n\n## Quality and Logging\n\nAfter changing files:\n\n1. **Always** format with `yarn fmt:write`, run from the `code/` directory (`cd code && yarn fmt:write`), once you are done editing. The repo uses `oxfmt`, so hand-written formatting will frequently be wrong — do not skip this step.\n2. Lint with `yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix` or `cd code && yarn lint:js:cmd <file-relative-to-code-folder>`\n3. Run relevant tests before submitting a PR\n\nUse Storybook loggers instead of raw `console.*` in normal code paths:\n\n- Server-side: `storybook/internal/node-logger`\n- Client-side: `storybook/internal/client-logger`\n\nFor TypeScript source in the repo, prefer explicit file extensions for relative code imports and exports such as `./foo.ts` or `./bar.tsx` when the target is another TS/JS module in this repository. Keep framework-specific component imports like `.vue` and `.svelte` in the form already expected by their package tooling.\n\nThe pre-commit hook automatically detects AI agents (via `std-env`) and switches from check-only to write mode, so formatting is auto-fixed when agents commit.\n\nAvoid `console.log`, `console.warn`, and `console.error` unless the file is isolated enough that importing the logger is not reasonable.\n\n## Troubleshooting\n\n- Build failures are often fixed by rerunning `yarn` and `yarn nx run-many -t compile`\n- Storybook UI uses port `6006` by default\n- Large compiles may require more Node.js memory\n- Sandbox paths are `../storybook-sandboxes/`, not `./sandbox` or `code/sandbox/`\n- Use `--debug` for verbose CLI output\n- Check generated sandbox directories and `.cache/` for build artifacts\n\n## Environment Variables\n\n| Variable                      | Purpose                                         |\n| ----------------------------- | ----------------------------------------------- |\n| `IN_STORYBOOK_SANDBOX`        | Set during sandbox creation                     |\n| `STORYBOOK_DISABLE_TELEMETRY` | Disable telemetry                               |\n| `STORYBOOK_TELEMETRY_DEBUG`   | Log telemetry events                            |\n| `DEBUG`                       | Enable debug logging                            |\n| `FIX_ON_COMMIT`               | Force autofix for fmt & lint in pre-commit hook |\n| `NX_CLOUD_ACCESS_TOKEN`       | Authenticate the NX Cloud remote cache          |\n\n## Commands To Avoid\n\n- **DO NOT RUN** `yarn task dev` without an explicit sandbox template\n- **DO NOT RUN** `yarn start`\n\nThese usually start long-running development servers and are the wrong default for agents.\n\n## Code Authoring Principles\n\nThese are recurring failure modes in agent-authored changes to this repo. Apply them when writing or reviewing code, not just when asked.\n\n- **Write comments only for the two reasons in [Comments and JSDoc](#comments-and-jsdoc).** That section is the rule; this list does not restate it.\n- **Verify environment assumptions empirically before encoding them.** If a design rests on \"the bundler strips X\" or \"this metadata is empty here\", prove it with a throwaway probe before building on it (and before writing it into a comment as fact). A 10-line experiment is cheaper than a wrong architecture.\n- **Encode assumptions with static checks first.** If an assumption is expected to always hold, prefer making it impossible via TypeScript types and existing lint rules. When static checks are not practical, add a cheap runtime assertion close to the boundary so violations fail loudly at the source.\n- **Avoid redundant tests already covered elsewhere.** Do not add tests for code patterns already guaranteed by TypeScript or linting, and do not duplicate coverage that already exists in Storybook `play` functions or Playwright tests.\n- **Test contracts (including side effects), not private implementation details.** It is valid to assert side effects when they are part of the public contract. Avoid assertions about internals that are not part of an exported contract, user-visible DOM output, or externally observable behavior.\n- **Bias toward broader coverage for security and migrations.** For security-sensitive code paths and legacy data migration logic, prefer handling more edge cases and documenting evidence for the chosen safeguards. Migration compatibility code should be explicitly version-scoped so it can be removed once the support window ends.\n- **Prefer deletion and simplicity over speculative generality.** No abstraction, fallback, or \"flexibility\" for a consumer or scenario that does not exist in this codebase today. If a change adds many lines, check whether the right change removes them.\n- **Don't commit accidental overrides to generated code.** Files like `code/core/src/manager/globals/exports.ts` are auto-generated, as stated in their JSDoc header. Only commit changes if they match changes you made on your PR, otherwise leave them untouched and flag flaky generated files in the PR description.\n\n## Comments and JSDoc\n\nCode should be self-explanatory. A comment is only justified when the code cannot explain itself (a non-obvious *why*) or when a public API needs explanation. Never comment to record that you did x, y, z.\n\nBefore writing or editing any code file, read [`.agents/guidelines/comments-and-jsdoc.md`](.agents/guidelines/comments-and-jsdoc.md) and follow it. Read it once per session, not once per file.\n\n## Maintenance Rules For Agents\n\n- Use this file as the canonical instruction source\n- Update `AGENTS.md` when architecture, commands, versions, release flows, or contributor guidance changes\n- Keep `CLAUDE.md` and other agent entrypoints as thin references to `AGENTS.md`\n- Do not reintroduce duplicated instruction files when a reference will do\n\n## Learned User Preferences\n\n- Prefer git worktrees for parallel or experimental work; keep the primary workspace clean and base feature branches on `origin/next`, not a dirty local `next`.\n- Prefer simplicity: avoid premature helpers and one-off abstractions; implement small logic inline when a shared helper is not clearly reused.\n- Keep e2e and long interaction tests as a readable continuous flow; do not force DRY with loops or heavy helpers when repetition is clearer.\n- For Storybook stories, put human-facing description in JSDoc above the `meta` const rather than a `description` parameter.\n- When renaming tools or APIs that emit telemetry, keep historical telemetry string names stable across Storybook versions unless the field is brand-new and has no existing data.\n","category":"root","tokens":5455},{"name":".cursorrules","path":".cursorrules","title":".cursorrules","content":"## Test Configuration\n\nThis Storybook repository uses Vitest as the test runner. Here are the key commands and configuration:\n\n### Test Scripts\n\n- `yarn test` - Run all tests (from root directory, delegates to `cd code; yarn test`)\n- `yarn test <test-name>` - Run focused tests matching the pattern\n- `yarn test:watch` - Run tests in watch mode\n- `yarn test:watch <test-name>` - Run focused tests in watch mode\n\n### Test Directory Structure\n\n- Tests are located in the `code/` directory\n- Vitest configuration is in `code/vitest.workspace.ts`\n- Test files typically follow the pattern `*.test.ts`, `*.test.tsx`, `*.spec.ts`, or `*.spec.tsx`\n\n### Running Tests in Cursor\n\n1. Use Cmd+Shift+P (or Ctrl+Shift+P) and search for \"Tasks: Run Task\"\n2. Select from the available test tasks:\n   - \"Run All Tests\" - Runs all tests\n   - \"Run Test (Watch Mode)\" - Runs tests in watch mode\n   - \"Run Focused Test\" - Prompts for test name/pattern to run specific tests\n   - \"Run Focused Test (Watch Mode)\" - Runs specific tests in watch mode\n\n### Vitest Configuration\n\n- Workspace configuration: `./code/vitest.workspace.ts`\n- Command line: `yarn --cwd code test`\n- Root directory for tests: `./code/`\n\n### Test Execution Context\n\n- Tests run from the `code/` directory\n- Use `NODE_OPTIONS=--max_old_space_size=4096` for memory optimization\n- Supports both watch mode and single-run execution\n\n### Focused Test Patterns\n\nWhen running focused tests, you can use:\n\n- File names: `Button.test.ts`\n- Test descriptions: `\"should render correctly\"`\n- Directory patterns: `components/`\n- Vitest patterns: `-t \"pattern\"` for test name matching\n\n### Test Mocking Rules\n\nFollow the spy mocking rules defined in `.cursor/rules/spy-mocking.mdc` for consistent mocking patterns with Vitest.\n","category":"root","tokens":441}]}