Design System Builder

Working demo · beta

Two decisions in. A validated design system out.

Pick a typeface and a brand colour. Get colour ramps, a semantic token layer, a type scale, spacing, motion, component styles and page sections — generated, checked for contrast and accessibility as you work, and exported as working HTML.

Not a template gallery and not a website builder. The system is generated and validated: every failure is clickable and lands on the control that fixes it.

Open the live demo → Read the documentation PIN-gated · synthetic projects

29s · recorded from the running demo, not a mockup

OKLCHPerceptual colour maths throughout; hex only at export.
WCAG + APCABoth contrast standards, live, in light and dark.
0 requestsThe exported HTML opens from a file with nothing to fetch.
177/183Acceptance tests run and passing in the build tracker.

The problem

A design system is a week of decisions most teams get wrong once and live with for years.

A founder or a developer picks a blue, picks a font, and then quietly makes four hundred more decisions by hand — every one of them a place for the system to become inconsistent or inaccessible.

Everything after the second decision should be derived, checked, and reversible. That is the whole product.
  • Ramps built by eye go muddy. HSL lightness is not perceptual, so the 700 of a yellow and the 700 of a blue are nowhere near the same weight. Yellow and cyan are in the acceptance tests for exactly this reason.
  • Contrast is checked at the end, if at all. By then the palette is in production, and the fix is a redesign rather than a slider.
  • Dark mode gets bolted on. Inverting a light theme produces glare and dead greys; the two themes need to be generated as siblings.
  • No semantic layer. Components that reference blue-600 instead of action-primary cannot be re-themed without a rewrite — which is why the semantic layer exists from the first commit here.
  • Handoff breaks. "Export to Figma" is a promise that fails on first use. Tokens are not paste-able as Figma Variables; that limit is stated in the UI rather than discovered by the user.

The product

A wizard with one decision per step, and a preview that never goes blank.

The start card asks three questions and builds a complete system before the user sees a single empty field. Every later step changes that system in place, with the live preview and the health score reacting on every keystroke.

1

Colour

One seed hex becomes OKLCH ramps from 50 to 950 with tapered chroma, a secondary and tertiary from published pairings, tinted neutrals, status colours that move away from a red brand, and light and dark semantic maps generated as siblings.

2

Type

About forty curated faces in seven classes with pairing reasons, a ratio-driven clamp() scale, per-step line height, letter spacing and measure, a live payload counter, and fallback metrics so nothing shifts when the web font lands.

3

Foundations

Spacing, radius with the nested rule, borders, brand-tinted shadows, breakpoints, grid, motion tokens with a bezier preview and an automatic reduced-motion block, icons, z-index layers. Every one has a default, so the step can be skipped.

4

Components & sections

Nine states for every interactive component, checked from a registry, and five kinds of page section in twenty types. No component references a primitive token; Tab reaches everything with a visible ring.

5

Validation

Contrast across theme × state × component, touch targets, German +35% and Arabic right-to-left inside real button widths, payload, reduced-motion coverage, tab order, heading hierarchy — one health score, every failure clickable.

6

Export

One self-contained HTML file or a four-file bundle with subset fonts, three generated pages, and a README. Zero console errors, zero network requests, Lighthouse accessibility 100. Tokens in DTCG, Style Dictionary, CSS, SCSS, JS/TS, Tailwind, Swift and XML.

The projects gallery: three cards, each showing its own colour ramps and type sample.
Projects — each system behind its own PIN
The colour step after changing the seed to a burnt orange: ramps, component gallery and health score all regenerated.
One seed change regenerates the whole system
The sections step with live thumbnails of hero, social proof, testimonial, feature and footer types.
Sections — five kinds, twenty types
The export step showing the HTML bundle, token formats and Figma paths.
Export — HTML, tokens, and three honest Figma paths

Architecture

One object, pure engines over it, and three doors out.

Server-rendered FastAPI with Jinja and HTMX. The whole system is one DesignSystem object per project, with immutable snapshots in SQLite behind /s/<id>. Vanilla JavaScript only where a browser API demands it.

