Design tokens for AI-built websites, in the W3C format

Design tokens in the W3C DTCG format, the three tiers, and why a model handed a tokens file builds every page on the same values instead of guessing.

A tall stack of thin glass plates on pure black, perfectly aligned and evenly spaced, each lit along its edge in green so the stack reads as one ordered column of light.
Every layer the same thickness, because every layer reads the same values.

Design tokens are named design decisions, such as a color, a size, a duration or an easing curve, stored as data so that every tool and every page reads the same value. For a website built with AI they solve one specific problem. A model handed a tokens file and told to use nothing else has one palette, one type scale and one set of curves to build every page from, while a model handed adjectives makes a fresh guess in every session.

Below are the W3C community format, which reached its first stable version in October 2025, the three tiers most systems use, and a way to hand tokens to a model so that the output can be checked rather than trusted.

What a design token is#

A token has three parts: a name, a value and a type. color.accent is a name, #B3421C is the value and color is the type. On the web, tokens are usually compiled into CSS custom properties such as --color-accent, and every component reads those properties instead of holding its own values.

The token is the source and the CSS variable is one output. The same file can generate custom properties for a site, constants for a native app and a plain list a model reads at the top of a prompt. The decisions live in one place, in a format any tool can parse, which is what makes tokens more useful than a stylesheet of variables.

For a website, these are the decisions worth tokenizing:

  • Color, by role: ground, text, muted text, accent, surface, border.
  • Type: families, the sizes of the scale, weights and line heights.
  • Space: the steps of the spacing ramp, from component padding to section rhythm.
  • Shape: radii and shadows, if the design uses them.
  • Motion: durations and easing curves, so every element moves on the same timing.

Every Thanor design carries this kind of value set inside its art direction, written as hex colors, a type scale, spacing and easing curves with durations. Two where color does most of the work:

The W3C format, version 2025.10#

The Design Tokens Community Group published the first stable version of its specification, 2025.10, on 28 October 2025 (W3C announcement). It is a Final Community Group Report: the Format Module states that it is not a W3C Standard and not on the W3C Standards Track. It is stable, and it is split into three modules: Format, Color and Resolver.

The rules that matter in practice:

  • Files use .tokens or .tokens.json, served as application/design-tokens+json.
  • Properties that start with $ are reserved: $value, $type, $description, $extensions, $deprecated. A $type on a group applies to the tokens inside it.
  • Aliases use curly braces, {color.ink}, and resolve to that token's value. A $ref JSON Pointer can reach inside a value.
  • Types include color, dimension, fontFamily, fontWeight, duration, cubicBezier and number, plus composites such as border, transition, shadow, gradient and typography.

A small file in that shape:

json
{
  "color": {
    "$type": "color",
    "ink":    { "$value": { "colorSpace": "srgb", "components": [0.0706, 0.0627, 0.0549], "hex": "#12100e" } },
    "paper":  { "$value": { "colorSpace": "srgb", "components": [0.9804, 0.9686, 0.9490], "hex": "#faf7f2" } },
    "clay":   { "$value": { "colorSpace": "srgb", "components": [0.7020, 0.2588, 0.1098], "hex": "#b3421c" } },
    "accent": { "$value": "{color.clay}" },
    "text":   { "$value": "{color.ink}" }
  },
  "space": {
    "$type": "dimension",
    "1": { "$value": { "value": 8, "unit": "px" } },
    "2": { "$value": { "value": 16, "unit": "px" } },
    "3": { "$value": { "value": 24, "unit": "px" } }
  },
  "motion": {
    "enter-duration": { "$type": "duration", "$value": { "value": 560, "unit": "ms" } },
    "enter-curve": { "$type": "cubicBezier", "$value": [0.16, 1, 0.3, 1] }
  }
}

Colors are objects with a color space and components, with hex as an optional fallback; dimensions and durations are a number plus a unit. On tooling, Style Dictionary's documentation says it has had first-class support for the format since version 4, and that full support for 2025.10 is still in progress for version 5, so check how your transformer reads the new color objects before you rely on them.

