Caret / Guides

What are design tokens?

A design token is a design decision with a name, stored as data. Instead of #0066cc appearing in forty files, there is one value called color.primary, and everything that means “the primary colour” points at it.

Updated 6 October 2026 · 9 min read

A tray of design token tiles for colour, spacing, radius and type, each wired to the part of an interface card that uses it

The definition, from the people who wrote it

The term came out of Salesforce’s Lightning Design System, where Jina Anne and Jon Levine are credited with coining it. Their own page describes tokens as “the visual design atoms of the design system — specifically, they are named entities that store visual design attributes,” used in place of hard-coded hex values and pixel sizes.

Adobe’s Spectrum puts it in one line: tokens are “a methodology for expressing reusable design decisions as structured data.” And the W3C Design Tokens Community Group, which maintains the shared file format, keeps it minimal: a token is “information associated with a human readable name, at minimum a name/value pair.”

The useful word in all three is decision. A token is not just a value. It records that someone decided the primary colour is this blue, that the gap between cards is 16 pixels, that buttons have an 8 pixel radius, and it gives that decision a name the rest of the system can point at.

Why bother

Because a value with a name can change in one place. If #0066cc is typed into forty components, a rebrand is forty edits and a search for near-misses like #0067cc. If those forty components say color.primary, it is one edit.

Names also carry intent, which raw values cannot. 16px tells you nothing about when to use it. space.card-gap does. That matters more than it used to, because the thing reading your code is increasingly an AI agent, and an agent given a list of named decisions makes fewer guesses than one given a pile of hex codes.

And tokens are platform-neutral data, so the same decisions can be turned into CSS variables for the web, Swift constants for iOS and XML resources for Android from one source.

Primitive, semantic, component

Most systems arrange tokens in three tiers. The names differ, the idea does not.

TierWhat it holdsExample
PrimitiveThe raw palette. Every available value, with no opinion about where it goes.color.blue.600 = #0066cc
SemanticPurpose. Points at a primitive and says what it is for.color.action.primary = {color.blue.600}
ComponentOne component’s use of a semantic token.button.background = {color.action.primary}

Spectrum calls the first tier primitive tokens that “communicate little or no information about how those values should be used,” and the second semantic tokens that “communicate purpose.” Material Design 3 uses reference, system and component tokens for the same three layers. Nathan Curtis’s Naming Tokens in Design Systems is the standard reference for the naming itself, and has one piece of advice worth repeating: start a token inside a component, and promote it to a shared tier once several components need it.

The semantic tier is the one that pays off. Dark mode, a second brand, a high-contrast theme: each is a different mapping from semantic names to primitives, while the components never change.

The format: DTCG 2025.10

For years every tool had its own token JSON. On 28 October 2025 the W3C Design Tokens Community Group published the first stable version of its specification, 2025.10. It is a Community Group report rather than a formal W3C standard, but it is the format Style Dictionary, Tokens Studio and Terrazzo implement, and the one Figma can import.

The basics:

One thing catches people coming from older formats: in 2025.10 a colour is an object with a colour space, not a hex string, and a dimension is a value with a unit.

{
  "color": {
    "$type": "color",
    "blue-600": {
      "$value": { "colorSpace": "srgb", "components": [0, 0.4, 0.8], "hex": "#0066cc" }
    },
    "primary": {
      "$value": "{color.blue-600}",
      "$description": "Main action colour"
    }
  },
  "space": {
    "$type": "dimension",
    "4": { "$value": { "value": 16, "unit": "px" } }
  },
  "radius": {
    "md": { "$type": "dimension", "$value": { "value": 0.5, "unit": "rem" } }
  }
}

Tokens vs CSS variables

They are not the same thing, and the difference is where each one lives. Penpot’s developer guide puts it well: “Design tokens define what the design values are and their semantic meaning. CSS variables determine how these values are implemented in the browser.”

The token file above becomes this on the web:

:root {
  --color-blue-600: #0066cc;
  --color-primary: var(--color-blue-600);
  --space-4: 16px;
  --radius-md: 0.5rem;
}

Custom properties are one output of a token. The token is the source; the variable is what the browser sees.

Where tokens live in real tools

Tailwind CSS v4

Tailwind now says this outright: “These low-level design decisions are often called design tokens, and in Tailwind projects you store those values in theme variables.” You declare them with @theme, and each one both becomes a CSS variable and decides which utility classes exist:

@theme {
  --color-brand-600: #0066cc;
}
/* now bg-brand-600 and text-brand-600 exist,
   and var(--color-brand-600) is available everywhere */

The flip side is easy to miss: if an agent writes text-brand-950 and there is no --color-brand-950 in a theme, Tailwind generates nothing for it. The class looks right in the diff and does nothing on the page.

Style Dictionary

Style Dictionary turns one token source into CSS, JavaScript, iOS and Android output. It has supported the DTCG format since version 4; its own docs note that full support for 2025.10 is still in progress in version 5.

Figma Variables and Tokens Studio

Figma’s variables are its built-in store for these values, and its help centre documents exporting modes to JSON and importing DTCG tokens. Tokens Studio, the long-running Figma plugin, can switch between its own legacy format and DTCG.

Penpot

The open-source design tool added native tokens in 2025, built with Tokens Studio. Users have pointed out that its export is Tokens Studio’s multi-set format rather than 2025.10, so check before wiring it into a pipeline that expects the spec.

Tokens and AI coding agents

Here is the problem in one sentence: an agent told to “build me a card” that has to choose to look up your spacing scale usually won’t, and fills the gap from its training data. You get p-5 where your system says 16, and a blue that is close to yours but not yours.

Two things help. The first is putting the tokens where the agent reads before its first turn. Every mainstream coding agent loads a rules file automatically:

A rules file is context, not enforcement, and it goes stale the moment a token changes. The second thing that helps is the codebase itself. Builder.io’s write-up on this has the line worth remembering: “Your codebase is your prompt.” An agent copies the patterns it sees, so code that already uses tokens everywhere teaches it to do the same, and a linter that rejects raw hex values closes the loop.

How Caret handles it

Caret is a free, open-source desktop app that keeps a project’s design in the repo as real React, in a .caret/ folder beside your app. Its foundation tokens (colour, type, spacing, radius) live in .caret/tokens/foundation.json, in Caret’s own shape rather than DTCG. From there it does three things:

Questions

Keep your tokens where your agent reads them.

Caret stores your colour, type, spacing and radius in your repo, turns them into Tailwind theme variables, and writes them into AGENTS.md, CLAUDE.md and .cursor/rules so every agent session starts with them.

All platforms

Free, Apache-2.0, no account. macOS, Windows and Linux. Needs Node.js for the live canvas.