Back to blog
Priya Kumaraswamy 8 min read

What We Learned from 47 Design System Token Audits

Design system token audit insights

Before we wrote the first line of Flowstep's token resolution engine, we needed to understand what design systems we'd actually be resolving against. So we asked a group of early-access participants to let us audit their token setups. Forty-seven teams said yes.

This is a writeup of what we found. The patterns were not random. They clustered into a small set of structural problems that appeared repeatedly, regardless of whether the team was using Figma Tokens, Tokens Studio, Style Dictionary, or a custom JSON pipeline. The problems were also fixable, which matters for what we built next.

How the audits worked

Each team provided their token files: usually a JSON export from their primary token tool, sometimes a Style Dictionary config, occasionally a Figma library export. We did not ask for proprietary product screens or internal tooling. Just the token layer itself.

We looked at four things per system: the completeness of the semantic layer, the consistency of naming conventions, the depth of component-level token coverage, and the presence or absence of alias chains (semantic tokens pointing at primitive tokens rather than raw values).

The audit was structured, not impressionistic. We built a small scoring tool internally to flag specific patterns, which also became an early prototype for part of Flowstep's ingestion pipeline. The 47 systems ranged from two-person product teams to design systems maintained by groups of four or five.

What we found: the semantic layer is the gap

The most consistent finding was this: teams had invested significant effort in primitive tokens but had stopped well short of a complete semantic layer. The primitive layer, things like --color-violet-500, --spacing-4, --font-weight-semibold, was often thorough and well-maintained. The semantic layer, where those primitives get named for their role in the UI, was partial or absent.

One team we audited had a complete primitive color ramp with 11 shades per hue and consistent step naming. Their semantic layer had three entries: --color-primary, --color-secondary, and --color-error. That is not a semantic layer. That is a shortcut list that breaks the moment a designer needs to specify an interactive state, a surface, a border, or a disabled variant.

The reason this matters for Flowstep is direct: if a brief says "primary action button", we need a semantic token to resolve that to. --color-primary is close but ambiguous. --color-interactive-default or --button-bg-primary is resolvable. The more complete the semantic layer, the more precisely we can map a brief to the correct token paths.

Naming patterns: the ones that held and the ones that broke

We saw roughly four naming conventions across the 47 systems.

The first was scale-based naming: --color-blue-100 through --color-blue-900, with no semantic interpretation. This is common and works fine as a primitive layer but provides no resolution hooks for semantic use cases.

The second was role-based with generic names: --primary, --secondary, --success, --danger. This offers semantic intent but breaks once you need to distinguish between a primary background and a primary text color on that background.

The third was role-plus-state naming: --color-interactive-default, --color-interactive-hover, --color-interactive-disabled. This held up well. The explicit state encoding makes alias resolution deterministic.

The fourth was component-scoped naming: --button-bg-primary, --button-text-primary, --input-border-default, --input-border-focus. This is the most resolvable layer from a generation standpoint. When component tokens exist, Flowstep can map directly to them without inferring from higher-level semantics. The tradeoff is maintenance surface, and several teams mentioned that keeping component tokens in sync with design changes was their primary governance headache.

Alias chains: present in 19 of 47, complete in 9

Alias chains, where a semantic token points at a primitive rather than a raw value, were present in just under half the systems we audited. Complete alias chains, meaning every semantic token in the system resolved to a primitive rather than a hardcoded value, appeared in 9 of the 47.

The incomplete cases followed a pattern: the team had set up aliases for their primary palette and then added raw values directly to component tokens when building new features under time pressure. The alias structure existed in the system's documentation but had eroded in the actual exported JSON.

This is the origin of token drift. It is not usually a deliberate choice. It is what happens when a component needs a color value quickly and the correct alias does not yet exist. The shortcut gets written once and then never cleaned up because it works and the effort to clean it is invisible against other priorities.

What was actually fixable

Most of the problems we found fell into three categories: incomplete semantic coverage, inconsistent naming that made alias resolution ambiguous, and component tokens that had drifted to raw values.

All three are fixable with structural changes to the token file rather than visual redesign. Adding semantic tokens that point at existing primitives costs no visual change to the product. Normalizing naming conventions across a partial system takes hours, not weeks. Re-aliasing drifted component tokens is mechanical work once the correct primitive exists.

What the audit confirmed for us is that the resolution problem is not a philosophical one about how teams should structure design systems. It is a practical one about the gap between how token systems are designed and how they get maintained over time. Flowstep's job is to resolve against what actually exists, not against what should exist. But understanding the gap helps us produce more useful feedback when the resolution is ambiguous or incomplete.

How this shaped what we built

The audit directly changed the ingestion pipeline. We built a token coverage analyzer that runs before generation and tells you which semantic roles are mapped, which are missing, and which are pointing at raw values instead of aliases. The output is not a grade. It is a list of specific token paths that, if added or corrected, would increase resolution precision for the generation you are about to run.

We also built in graceful degradation for systems where the semantic layer is partial. If a component token does not exist, Flowstep walks up the alias chain to find the nearest semantic equivalent. If no semantic equivalent exists, it uses the primitive with a flag in the output indicating which token paths were resolved by fallback rather than by direct match. That flag is the designer's signal to check those components first after generation.

Forty-seven systems told us the same thing in forty-seven different configurations: the token layer is where the real design decisions live, and it is also where the real maintenance debt accumulates. Building a tool that works with real systems means working with that debt, not assuming it away.

More from the blog

Turn your next brief into screens today.

Token-aligned screen generation, starting free. No card needed.

Start free