Skip to content

Configuration Reference

Learn more about configuring Poveste here.

plugins

Array of plugins. Learn more about official plugins and how to develop them.

ts
import { HstNuxt } from '@poveste/plugin-nuxt'
import { HstVue } from '@poveste/plugin-vue'

export default defineConfig({
  plugins: [
    HstVue(),
    HstNuxt(),
  ],
})

outDir

string - Default: '.poveste/dist'

Output directory.

ts
export default defineConfig({
  outDir: '.poveste/dist',
})

storyMatch

string[] - Default: ['**/*.story.vue', '**/*.story.svelte']

Glob patterns for story files to include.

ts
export default defineConfig({
  storyMatch: [
    '**/*.story.vue',
  ],
})

Use src/**/*.story.vue to prevent search errors in binary files (e.g., in iOS or Android folders) when using Ionic Capacitor.

storyIgnored

string[] - Default: [ '**/node_modules/**', '**/dist/**' ]

Glob patterns to ignore files while searching for story files. Patterns you set are added to the defaults, so node_modules and dist stay ignored without being spelled out again.

ts
export default defineConfig({
  storyIgnored: [
    '**/fixtures/**',
  ],
})

supportMatch

SupportMatchPattern[] - Default: []

Which support plugin renders a story, once storyMatch has decided it is one. The two are separate globs: storyMatch is what is a story, supportMatch is who renders it. Each entry is { id, patterns, pluginIds }, where patterns are matched against the absolute path.

Plugins contribute the defaults, and they match on extension rather than on the .story. infix:

idpatternspluginIdsFrom
vue**/*.vuevue3@poveste/plugin-vue
svelte**/*.sveltesvelte4@poveste/plugin-svelte
vanilla**/*.jsvanillabuilt in

Entries merge by id rather than replacing: reuse an existing id and your patterns and pluginIds are appended to it, so the plugin's own are kept. A new id adds a new entry, which is what you want only if you are pointing at a plugin nothing else claims.

A story matching storyMatch and no supportMatch entry fails collection with No support plugin found for file …. That is the reason to set this key — TypeScript stories, for instance, since the built-in entry claims **/*.js alone.

ts
export default defineConfig({
  storyMatch: ['**/*.story.ts'],
  supportMatch: [
    // Same `id` as the built-in entry, so this extends it rather than
    // competing with it.
    { id: 'vanilla', patterns: ['**/*.ts'], pluginIds: ['vanilla'] },
  ],
})

tree

Object - Default: { file: 'title', order: 'asc' }

How to generate the story tree.

Learn more: Vue 3

Properties:

  • file: 'title' | 'path' | ((file: TreeFile) => string[]): How to get the path of a story.
  • order: 'asc' | ((a: string, b: string) => number): How to sort the stories.
ts
export default defineConfig({
  tree: {
    file: 'title',
    order: 'asc',
  },
})

theme

Object

Customize the look of the book.

Learn more

Properties:

  • title: string: Main page title. For example: 'Acme Inc.'
  • logo: Object: Logo configuration.
    • square: string: Square logo image without text.
    • light: string: Full logo for light theme.
    • dark: string: Full logo for dark theme.
  • favicon: string: Href to the favicon file (not processed by Vite). Put the file in the public directory.
  • colors: Object: Customize the colors. Each color should be an object with shades as keys.
  • logoHref: string: Add a link to the main logo
  • darkClass: string: Class added to the story preview when dark mode is enabled (default is 'dark'). The story preview has its own color scheme, picked from the preview appearance dropdown in the toolbar (System / Light / Dark) and independent from the color scheme of the app around it.
  • defaultColorScheme: 'light' | 'dark' | 'auto': Default color scheme for the app and for the story preview. 'auto' will use the system preference.
  • hideColorSchemeSwitch: boolean: Hides the dark mode button in the toolbar, and the color scheme buttons in the preview appearance dropdown — the story preview then stays on defaultColorScheme.
  • storeColorScheme: boolean: Enable persistence of the color scheme in the browser's local storage.
ts
import { defaultColors } from 'poveste'

export default defineConfig({
  theme: {
    title: 'Acme Design System',
    favicon: '/my-favicon.svg',
    logo: {
      square: '/src/img/logo-square.svg',
      light: '/src/img/logo-light.svg',
      dark: '/src/img/logo-dark.svg',
    },
    colors: {
      primary: defaultColors.cyan,
    },
    logoHref: 'https://acme.com',
    defaultColorScheme: 'light',
    hideColorSchemeSwitch: true,
    storeColorScheme: false,
  },
})