Three tiers of tokens#

Many token systems arrange values in three tiers, and each tier points only at the one below it.

TierAlso calledWhat it holdsExample
PrimitiveReference, globalRaw valuescolor.clay is #B3421C
SemanticSystem, aliasRolescolor.accent points to {color.clay}
ComponentComponentOne element's use of a rolebutton.background points to {color.accent}

Google's Material Web theming guide describes the same structure: reference tokens hold concrete values, system tokens define the decisions and roles that give a design system its character, and component tokens are attributes assigned to elements, as in --md-sys-color-primary and --md-filled-button-container-color.

The rule that makes tiers worth having is that components never point at primitives. A rebrand then means changing primitives, and dark mode means remapping the semantic tier, while every component stays untouched. The DTCG Resolver Module formalizes the second case, with sets of tokens, modifiers such as light and dark, and an order that decides which wins.

For a model, the semantic tier is the one to show. It is short, its names say where each value goes, and it is the layer a generated page gets wrong when nobody wrote it down. Its names matter as much as its values, because the model reads the names. Four conventions that read well to people and to models alike:

  • Category, then role, then state: color.text-muted, color.accent-hover.
  • Sizes by step, not by pixel: type.step-3 rather than type.31, so the scale can change without a rename.
  • Motion by purpose: motion.enter-duration, motion.hover-curve.
  • Whole words: no abbreviation the model has to guess, such as clr or bg2.

Why tokens make a model consistent#

A model building a page without tokens tends to fill every unstated value with what it has seen most often, which is why generated sites converge on the same look. Tokens change four things about that.

  1. The choices become a closed list. Asked for a muted text color, the model picks a name from the file instead of inventing a gray.
  2. The names carry intent. color.text-muted says where a value belongs in a way #6E6459 alone does not.
  3. The output can be checked. A component holding a raw hex or a raw duration is visibly breaking the rule, and a linter can find it.
  4. The file outlasts the conversation. A new session remembers nothing of yesterday's choices; a tokens file at the top of the prompt brings all of them back.

Model makers point the same way. Anthropic's public frontend design skill tells Claude to plan a compact token system, with a base palette of 4 to 6 named hex values and the typefaces with their roles, before writing any code. Claude Design builds a team's design system by reading its codebase and design files and then reuses its colors, typography and components. The gap between phrasing and specification explains why a list of values beats a paragraph of style guidance.

A small semantic tier is enough for a whole site. Two designs where very few colors carry a strong look:

How to hand tokens to a model#

1. Write the primitives and the semantic tier#

Start with the semantic tier and add only the primitives it needs. Five to seven color roles, the seven sizes of a type scale, five or six spacing steps and two motion pairs cover a typical marketing site. What changes between a cheap and an expensive site shows how much of the difference sits in exactly those values.

Motion can be one composite token per purpose, using the format's transition type, which bundles a duration, a delay and a curve:

json
{
  "motion": {
    "hover": {
      "$type": "transition",
      "$value": {
        "duration": { "value": 160, "unit": "ms" },
        "delay": { "value": 0, "unit": "ms" },
        "timingFunction": [0.33, 1, 0.68, 1]
      }
    }
  }
}

2. Generate the custom properties#

Compile the file with a transformer such as Style Dictionary, or ask the model to convert it once and check the result by hand:

css
:root {
  --color-text: #12100e;
  --color-ground: #faf7f2;
  --color-text-muted: #6e6459;
  --color-accent: #b3421c;
  --space-1: 8px; --space-2: 16px; --space-3: 24px;
  --motion-enter-duration: 560ms;
  --motion-enter-curve: cubic-bezier(0.16, 1, 0.3, 1);
}

3. Put the rule in the prompt#

text
Use only the custom properties defined in tokens.css. Never write a hex color,
a px font size, a duration or a cubic-bezier inside a component. If a value you
need is missing, stop and name the token you would add instead of inventing it.

