Welcome! We are really excited that you are interested in contributing to Histoire. Before submitting your contribution, please make sure to take a moment and read through the following guide:
Contributing doesn't necessarily mean you need to write code and open Pull Requests. There are many other ways you can help the project!
- Try the latest version of Histoire and report bugs.
- Discuss your ideas with the community on the discussion board.
- Answer to other people's questions.
- Report typos or issues of the docs.
- Support us financially on GitHub sponsors:
- Do you like Histoire? Spread the love on social media!
This mono-repo contains the following packages:
| Package | Description |
|---|---|
| histoire | Main package |
| @histoire/app | Pre-bundled UI |
| @histoire/controls | Builtin controls components |
| @histoire/controls-stories | Stories for builtin controls |
| @histoire/plugin-vue | Vue 3 integration |
| @histoire/plugin-react | React 18/19 integration |
| @histoire/plugin-svelte | Svelte 4/5 and SvelteKit 2/3 integration |
| @histoire/plugin-nuxt | Nuxt 3/4 integration |
| @histoire/plugin-percy | Visual regression testing with Percy |
| @histoire/plugin-screenshot | Visual regression testing with simple screenshots |
| @histoire/shared | Shared utilities |
| @histoire/vendors | Pre-bundled dependencies |
- Install dependencies with pnpm:
corepack enable
pnpm i- Compile Histoire in watch mode:
pnpm run watchWait before the initial build is done and the terminal output stabilizes.
If you do not intend to make changes to the histoire main packages, you can use this script instead:
pnpm run build- In the
examplesdirectory, you can runstory:devscripts to start Histoire on an example project.
cd examples/vue3
pnpm run story:devExample story:dev scripts watch built outputs across repository packages. After output changes settle for 1.5 seconds, Histoire restarts automatically with fresh runtime code and the browser reconnects. Story and component edits still use Vite HMR without restarting the process.
Keep pnpm run watch running separately when editing Histoire packages. The example launcher does not build packages; if a rebuild temporarily removes outputs or startup fails, it waits for later output changes and starts again. Optimizer caches are preserved. A rebuild can interrupt active tests; run them again after Histoire finishes restarting.
story:dev uses the built Histoire UI. In vue3, pnpm run dev:hst uses the same automatic restart launcher with HISTOIRE_DEV=true, enabling HMR for Histoire UI sources. Both commands forward CLI arguments, for example pnpm run story:dev -- --port 6006 --config "custom config.ts".
- After you have tested your changes in development mode, build the story apps and test them using the
story:buildandstory:previewscripts:
pnpm run story:build
pnpm run story:previewpnpm exec tsc runs native TypeScript 7 for builds and type checks. Workspaces
that use TypeScript declare @typescript/native from the shared catalog.
The typescript catalog entry aliases @typescript/typescript6, keeping the
TypeScript 6 JavaScript API available to Vue tooling, ESLint, vendor builds,
Svelte tooling, and tests that parse TypeScript. Declare both catalog entries
in each workspace so pnpm resolves framework peers to the compatibility API.
pnpm exec tsc6 runs the compatibility compiler explicitly. Keep both catalog
entries when updating TypeScript; replacing typescript with stock TypeScript 7
breaks those tools.
Workspace builds use Vite 8 with Rolldown and Oxc. Keep Vite versions on the
shared catalog and use build.rolldownOptions in workspace Vite configs.
Histoire still supports Vite 7 consumers through its Rollup config path.
The Svelte 4 example and VitePress retain their separate Vite 5 dependencies.
@histoire/vendors still builds with Rollup and the TypeScript 6 API. Histoire
also uses Rollup's parser and esbuild for deployed Node bundles; these direct
dependencies are independent of Vite's bundler.
Use Node.js 22.12+ and the repository's pinned pnpm version:
corepack enable
pnpm install --frozen-lockfile
pnpm docs:build
pnpm --filter histoire-example-vue3 exec playwright install chromium
pnpm docs:check
pnpm docs:servedocs:build first compiles the Vue demo's workspace dependencies in dependency order, so it works from a fresh checkout without a separate pnpm build. It then builds a static Vue book into ignored docs/public/demo/ before VitePress copies it into docs/.vitepress/dist/demo/. Publish the whole docs/.vitepress/dist/ directory. The /demo/ asset base and hash routing keep direct story links usable without host rewrite rules. Demo links perform a full navigation so VitePress does not treat the book as a Markdown page.
docs:dev also builds this book before starting VitePress; compile workspace packages first with pnpm build or pnpm docs:build. After changing a demo story, run pnpm docs:demo to refresh it. examples/vue3/histoire.docs.config.ts selects existing interactive examples and omits stress and failure fixtures; the regular Vue test book remains unchanged.
docs:check serves the production output using a plain static server and checks the actual browser: demo navigation, prop edits reaching the canvas, generated source, docs links surviving reload, narrow-screen rendering, and development actions staying hidden. It needs the Vue example's Playwright dependency and Chromium. It uses an ephemeral loopback port and closes both server and browser on failure.
Refresh screenshots after workbench changes:
pnpm docs:build
pnpm docs:screenshots
pnpm docs:build
pnpm docs:checkdocs:screenshots runs the same browser checks, captures light/dark workbench images under docs/public/screenshots/, and updates the README's screenshot.png. Review both images before committing. Rebuild afterward so the published docs contain the new images.
We use ESLint to check for code quality and style.
# Root of the mono-repo
pnpm run lintWe use Vitest to run unit tests on workspaces listed under the packages folder.
For developping:
# Root of the mono-repo
pnpm run test:dev(You can also run this in specific package folders.)
For running all tests in the terminal:
# Root of the mono-repo
pnpm run testExamples projects found in the examples can also have tests. To run them all:
# Root of the mono-repo
pnpm run test:examplesIn an example project, you can run the following script if there are tests:
cd examples/vue3
pnpm run test:examplesTo develop new tests in an example project, you can use:
cd examples/vue3
pnpm run story:dev
# In another terminal
pnpm run test:dev-
Checkout a topic branch from a base branch, e.g.
main, and merge back against that branch. -
If adding a new feature:
- Add accompanying test case.
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
-
If fixing bug:
- If you are resolving a special issue, add
(fix #xxxx[,#xxxx])(#xxxx is the issue id) in your PR title for a better release log, e.g.fix: update entities encoding/decoding (fix #3899). - Provide a detailed description of the bug in the PR. Live demo preferred.
- Add appropriate test coverage if applicable.
- If you are resolving a special issue, add
-
It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging.
-
Make sure to follow the code style of the project.
-
Make sure tests pass!
-
Commit messages must follow the commit message convention so that changelogs can be automatically generated.