setupFile

string | { browser: string, server: string }

Setup file exporting a default function executed when setting up each story preview.

Import custom CSS files from this file.

Learn more

ts
export default defineConfig({
  setupFile: '/src/poveste-setup.ts',
})

If you need a different version for the NodeJS server (while collecting stories), you can use an object:

ts
export default defineConfig({
  setupFile: {
    browser: '/src/poveste-setup.ts',
    server: '/src/poveste-setup.server.ts',
  },
})

This can be useful if you need to exclude some imported libraries that only works in the browser.

isolateStyles

boolean - Default: true

Master switch for CSS isolation between Poveste's chrome and your stories. When enabled, your CSS imported via setupFile is scoped to story containers, chrome CSS is scoped away from them, and grid items render in iframes.

See the Styles & CSS guide for details.

ts
export default defineConfig({
  isolateStyles: false, // restore pre-isolation behaviour
})

globalStyles

string[] - Default: []

CSS files to load into the main app (not into stories). They are wrapped in @layer poveste-user-globals, which keeps them lower priority than chrome rules. Use for design tokens or anything you want to apply across both chrome and stories.

ts
export default defineConfig({
  globalStyles: ['./src/styles/tokens.css'],
})

defaultStoryProps

Object

Default values for story props.

ts
export default defineConfig({
  defaultStoryProps: {
    icon: 'carbon:assembly-reference',
    iconColor: '#00c5a5',
    layout: {
      type: 'grid',
      width: 300,
    },
    responsiveDisabled: true,
    autoPropsDisabled: true,
  },
})

autoPropsDisabled applies to Vue and Svelte stories. Automatic prop detection does not run for vanilla stories, so setting it here changes nothing for them.

setupCode

string[] - Default: none

Setup modules injected into the story sandbox as source, for plugins that have to generate code rather than point at a file. @poveste/plugin-nuxt uses it to import the app's CSS and call setupNuxtApp with the resolved runtime config, neither of which exists as a file a book could name.

Set by plugins, not by books. Use setupFile instead — it takes a path, runs in both the app and the sandbox, and is the supported surface. Entries are concatenated rather than replaced, so a book assigning this does not remove what a plugin added.

sandboxDarkClass

string - Default: none - Deprecated

Class added to the story preview's html root in dark mode. Superseded by theme.darkClass, which applies to every render path — inline, iframe and grid — rather than only the sandbox.