Design System Builder architecture Two inputs and a snapshot store feed one DesignSystem model and the wizard shell. Four pure engines — colour, contrast, type and foundations — read the model. Their output drives component styles and page sections, which the validation layer checks. Three exporters produce HTML, token files and Figma artefacts. INPUT — TWO DECISIONS, PLUS A SNAPSHOT ID ON A SHARED LINK brand colourhex · picker · eyedropper · logo typefacecurated shortlist · ~40 faces /s/<id> snapshot store (SQLite) content-addressed, immutable · a project cookie restores the working copy model — DesignSystem object, per-project store, snapshots primitives (OKLCH) · semantic light + dark · components · sections · schemaVersion server-side undo/redo · validate(): one-level refs, both themes, versioned renames shell — Jinja wizard + HTMX live preview step rail · one decision per step preview swaps on any token change · dogfoods its own tokens ENGINES — PURE FUNCTIONS OVER THE MODEL colour OKLCH ramps 50–950, tapered chroma pairings · tinted neutrals · status light + dark semantic maps contrast WCAG 2.1 · APCA, hand-ported Fix walks lightness · CVD simulation zero unfixable failures, any hex type pairings with reasons · ratio scale clamp() fluid · payload counter fallback metrics, no layout shift foundations space · radius · border · shadow breakpoints · grid · icons · z-index motion + reduced-motion block SURFACES — BUILT ONLY FROM SEMANTIC TOKENS components — nine states each inputs · buttons · loading · feedback · navigation · data display no primitive references · keyboard everywhere · both themes sections and pages hero · social proof · testimonial · features · footer — twenty types 320 / 768 / 1440 · awkward copy · heading order · usage counted validation — beside editing, one health score, every failure jumps to its fix contrast across theme × state × component · touch targets · German +35% / Arabic RTL · payload · reduced motion · tab order · headings OUTPUT — THREE DOORS, NONE OF THEM ONE-CLICK-EVERYTHING export — HTML, the ship line single file or four-file bundle vanilla custom properties, oklch() + hex dark toggle with no flash · Lighthouse 100 tokens — every format DTCG first · Style Dictionary CSS · SCSS · JS/TS · Tailwind iOS Swift · Android XML · handoff sheet figma — three honest paths A: section SVG to clipboard, editable B: Tokens Studio JSON download C: companion plugin writes Variables developer: index.html, opens by double-click build pipeline: tokens.json and friends designer: editable layers and variables

the parts that run on every keystroke engines and surfaces inputs and outputs, not code

Requirements against reality

What is built, what is partial, and what is not started.

This table is generated from the internal build tracker, not written by hand. A row counts as built only when every leaf under it has had its acceptance test actually run — never on the strength of a commit message.

Generated from the build tracker on 8 September 2026: 177 of 183 acceptance tests run and passing. A row is green only when every one of its leaves has had its test run — not when the code looked finished.

RequirementLeaves provenState
Groundwork
D0 Decisions before any code5/5Built
v1 — generate and export
P0 Skeleton and data model12/12Built
P1 Color engine20/20Built
P2 Typography12/12Built
P3 Remaining foundations10/10Built
P4 Component styles10/10Built
P5 Page sections: five kinds, each with several types17/17Built
P6 HTML export and share — v1 ship line12/12Built
P7 Validation layer10/10Built
P8 Token exports and Figma6/9Partial
v2 — calm, presets, projects, content
V0 v2 · Calm redesign: less on screen, one decision at a time5/6Partial
V1 v2 · Presets, explore, contrast levels, history5/5Built
V2 v2 · Import an existing brand4/4Built
V3 v2 · Projects4/4Built
V4 v2 · Content and pages — v2 ship line4/4Built
V5 v2 · Component code3/3Built
V6 v2 · Platforms and data-viz3/3Built
V7 v2 · Reports2/2Built
V8 v2 · Icons and Figma1/2Partial
v3 — running the system
V9 v3 · Step 0 — projects page redesign3/3Built
W0 v3 · Theme axes and multi-brand4/4Built
W1 v3 · Adaptive colour5/5Built
W2 v3 · Agent-ready3/3Built
W3 v3 · Drift, lint and adoption4/4Built
W4 v3 · Versions and documentation site — v3 ship line5/5Built
W5 v3 · Application pages3/3Built
W6 v3 · Visual regression kit3/3Built
W7 v3 · Design-tool round trip2/3Partial

