design-RFC-004 — Component preview tooling (Storybook-equivalent)
Evaluates 3 options for shipping a live, interactive component preview alongside the KDS site — Storybook proper, Ladle / Histoire (lighter alternatives), or a Koder-native HTMX-driven sandbox using the existing design-gen + templ pipeline. Recommendation: Koder-native v0; promote to external tooling later if breadth justifies.
designRFC004 — Component preview tooling
*tatus* v0.1.0 — Draft. Decision required to unblock further playground work; current state limits us to static demos.
R1 — Problem
KDS today renders static demos via templ (e.g., /components/buttons/ shows pre-rendered HTML for each Button variant). Users cannot:
- Toggle props live (size, density, state, variant) and see the
result update without page reload.
- Cycle through theme / preset / a11y modes from a single panel.
- See the per-language code snippet that would produce the demoed
variant alongside the rendered output.
Ticket tools/design-gen#046 (componentpropplayground) opened this direction in design-gen, but only for a handful of components. A proper system-wide solution needs a strategic choice.
R2 — Options evaluated
Option A — Storybook proper
Industry standard. Vast plugin ecosystem (a11y addon, viewport addon, docs addon, Chromatic visual regression). Used by Pajamas (GitLab), Polaris (Shopify), Carbon (IBM), many others.
*ros*
- Mature, well-known, no learning curve for new contributors.
- Plugin ecosystem covers a11y / viewport / docs / interactions / etc.
- Per-component stories scale to thousands without engineering effort.
*ons*
- Heavy: ~200MB node_modules, multi-minute cold builds.
- Conflicts with
policies/self-hosted-first.kmdG2 (depends onexternal infra for Chromatic-style services if we adopt those).
- Adds a second JS runtime alongside the existing templ + Go pipeline
(operational overhead).
- Per-component story authoring becomes a maintenance burden as
components multiply (current 30+ component specs each need 5–10 stories minimum).
Option B — Ladle / Histoire (lighter alternatives)
*adle*(Uber): Vite-based, faster than Storybook (~10× cold build), fewer plugins but covers the common 80%.
*istoire*(Vue ecosystem origin, framework-agnostic now): even lighter, focused on Vue+Svelte+React; KDS would need to confirm templ/Go-rendered story support.
*ros*
- 80% of Storybook's UX at 10–30% of the build cost.
- Lower operational overhead.
- Better fit for our small contributor base.
*ons*
- Smaller community → some addons missing or stale.
- Still adds a JS runtime to the build pipeline.
- Story-authoring burden largely the same as Storybook.
Option C — Kodernative HTMX sandbox via designgen
Extend designgen with a binary) sub-command that, for each component spec, emits an interactive HTML page driven by HTMX (already a dependency) + a per-page JSON descriptor of variants. The "story" is just a templ template that swaps inner HTML on prop-toggle clicks.cmd/playground (or in
*ros*
- Zero new dependency. Reuses templ + HTMX already in the stack.
- Build cost is design-gen's normal cost (current ~18s full
generation; per-component playground adds linear scaling).
- 100% self-hosted; no external service dependency.
- Per-component "story" is just a templ snippet — natural extension
of existing design-gen patterns.
- AI agents can introspect playground state via the existing
/api/v1/mcp/descriptor.jsonwe already emit (#058).
*ons*
- Loses external ecosystem (Chromatic visual regression, story-format
conventions).
- Each new component requires hand-written templ playground tile.
- Plugin authors targeting Storybook do NOT plug in.
R3 — Decision criteria (per policies/self-hosted-first.kmd)
| Gate | A (Storybook) | B (Ladle) | C (Koder-native) |
|---|---|---|---|
| G1 — own infra | ⚠ relies on Chromatic for vis-regression | ⚠ similar | ✅ |
| G2 — own toolchain | ⚠ external JS toolchain | ⚠ external JS toolchain | ✅ |
| G3 — paritythreshold | matches when adopted | partial | reaches MVP fast |
| G4 — faster than alt | builds slower than design-gen normal | builds 3-5× faster than A | builds fastest (reuses pipeline) |
| G5 — owner approval | TBD | TBD | TBD |
R4 — Recommendation
*dopt Option C (Koder-native HTMX sandbox) for v0* with the following migration path:
- *0 (1–2 weeks)* design-gen ships
playgroundrendering forthe 5 most-used components (Button, Card, EmptyState, DataTable, Combobox). Per
prop toggle via HTMX; perlanguage code snippet panel via existinginternal/apidata. - *1 (1–2 months)* extend to all components; add density mode
+ a11y mode + preset switching in the toolbar.
- *e-evaluation (6 months in)* if KDS contributor count grows
and story
authoring becomes bottleneck, reopen this RFC to evaluate Storybook adoption as overlay (keep Koder-native as default; Storybook for power users who want addons).
This honors self-hosted-first.kmd while shipping fast. Promotion to external tooling is reversible if the cost-benefit shifts.
R5 — Implementation tickets (post-ratification)
Subtickets to open in designgen once this RFC ratifies:
- design-gen#XXX —
cmd/playgroundscaffolding (HTMX shell). - design
gen#XXX — Perspec playground template (1 ticket percomponent picked for v0).
- design-gen#XXX — Toolbar (density / a11y mode / preset switcher).
R6 — Cross-references
- Coordinates with
tools/design-gen#046(which delivered theper
component propplayground groundwork). - Coordinates with
projects/koder-stack#157(Figma kit) — Figmastays the design source of truth; this RFC is about the live code preview, separate from the design tool.
- Coordinates with
projects/koder-stack#158(cross-language tokendistribution) — playground consumes the same tokens.
Não-escopo
- Component testing framework (separate spec).
- Visual regression testing infrastructure (separate ticket once
the playground exists).
- Per
product playground (only KDSscoped here; products may buildtheir own).