Still honoured where it is set, and emitted alongside theme.darkClass rather than instead of it, so a book that set both gets both classes. A book setting only theme.darkClass gets that one class everywhere (#126). Nothing needs doing on upgrade unless you set this key; if you did, move the value to theme.darkClass and delete it.

responsivePresets

Array

Predefined responsive sizes for story playgrounds.

Each object in the array is a preset with the following properties:

  • label: string: Label for the preset.
  • width: number: Width of the preset (pixels).
  • height: number | null: Height of the preset (pixels). null sizes the preview to the available space, which is what four of the defaults below do.

Default values are shown in the example below:

ts
export default defineConfig({
  responsivePresets: [
    {
      label: 'Mobile (Small)',
      width: 320,
      height: 560,
    },
    {
      label: 'Mobile (Medium)',
      width: 360,
      height: 640,
    },
    {
      label: 'Mobile (Large)',
      width: 414,
      height: 896,
    },
    {
      label: 'Tablet',
      width: 768,
      height: 1024,
    },
    {
      label: 'Laptop (Small)',
      width: 1024,
      height: null,
    },
    {
      label: 'Laptop (Large)',
      width: 1366,
      height: null,
    },
    {
      label: 'Desktop',
      width: 1920,
      height: null,
    },
    {
      label: '4K',
      width: 3840,
      height: null,
    },
  ],
})

backgroundPresets

Array

Background color of the story preview.

Each object in the array is a preset with the following properties:

  • label: string: Label for the preset.
  • color: string: Color of the preset.
  • contrastColor?: string: Contrast color of preset

Default values are shown in the example below:

ts
export default defineConfig({
  backgroundPresets: [
    {
      label: 'Transparent',
      color: 'transparent',
      contrastColor: '#333'
    },
    {
      label: 'White',
      color: '#fff',
      contrastColor: '#333'
    },
    {
      label: 'Light gray',
      color: '#aaa',
      contrastColor: '#eee'
    },
    {
      label: 'Dark gray',
      color: '#333',
      contrastColor: '#ccc'
    },
    {
      label: 'Black',
      color: '#000',
      contrastColor: '#fff'
    },
  ],
})

You can use the current contrast color via the css variable --poveste-contrast-color. The histoire-era --histoire-contrast-color is still set as a deprecated alias:

css
.my-class {
  color: var(--poveste-contrast-color);
}

defaultBackgroundColor

string - Default: 'transparent'

Initial background color used for story previews before the user picks one from the dropdown. Should match a color from backgroundPresets to also highlight the matching entry.

ts
export default defineConfig({
  defaultBackgroundColor: '#fff',
})

The value is applied on every load — including to users with previously stored settings, and when you change it — until the user picks a color from the toolbar dropdown. From that point on their pick wins and this option is ignored.

autoApplyContrastColor

boolean - Default: false

Automatically apply the contrast color to the story preview text.

ts
export default defineConfig({
  autoApplyContrastColor: true,
})

UseHeadInput - Default: undefined

Extra <head> tags injected into the Poveste app and the story sandbox iframe. Same input shape as Nuxt's useHead, rendered at build time. Use for global stylesheets, web fonts, analytics snippets, or any meta tag that needs to apply in both contexts.

ts
export default defineConfig({
  head: {
    link: [
      { rel: 'preconnect', href: 'https://fonts.googleapis.com' },
      { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Poppins&display=swap' },
    ],
    meta: [
      { name: 'theme-color', content: '#10b981' },
    ],
  },
})

markdown

(md: MarkdownIt) => MarkdownIt | Promise<MarkdownIt>

Customize the markdown-it renderer.

ts
export default defineConfig({
  markdown: (md) => {
    md.use(SomeMarkdownItPlugin)
  },
})

routerMode

'history' | 'hash' - Default: 'history'

Changes the router mode:

  • 'history': HTML 5 history mode with cleaner URLs.
  • 'hash': Use the hashtag hack in the URL to support more servers and static hosting services.
ts
export default defineConfig({
  routerMode: 'hash',
})

vite

ViteConfig | ((config: ViteConfig, env: ViteConfigEnv) => void | ViteConfig | Promise<void | ViteConfig>)

Vite config override.

ts
export default defineConfig({
  vite: {
    server: {
      port: 3042,
    },
  },
})

viteIgnorePlugins

string[]

List of Vite plugin names to exclude for Poveste.

ts
export default defineConfig({
  viteIgnorePlugins: [
    'vite-plugin-example',
  ],
})

viteNodeTransformMode

{ web?, ssr? }

Determine the transform method of modules

viteNodeTransformMode.ssr

RegExp[] - Default: [/\.([cm]?[jt]sx?|json)$/]

Use SSR transform pipeline for the specified files.
Vite plugins will receive ssr: true flag when processing those files.

viteNodeTransformMode.web

RegExp[] - Default: modules other than those specified in transformMode.ssr

First do a normal transform pipeline (targeting browser), then do a SSR rewrite to run the code in Node.
Vite plugins will receive ssr: false flag when processing those files.

When you use JSX as component models other than React (e.g. Vue JSX or SolidJS), you might want to config as following to make .tsx / .jsx transformed as client-side components:

ts
export default defineConfig({
  viteNodeTransformMode: {
    web: [/\.[jt]sx$/],
  },
})

viteNodeInlineDeps

RegExp[]

Transpile dependencies when collecting stories on Node.js.

For example, if you have a dependency that contains ESM code but Node tries to load it in CommonJS context, you might have this kind of error:

.../my-project/node_modules/.pnpm/some-library@1.0.0/lib/esm/index.js:3
export function foo() {
^^^^^^

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    ...

We can see that the some-library (made-up name) is misconfigured and Node treats it as CommonJS code (the cjs/loader is being used) but it contains ESM code. Hence the error.

ts
export default defineConfig({
  viteNodeInlineDeps: [
    /some-library/,
  ],
})

collectMaxThreads

number - Default: available cpus

Number of maximum threads used to collect stories (both for development and building). Threads count will never go above this limit but might be lower.

ts
export default defineConfig({
  collectMaxThreads: 4,
})

build

Object

Build-time options, applying to poveste build only.

build.excludeFromVendorsChunk

(string | RegExp)[] - Default: []

Dependencies to keep out of the single vendors chunk that everything in node_modules is bundled into by default. Use it for a dependency large enough that loading it with the first story costs more than fetching it separately.

ts
export default defineConfig({
  build: {
    excludeFromVendorsChunk: ['lottie-web', /^@my-org\//],
  },
})

Released under the MIT License. Updates on Bluesky and X.