Variants & auto-generation
How variants.json drives the build, and why the whole catalogue is generated from the content.
You author three files per component — component.css, macro.njk, variants.json.
Everything else (the rendered variants, the bundled stylesheet, the Storybook) is
generated from those files. This page explains how, and why it's done that way.
How the variant logic works
Each entry in a component's variants.json is a named prop set rendered through the
component's macro. Given:
{
"macro": "button",
"variants": [
{ "name": "Primary", "filename": "primary", "props": { "label": "Continue", "variant": "primary" } }
]
}the generator calls the button macro with { "label": "Continue", "variant": "primary" }
and writes the rendered markup to primary.html in the component folder. Add a variant by
adding an entry; there's no other file to edit.
The build pipeline
npm run build runs three steps, in order:
generate-variants.mjs— for each component, renders the macro with each variant's prop set and writes<filename>.html. (These are the GENERATED files you never edit.)generate-stories.mjs— concatenatesglobal.css+ every component'scomponent.cssinto the version'sstyle.css, and writes one Storybook story per variant.build-storybooks.mjs— builds a Storybook once per design-system version.
During local development the dev server also recompiles /ds/<version>/style.css on
every request, so edits to a component.css show up live without a full rebuild.
Why auto-generate
The design system is generated from the content itself — the authored CSS, the macro,
and the variant prop sets. Because the storybook and the rendered <variant>.html pages
are produced from those same three files, they can never drift from the source:
there's no separate, hand-maintained component catalogue to keep in sync. One source of
truth, regenerated on every build.
Just as important, authoring needs no framework or build tooling — only CSS, Nunjucks, and JSON. That keeps the barrier to authoring low and the whole design system portable: a version is just a folder you can copy, re-theme, and freeze.
Don't
- Edit a generated
<variant>.html. It's overwritten on every build — editmacro.njkorvariants.jsoninstead. - Edit
style.cssdirectly. It's generated fromglobal.css+ the component CSS. - Add story-scaffolding CSS (e.g.
.story-grid,.frame-demo) to acomponent.css. That's storybook layout, not the component. - Reach across versions. A component in one version must never reference paths inside another. Each version is a self-contained snapshot.