Why Naming Conventions Are the Hard Part of a Token System
Most design system failures are not caused by wrong color values or wrong spacing scales. They are caused by tokens whose names mean different things to different people. A token called gray-500 is a hex value to one engineer, a tone to a designer, and a semantic promise to a product manager. When the same name has to survive Figma libraries, a CSS custom-property pipeline, a TypeScript export, and an MCP server exposing components to AI agents, that ambiguity compounds. By 2026, with agentic tools reading tokens directly (Figma's MCP, Claude Skills, internal Cursor rules), the cost of a sloppy name is no longer a Slack message; it is a wrong decision made by a model at 3 a.m.
Also worth reading: What are qualitative coding best practices for product and design-ops teams? · What are the essential design ops metrics dashboard best practices for 2026? · What are the definitive best practices for ensuring design system scalability in enterprise environments?
A good naming convention is therefore a contract. It commits the organization to specific category boundaries, specific role labels, and a specific escape hatch for one-off values. Without that contract, every team invents its own dialect, and the token graph becomes a swamp. The convention itself is small — usually 3-5 rules — but the discipline to enforce it across hundreds of contributors is the real work.
The Three Layers Most Teams Eventually Need
Almost every mature system that has survived more than two major releases ends up with three distinct layers, even when the team originally planned two. The first layer is the primitive (or "global") layer: the raw palette, type ramps, spacing scale, and radius scale. Names here describe appearance, not purpose. blue-600, space-24, font-size-14 belong to this layer. Tokens at this layer should change rarely, and they should not be referenced directly in product code.
The second layer is the semantic (or "alias") layer. These tokens describe intent. color-action-primary, color-text-on-brand, space-stack-md, radius-control map to primitives through an alias file. This is the layer most product code should consume, because it survives a brand refresh. A typical ratio in healthy systems is roughly 1 semantic token to 3-7 primitives, and a semantic rename should be possible without touching call sites.
The third layer, increasingly common, is the component layer. These tokens are scoped to a single component or pattern, for example button-bg-primary-hover or card-padding-compact. Component tokens exist because the gap between "primary action color" and "button hover state" is not always expressible in pure semantic terms — dark mode, brand variants, and density modes each add a dimension. A clean system usually reserves a fourth, optional layer for mode (light, dark, high-contrast, RTL), applied as a suffix rather than baked into the name.
A Taxonomy That Holds Up: Category, Role, Variant, State
Naming conventions fail when they try to encode too much. The most resilient pattern, used by Material 3, Polaris, and the rebuilt Harvey system, has four slots at most. Category is the noun (color, space, radius, font-size, motion, elevation, shadow). Role is the purpose within the product (action, surface, text, border, stack, inset). Variant is the family within the role (primary, secondary, neutral, compact, loose). State is the optional interaction modifier (hover, pressed, focus, disabled).
A real name therefore reads as color-action-primary-hover or space-stack-md or radius-control. When a token cannot be described in those four slots, it is usually a sign that the abstraction is leaking — either the role is wrong, or the token should be a component-scoped one-off, not a global. Coinbase's automated Figma-to-code pipeline, documented in 2024, depends on this exact shape: their generator refuses to emit a component unless every style it consumes can be parsed into a category-role-variant-state tuple within a 50 ms budget.
Concrete Patterns Worth Copying and Patterns Worth Avoiding
Several patterns recur in production systems and are worth copying verbatim. The first is dash-separated, lowercase, ASCII-only — no camelCase, no spaces, no &, no localized characters. Figma variable names, CSS custom properties, and iOS asset catalogs all accept dashes, and a single style that crosses every platform is worth more than typographic elegance. The second is numeric scales for primitives (blue-100 to blue-900) where the number tracks perceptual lightness, not alphabetical order. The third is role-first ordering for semantics (color-action-primary, not color-primary-action) so that grouped tokens sort predictably in autocomplete.
Patterns to avoid are equally specific. Do not encode the hex value in the name (blue-0066cc) — it makes dark mode migrations miserable. Do not include the Figma frame name or screen name; tokens outlive screens. Do not use brand names inside generic tokens (fb-blue) unless the token is genuinely brand-scoped. And do not allow two tokens that resolve to the same value with different names; that is the fastest way to lose trust in the system, because the next maintainer has no way to know which is canonical.
How Naming Interacts With Figma, MCP, and AI Agents
The 2025-2026 shift toward agentic design tooling has changed the stakes. Figma's MCP server, Anthropic's Claude Skills, and Cursor's project rules all consume token files as context. A model that sees gray-500 and bg-surface will reach for gray-500 only when the developer has explicitly opted out of semantic tokens, because the system prompt can encode that preference. A model that sees g500 and bgSrf cannot. Naming conventions are now an input to model behavior, not just to human engineers.
The practical implication is that token files should be treated like a public API. Every name should be self-describing, every alias should be documented, and every deprecated token should be marked with a deprecated and replacedBy field rather than silently renamed. Netguru's write-up of their Figma-to-React pipeline reports that roughly 30% of component generation failures traced back to a token whose name had changed in Figma but not in the published npm package. The fix was not better tooling; it was a deprecation contract that forced the team to keep the old name alive for at least two release cycles.
Comparison of Three Public Conventions
The table below compares the conventions used by Material 3, IBM Carbon, and a typical hand-rolled semantic system. It is not a ranking; each has tradeoffs that depend on team size, platform breadth, and how much AI tooling the system feeds.
| Feature | Material 3 (md.sys.) | IBM Carbon (cds-) | Hand-rolled semantic (color-action-primary) |
|---|---|---|---|
| Naming style | Dot-separated, kebab segments | Dash-separated, single word | Dash-separated, 3-4 segments |
| Primitive layer | md.ref.color.primary40 | $blue-60 (Sass) | blue-600 (Tailwind-style) |
| Semantic layer | md.sys.color.primary | $button-primary | color-action-primary |
| State expressed in token name | No (separate state-layer tokens) | Yes (--cds-button-primary-hover) | Yes (color-action-primary-hover) |
| Mode handling | md.sys.color.primary swaps per scheme | Class-based (cds--g100) | [data-theme="dark"] attribute |
| AI-agent readability | High, but verbose | Medium, predictable | High, self-describing |
| Rename blast radius | Library-wide, breaking | Library-wide, breaking | Small if scoped to semantic layer |
| Best fit | Cross-platform design systems | Enterprise B2B with strict theming | Mid-size product teams feeding MCP/AI |
Practical Steps to Roll Out or Fix a Convention
A renaming exercise is one of the highest-risk changes a design system can ship, and most of the failures come from underestimating the migration. A reliable sequence, drawn from the Coinbase and Harvey rebuilds, has six steps and usually takes 8-12 weeks for a system of 300-600 tokens. First, audit the current names and bucket them into the four slots (category, role, variant, state); anything that does not fit is a candidate for retirement. Second, draft the new convention in a 1-2 page document with ten positive examples and ten negative examples — the negative examples are what reviewers will actually use. Third, write a codemod (ts-morph, jscodeshift, or a Style Dictionary transform) that mechanically rewrites the old names to the new ones; do not rely on find-and-replace.
Fourth, publish both name sets in parallel for at least one minor release, with a runtime console warning when the old name is used. Fifth, mark old names as deprecated in the token manifest and in the Figma library description. Sixth, only after a full release cycle, remove the old names. Skipping step four is the single most common reason a token migration never finishes: the team runs out of patience, deletes the old names, and ships a Friday-afternoon breaking change.
Common Mistakes and How to Recover
Three mistakes show up in roughly 70% of the systems reviewed in 2024-2025. The first is starting with semantics before primitives are stable. If the raw palette is still moving, every semantic token built on it is sand. The fix is to freeze primitives first, even at the cost of an ugly palette, and only then build the alias layer. The second is inventing a new role for every new use case. A role like color-action-tertiary-destructive-quiet is not a role, it is a component token in disguise. The fix is a documented rule that any role name longer than two words triggers a review.
The third is failing to separate brand tokens from product tokens. Brand tokens describe the company (logo color, official type, sanctioned illustration style); product tokens describe the software (button backgrounds, form borders). Mixing them means a rebrand forces a refactor of every screen. The fix is two top-level folders, brand/ and product/, with different owners and different release cadences. Recovery from any of these is possible but expensive; the Coinbase team estimated their 2024 rebuild cost roughly 4 engineer-months and 1 design-month, and the largest single line item was the rename, not the new tokens themselves.
When to Act and What It Costs
There is no universal trigger to overhaul a token system, but three signals are reliable. First, when more than 20% of PRs touching styles also touch a token file, the convention is too tight and the abstraction is leaking. Second, when an AI agent produces a wrong component because it misread a token name, the convention has crossed from human-only to machine-read, and human-only conventions no longer suffice. Third, when a brand refresh is on the roadmap within 12 months, the cost of fixing names now is lower than the cost of doing it during the refresh.
The cost of a full rename, based on the public Coinbase and Harvey write-ups, is roughly 3-5 engineer-weeks for a mid-size system (200-400 tokens, 50-150 components) plus 1-2 design-weeks. Tooling cost is usually zero — Style Dictionary, Token Studio, and Specify are free or free-tier. The hidden cost is the migration window during which two name sets must be supported, which usually lasts 6-10 weeks and requires a designated owner. For teams under 5 engineers, a single afternoon with a shared Notion document and a hand-edited CSS file is often enough; the ceremony described above pays off only past roughly 20 components or past the first AI-tooling integration.