Product Design

Design token naming conventions: a 3-tier system that scales

A three-tier scheme (primitive, semantic, component) keeps token names stable as a system grows. Here is how to structure and name each layer.

July 2, 20266 min read
Wooden card catalog drawers with labels

By the end of this guide you will have a token naming scheme where a developer can name a new token correctly on the first try, without asking anyone. The scheme uses three tiers, primitive, semantic, and component, and the name itself tells you which tier a token belongs to.

A design token naming convention is the set of rules that decides what each token is called and how the parts of the name are ordered. Get it right and the system scales. A designer adds a color, a developer knows where it belongs, and a dark mode swap changes a handful of lines. Get it wrong and you collect blue2, blueDark, and brandBlueNew pointing at three shades no one can tell apart six months later.

What you need before you start

Three things, and the second one causes the most arguments, so settle it first.

  • A list of the raw values already in your product: colors, spacing steps, font sizes, radii, shadows, and durations. You are naming what exists, not inventing a palette.
  • Agreement on one delimiter and one word order. Mixing color-bg-primary with colorBgPrimary in the same system breaks tooling and search. Pick one and enforce it.
  • A file format to write into. Since October 2025 the W3C Design Tokens Format Module has a first stable version, so JSON with $value and $type is a safe default that Style Dictionary, Tokens Studio, and Figma variables can all read.

Step 1: Split every token into one of three tiers

Mature systems, IBM's Carbon among them, organize tokens in three tiers connected by a reference chain: primitive to semantic to component. Each tier answers a different question.

  • Primitive (also called global or base): the raw value with no context. blue-500 says a blue exists and what it equals. It does not say where to use it.
  • Semantic (also called alias): the intent. color-text-default points at a primitive and says what the value is for.
  • Component: bound to one component. button-background-hover points at a semantic and exists so one component can diverge on its own.

The primitives are the options. The semantics are the choices. Products consume semantic and component tokens; primitives stay behind the curtain as reference values.

Step 2: Name primitives by what they are

Primitives describe appearance, because appearance is all they carry. Use a category, a hue or property, and a numeric scale: color-blue-500, dimension-space-4, font-size-300. The numeric scale matters. Steps of 100 (100 to 900) leave room to insert a value later without renaming its neighbors. Avoid adjectives like blueMedium or spaceBig; they run out of headroom the moment you add a shade between two of them.

Step 3: Name semantic tokens by intent, never by appearance

This is the single rule that saves the most pain. Name a semantic token for what it does, not for what it looks like. Use color-feedback-success, not color-green. When one brand renders success in amber, or dark mode flips a surface, the intent name still holds and only its reference changes. An appearance name like color-green-button becomes a lie the day the value stops being green.

Nathan Curtis's token taxonomy gives the levels a semantic name can draw on: namespace, category, concept, property, variant, state, and scale. You rarely use all of them. A common, readable shape is category, concept, property, then state: color-action-primary-hover. Read left to right it says: a color, for actions, the primary one, in its hover state.

Step 4: Add component tokens only when a component earns one

A component token exists to give one component a hook a designer can retarget without touching the shared semantic layer. card-border-default lets the card team change card borders alone. That is useful the day a component genuinely needs to diverge. It is clutter every other day. Default to the semantic layer. Promote a value to a component token when, and only when, a real divergence appears. Most components never need one.

Step 5: Fix one delimiter and one order, then write it into the linter

Order the levels from general to specific: namespace, category, concept, property, variant, state, scale. Drop the levels a token does not need. Curtis's own example, esds-color-neutral-42, packs a namespace (esds), a category (color), a variant (neutral), and a scale (42) into that order.

Delimiter depends on the output. Use dots in the JSON source (color.text.default) because that is how groups nest in the W3C format. Use hyphens in the CSS custom properties your build emits (--ds-color-text-default). Pick a single namespace prefix for the CSS layer (--ds- here) so your tokens never collide with a third-party stylesheet. A build tool such as Style Dictionary transforms one source into every output, so you author the name once.

Step 6: Turn the convention into a one-page grammar

A list of tokens goes stale the week after you publish it. A one-page grammar does not. Write down each level, the words allowed at that level (is it bg or background, text or fg), and the order they appear in. With the grammar in hand, a developer names a token they have never seen and lands on the same name a maintainer would have picked. That is the whole point of a convention.

How do you know the convention works?

Two tests. First: hand a new developer a raw value with no token and ask them to name it. If they produce the name you would have written, without asking, the convention holds. If they guess wrong, the grammar has a gap. Second: run a theme change. A rebrand or a dark mode should touch the semantic layer and nothing else. If it forces edits across dozens of component tokens, your semantic layer is too thin and components are referencing primitives directly.

Common mistakes and how to fix them

  • Appearance words in the semantic tier. color-green-success defeats the point. Rename to color-feedback-success and repoint the reference.
  • Encoding the value in the name. color-text-16px mixes a color with a size. Size is its own token; keep the two axes apart.
  • Synonym sprawl. bg, background, and surface used for the same concept force everyone to guess. Pick one word per concept and ban the rest in the linter.
  • Runaway nesting. color-button-primary-default-hover-large has too many levels to read. Cap names at roughly four meaningful levels; if you need more, a component token is hiding in there.
  • Component tokens by default. Creating button-*, card-*, and modal-* for every property before any of them diverge doubles the surface with no benefit. Wait for the divergence.

Going further

Naming is one layer of a larger structure. Read design tokens vs CSS variables vs Tailwind for where tokens sit in the stack, design system structure for the order to build the categories in, and component drift for what happens when a convention exists on paper but nothing enforces it.

Sources

Photo by Ilya Semenov on Unsplash

Frequently asked questions

How many token tiers do I actually need?
Two is enough to start: primitive and semantic. The component tier is optional, and you add it per component only when one needs to diverge from the shared semantic value. A small product can ship with primitive and semantic tokens alone and stay clean for a long time. Add the third tier the day a real divergence appears, not before, or you end up maintaining hundreds of component tokens that all point at the same three semantics.
Should a semantic token name ever include its value, like color-primary-blue?
No. The value lives in the primitive that the semantic token references. The moment the value changes, an appearance word inside a semantic name turns into a lie you then have to rename everywhere it is used. Keep appearance words in the primitive tier, where blue-500 is honest. Keep semantic names about intent, like color-action-primary. Primitives can encode the value; semantics must not.
Do I have to migrate old tokens to the W3C format?
No. The W3C Design Tokens Format Module reached its first stable version in October 2025, and the common tools support both it and older formats, so existing tokens keep working. The gain from adopting it is portability: the same JSON reads in Style Dictionary, Tokens Studio, and Figma without a custom converter. Adopt it for new work and migrate opportunistically, not in a big-bang rewrite.
camelCase, kebab-case, or dot notation, which should I use?
It depends on the output, and you do not have to pick only one. Author names as dot-nested groups in the JSON source, because that is the shape the W3C format expects. Let your build emit kebab-case for CSS custom properties and whatever casing your other platforms need. A tool like Style Dictionary transforms one source name into every casing, so the real decision is the source format, not a system-wide lock-in on one style.

Studio

Start a project.

One partner for the digital product you need to build. Faster delivery, modern tech, lower costs. One team, one invoice.