Design systems
Ship components and the config they were built against as one package.
A Panda design system is a package of components plus the config they were built against: tokens, recipes, and
the generated styled-system, published as one unit with panda lib.
Without it, the library and each app generate separate styled-system folders. That puts two copies of the runtime
(css(), cva(), the JSX factory) in the bundle, with no shared token contract between them. With it, apps load
the package's theme, reuse the styles the package already extracted, and stay typed against the merged theme.
Apps that run Panda opt in with one field:
panda.config.ts
export default defineConfig({
designSystem: '@acme/ds'
})Pick a path
Where the package lives
panda lib is the same either way. Only watch and publish differ.
In a workspace, depend on the source and run panda lib --watch. See
Monorepo workflow.
packages/app/package.json
{
"dependencies": {
"@acme/ds": "workspace:*"
}
}On npm, install a published version and run panda lib before npm publish. See
Publishing.
apps/web/package.json
{
"dependencies": {
"@acme/ds": "^1.0.0"
}
}Storybook
Stories that call recipes run Panda, even when production only imports a CSS file. That is why a story can look right while the app looks blank. Include the story files, or pre-generate variants:
panda.config.ts
export default defineConfig({
designSystem: '@acme/ds',
include: ['src/**/*.{ts,tsx}', '.storybook/**/*.{ts,tsx}'],
staticCss: {
recipes: '*'
}
})Storybook covers the package's own stories. Using Storybook covers adding Panda to an app's Storybook.
Writing the components
Once the package exists:
- Wrap headless libraries for compounds and single
styled()wrappers - Tracking JSX so
<Button size="lg" />still extracts - Isolated declarations to keep CSS out of your
.d.ts
Governing the system
Once apps depend on it:
- Linting to flag raw values where a token exists
- Analyze usage to see which tokens apps actually use
- Deprecations to warn consumers before a removal