Every project is created with a DESIGN SYSTEM folder holding eight files: Colors, Fonts, Images, Audios, Videos, Spacing, Radius and Themes. Together they are the vocabulary everything else is styled from.
A hard-coded value is a decision you have to find again. Type #0A84FF into forty places and the fortieth is where the rebrand breaks.
A token is that decision made once and named. Bind a style property to a token and the property follows the token — change the token, and every element bound to it changes with it.
Tokens are also the unit a theme switches. Because a bound property points at a name rather than a value, one project can hold several complete sets of values against the same names.
The Colors file has three tabs, and the tab is the tier:
PRIMITIVE — a literal value, the raw palette — blue-500 = #0A84FF.
SEMATIC — a reference to a primitive, named for its job — primary → blue-500.
ALIAS — a reference to a semantic, named for its place — button-bg → primary.
The chain only runs one way — alias to semantic to primitive — and a primitive may only hold a literal. That restriction is what keeps a palette from becoming a web of mutual references nobody can unpick. (Resolution follows up to ten hops before giving up — a guard against cycles, not a budget to spend.)
A color token does not have to be flat. It can be a solid with alpha, a linear gradient, a radial gradient, or a reference to another token — so a brand gradient is a token like any other, and re-themes like one.
SEMATIC colors are the tier that carries per-theme and per-layer values. Primitives are your fixed palette; semantics are where a theme does its work.
Fonts split into two things, and the distinction is the one people trip on.
A TYPE is a family and the weights and styles it ships with. Upload a font file — .ttf, .otf, .woff or .woff2 — and it becomes a real @font-face in your exported CSS, served from your own assets.
A TEMPLATE is a usage: family, weight, style and size bound together under one name, like heading-lg or body. Binding one template to an element sets all four at once — that is how type reaches a design.
There is no standalone font-size token. Type sizes reach a component through a template, and a template's size is in pixels.
The Images file holds SVG and icon artwork as tokens — upload or paste artwork, and reference it the way you reference a color. Like fonts, it splits into TYPES (the artwork) and TEMPLATES (a usage of it), so an icon token can point at different artwork per theme.
The Audios file holds named sounds — upload a file or point at a URL. A sound is played from logic: the Play Sound action (with Stop and Stop All) can hang off any element event or fire at a moment on a timeline, so a click sound and a timeline sting are wired the same way.
The Videos file holds video tokens by URL, each with a poster taken from your Images tokens. It stores no video bytes on purpose, and there is no video element to place yet — the tokens are the vocabulary; playback surfaces are still to come.
Neither file is themeable, and neither has the TYPES/TEMPLATES split: a sound or a video cannot be emitted as a CSS custom property, so a per-theme value would have nowhere to resolve.
Spacing and Radius are named scales — sm, md, lg rather than 8, 16, 24. Bind padding, margin or corner radius to one and the rhythm of a layout becomes a decision you can change centrally.
Radius binds per corner as well as all at once, and spacing binds per side.
Spacing and radius are not themeable. They are emitted once, globally, outside the per-theme blocks. Color and typography change with a theme; geometry does not — so a "compact" and "comfortable" density pair is not something themes can express.
Any token file can be grouped into named sections. A section is not just visual tidying: it becomes a nested object in the exported code, so Colors.brand.primary reads the way the file looks.
Every token and every section can carry a Note — the reason a token exists, kept next to the token instead of in someone's head. Agents working over MCP read those notes too.
A theme is a complete set of values against the same token names. You are not limited to light and dark: themes are a list you add to, and Default is always present as the base.
Themes cascade. Each theme has a path, and a theme inherits every value from the themes sorted before it, overriding only what it defines. So a dark-high-contrast theme built after dark starts as dark and changes the handful of tokens that actually differ — you build variations, not copies. The path is yours to edit.
Layers 1–4 are a second axis, at right angles to theme. The same token can hold a different value per layer, which is how nested surfaces get progressively lighter or darker without a token per depth. Theme answers which palette; layer answers how deep in the stack this surface sits.
Duplicating a theme snapshots its resolved values — including everything it inherited — so the copy is a real starting point rather than an empty shell.
You can preview any theme on the canvas from the dropdown in the component header.
Canvas theme selection is preview only. It does not set a project default, and export always emits every theme. Layers 2–4 have no editor preview at all — they are authorable in the token files and take effect in exported code.
Tokens become CSS custom properties, emitted per theme and per layer, plus typed TypeScript helpers — Colors, Fonts, Spacing, Radius, SVGs and Themes — so token names are autocompletable and checked at compile time rather than guessed as strings. Audio tokens export as design-system/audios.ts, an Audios map plus the small playback runtime the Play Sound action calls into. Video tokens do not reach the export yet.
Theme switching is generated too. Your export includes a ThemesLayer provider and a context exposing setTheme and setLayer, so changing theme at runtime is a class swap on a wrapper — no re-render of your tree, no second stylesheet. This site runs on exactly that mechanism.
For colors, font templates and image templates, a theme flip really is a variable swap. Spacing and radius are emitted once and do not participate.
There is no automatic dark mode. A theme is a class you switch; wiring it to
prefers-color-schemeis your app's job.
Every token file is addressable over MCP — colors, fonts, images, audios, videos, spacing, radius, themes and sections all have tools, and design-system-get reads back every theme × layer cell. An agent can also point at a live website and derive a starting palette, type scale and spacing rhythm from it.
See MCP tools.
Components — the unit these tokens get applied to.
How export works — what the rest of a project becomes.
Export your code — getting the CSS variables and helpers into your app.