What is not finished

Every open or partial leaf in the tracker, all 6 of them (4 partial, 2 not started), with the tracker's own note. They cluster in one place: the parts of the Figma path that need a human inside Figma to confirm, plus the owner walk-through that only the owner can sign off.

Partial P8.5 Figma path A: per-section SVG to clipboard, editable layers
machine half done: clipboard carries SVG text with <text> layers, no raster, test_svg.py green in both schemes. The Figma paste itself needs a person with a Figma file; not done in this session
Partial P8.6 Figma path B: Tokens Studio JSON with import instructions
Tokens Studio JSON with / and TOKENS-STUDIO.md instructions ship in the token bundle; the import round-trip inside Tokens Studio needs a person with Figma; not done in this session
Not started P8.7 Figma path C (stretch): companion plugin writes real Variables
stretch, not started: a Figma plugin needs the Figma desktop app and a plugin manifest; the Export step says so in plain words
Not started V0.5 Owner walk-through: five tasks completed without help
waiting for the owner: pick a colour, change the mood, switch a hero type, fix a health failure, export
Partial V8.2 Figma plugin writes Variables with light and dark modes (carried from P8.7)
figma-plugin/ (manifest, payload.js, code.js, ui.html, README) in app and in the bundle; pytest test_plugin checks the manifest and a payload with one variable per semantic role and two modes. The manual Figma desktop run and its screenshot are the owner's; pa…
Partial W7.3 Plugin pull and Code Connect stubs
Plugin Pull: code.js reads local variables (aliases followed) into the tokens-studio shape and the UI shows it for import; react/codeconnect/<Name>.figma.tsx for every component with enum/boolean/string mappings and a README; pytest test_plugin and test_figma_…

Roadmap

What comes next, in the order it is planned.

The three shipped releases are above. These are the next pieces, and none of them is started; the dates are intentions rather than commitments.

Deployment

One codebase, two ways to run it.

The lanes differ only in where the compute sits and whether the data is real. Flipping between them is environment configuration, not a code change.

Lane 1

On premises

Runs on
Your own hardware, or a machine inside your network
Data
Your real projects, in a SQLite file you can copy and back up
Network
Binds to loopback; nothing leaves the box, no egress at all
Fonts
Subset and self-hosted at export, so the output calls no CDN

Your brand, your systems and your data stay on your hardware.

Lane 2

Cloud twin

Runs on
A small VPS or container host, up around the clock
Data
Synthetic demo projects only, reseeded when idle
Access
One demo PIN at the door, then a PIN per project
Ship
deploy/twin/: compose file, .env.example, DEPLOY.md

Nothing to install. Send a link and let the client drive it.

Exposure

One port, two surfaces

Site
/, /documentation.html, /public/* — public, static
App
Every other path — proxied to the application behind the demo PIN
Why
The application builds URLs in JavaScript, so it is served at the root rather than under a rewritten prefix
Secrets
In a gitignored env file; nothing in the repository

One process to run, one port to open, no tunnel required.

# the two processes behind this page
./demo/start.sh    # the unchanged app on 127.0.0.1:8011, pointed at demo/data by env alone
./start.sh         # the front door on :6784 — static site, PIN gate, proxy

# the three self-checks
python3 serve.py --check        # the site/app path split and the gate token
python3 demo/seed.py --check    # every demo project opens with its published PIN only
python3 make.py --check         # the feature matrix still matches the build tracker

Try it

The real application, on synthetic projects.

Not a sandbox and not a video: the same build, with three demo systems seeded so there is something to drive on the first click. Change a seed colour and watch the ramps, the component gallery, the sections and the health score regenerate together — then export the HTML and open it.

Open the live demo →

Demo access

Demo PIN (the door)090397
Northwind Health1111
Meridian Finance2222
Fold Editorial3333

Start with Northwind Health — it is the project the walkthrough uses. Everything you change is disposable: the corpus is synthetic and resets when the demo has been idle for an hour. Please do not put real brand material into it.