Claude Code prompts for UI and vibe design both apply this rule to a full build.

4. Keep the names, change the values#

When the next project starts, copy the file, change the primitives and leave every semantic and component name as it is. The components, the prompt and the lint rules then carry over untouched, and only the look moves. Version the file with the project, with a git tag or a version in the file name, so that when a client asks why a color changed you can say which build used which values.

5. Lint what comes back#

Run grep -rnE "#[0-9a-fA-F]{3,8}" src/components and grep -rnE "[0-9]+ms" src/components. Every hit is worth a look, and most will be values the model invented. In a stylesheet pipeline, Stylelint's color-no-hex rule does the first check automatically. The fix is always one of two: replace the value with a token, or add the token on purpose.

Mistakes that make tokens useless#

Tokens fail in a few predictable ways, and every one of them shows up quickly when a model is the one reading the file:

  • Semantic names that describe the value. color.orange as the accent has to be renamed the day the brand turns blue. Name the role: color.accent.
  • A primitive ramp with no semantic tier. Ten shades of twelve hues give a model 120 options and no instruction, so its choice is close to arbitrary. Expose the roles, keep the ramp behind them.
  • No motion tokens. Durations and curves are where generated sites often fall back to one stock transition. Two named pairs, entrance and hover, fix it.
  • Dark mode by duplicating components. Remap the semantic tier instead, which is the case the Resolver Module was written for.
  • Tokens without direction. Tokens fix values. They say nothing about the section order, the signature moment or the media, so a page still needs a specification around them.

That last point is why the Thanor library ships designs as full art direction rather than as token files: the values and the decisions that use them, together. If you are setting up a studio around this, how to start a web design business with AI puts a house tokens file at step 3, and cloning a design legally uses the same idea to rebuild what you admire in your own values. The approach is the same one a 3D scene built with Claude depends on: values stated, nothing left to guess.

Turn one design into a tokens file#

Open Vesperion and copy its prompt; it is free with a free account. Take its palette, type scale, spacing and easing curves, write them into a tokens file with the shape above, and hand the model both the file and the prompt. Build the page twice in two fresh sessions and compare them. With the Thanor MCP, Claude, ChatGPT or Cursor can pull a design's full art direction straight from the library, and the MCP is included in every paid plan on the pricing page.

Questions this raises

What are design tokens?

Design tokens are named design decisions, such as a color, a font size, a spacing step, a duration or an easing curve, stored as data so every tool and every page reads the same value. A token has a name, a value and a type, and is usually compiled into CSS custom properties for the web and into other formats for apps.

Is the W3C design tokens format a standard?

Not a W3C Standard. The Design Tokens Community Group published its first stable version, 2025.10, on 28 October 2025 as a Final Community Group Report, and the document states that it is not on the W3C Standards Track. It is stable enough for tools to implement, and its modules cover the format, color and resolving tokens across themes.

What are the three tiers of design tokens?

Primitive tokens hold raw values, such as a hex color. Semantic tokens give those values roles, such as the accent or the muted text color. Component tokens apply roles to one element, such as a button background. Material Design calls the same tiers reference, system and component tokens. Components should point at semantic tokens, never at primitives.

What is the difference between design tokens and CSS variables?

A token is the source, written as tool-neutral data; a CSS custom property is one output generated from it. The same tokens file can produce CSS variables for a website, values for a native app and a list a model reads in a prompt. Writing tokens first keeps all of those outputs in agreement.

Do design tokens help AI tools build consistent UI?

Yes, because they turn open choices into a closed list. A model told to use only the custom properties in a tokens file has no reason to invent a new gray or a new duration, the names tell it where each value belongs, and you can check the output for any raw value it slipped in.

Part of

Build it with AI

Three dimensional scenes, scroll driven motion and animated pages, built by handing a model a specification instead of an adjective. What to write, and what comes back.