← Back Enterprise Design System

Enterprise Design System

Three-tier tokens, two themes, one pipeline from Figma to production code.

Role
Sole designer
Focus
Architecture, tokens, dev pipeline
Timeline
2025 – 2026
Status
In production, used by the dev team
[Hero image — design system overview]

Components shipped 1:1 with the design system on the first pass.


Context

The product this system was built for is an internal enterprise data platform — a place where engineers find, evaluate, and access data assets. The specifics are kept vague here by design. What mattered for the system: it needed two themes, a small but focused component set, and a direct path from design file to production code.

Off-the-shelf systems like Material or Fluent were not the right fit. They solve for breadth. This product needed depth in a specific interaction model, with a visual language that matched the platform's tone. A custom system also meant every token and component had a clear owner and a clear reason to exist.

I was the only designer. The system grew in parallel with the product — not before it. There was no separate design system phase. Every new screen was an opportunity to extract a pattern. Every extracted pattern reduced the cost of the next screen.

The problem

Four things made early handoffs slow and error-prone.

Handoff gap

Screenshots in Jira

Figma files were shared as static exports. Developers re-interpreted specs by eye. Documentation drifted as soon as the next design iteration started.

Duplication

Two files per component

Light and dark mode were handled at the component level — copy the component, override the colors. Any fix required touching two places.

No shared language

Designers used layer names, devs used hex values

There was no token layer connecting the two. Color changes in Figma did not propagate to code. Every update was a manual conversation.

Reinvention

Each screen rebuilt existing patterns

The filter row, the card, the empty state — each re-solved on new screens without a shared reference. Inconsistencies accumulated faster than they could be caught.

How the system grew

The system was never a separate project. There was no design system phase before the product phase. The two ran together from the start.

Every screen that was designed went through a two-step check: does this use a pattern that already exists in the system? If yes, use it. If no, does this pattern belong in the system? If yes, extract it. A pattern was promoted to the library only after it appeared in at least two separate product screens. No speculative components. No patterns that hadn't been used.

Three tiers — Primitives, Semantic, Component

Three tiers solve a problem that two tiers do not: you want components to be theme-aware without coupling component logic to raw color values. Two tiers almost works. Three tiers actually works, because the semantic layer acts as a stable interface between what changes (the theme) and what doesn't (the component).

Primitives

Raw values with no semantic meaning. Every color, spacing step, and type size in the system lives here. red-50, space-4, font-size-14. Primitives never appear in components directly.

[Token example: primitive values — color scale, spacing scale, type scale]

Semantic

Intent-based tokens that map to a primitive based on the active theme. surface.primary, text.muted, border.default. In light mode, surface.primary resolves to one primitive. In dark mode, it resolves to another. Components never know which.

[Token example: semantic layer — light vs. dark resolution table]

Component

Scoped to specific components. button.primary.background, card.border, input.text. These reference semantic tokens, never primitives. The component tier is what the MCP pipeline reads when it generates code.

[Token example: component layer — button token stack from component to primitive]
[Architecture diagram — three columns, primitive → semantic → component, with theme switching shown on the semantic layer]

Naming was the unlock

The Figma MCP server reads the Figma file structure — layer names, variable names, component names — and exposes them as structured data the dev's IDE can query. If a token in Figma is called surface.primary and the same token in code is called color-bg-main, the pipeline produces a mismatch on every component.

The naming conventions were agreed on before the first component was built: tier prefix, semantic category, variant. That one decision turned a manual process into an automated one. It also meant token renames became breaking changes — which made the team careful about when and why names changed.

From Figma to production code

The pipeline connects Figma to the developer's IDE through a Figma MCP server. A developer queries a component by node ID and gets back the structure, tokens, and variants. Claude Code generates the component from that output. The design file is the source of truth — not a screenshot of it.

Before

  • Annotated screenshots attached to Jira tickets
  • Developers re-interpret specs by eye
  • Documentation goes stale between design iterations
  • Code reviewed against static exports, not live design
  • Token changes communicated in Slack, applied manually

After

  • Developer queries the Figma node directly from the IDE
  • Claude Code generates the component from live design data
  • Token updates in Figma propagate to the next build automatically
  • First-pass output matches the design system 1:1
  • No back-and-forth on spacing, color, or naming
Figma file Design system, tokens, variables
MCP server Structured data layer — read-only
Claude Code / IDE Live queries from dev environment
Production code Components built 1:1 with design

How it works under the hood

The Figma MCP server exposes three operations used in this pipeline. All operations are read-only — the server never writes to the Figma file.

get_design_context Returns component structure, layout constraints, and variant data for a given node ID.
get_metadata Returns layer name, type, visibility, and parent/child relationships.
get_variable_defs Returns all token values resolved for the active theme — primitives, semantic, and component tiers.

Figma file key for this project: 1yEn24FNbHfdrvdJdNT6fz

Example prompt

Using the Figma MCP server, read the design context for node [node-id] from file key 1yEn24FNbHfdrvdJdNT6fz. Generate the component in React using our existing token system. Match the Figma source 1:1.

Button: from Figma node to production code

[Step-by-step walkthrough — Figma node selected → MCP query → generated React component with tokens annotated]

Placeholder for a detailed walkthrough of one component moving through the full pipeline.

Two themes, one component

Component tokens do not change between light and dark mode. Only the semantic layer resolves differently. button.primary.background always points to interactive.primary. In light mode, interactive.primary resolves to one primitive. In dark mode, it resolves to another. The component has no knowledge of which theme is active.

Light

[Light mode component — button, card, or input]

Dark

[Dark mode — same component, semantic layer resolves differently]

Governance

The system is used in production. Changes have consequences. Four rules keep it stable.

Naming Every token follows the tier/category/variant convention. Variables added to Figma outside the convention are flagged before they're published. The same rules apply in code.
Promotion A pattern enters the system only after it has been used in at least two separate product screens. Local-first, then promoted. No hypothetical components.
Propagation Token updates move through the tier chain automatically. Changing a primitive updates all semantic tokens that reference it, which updates all component tokens in turn. The update surfaces in code on the next build.
Changelog Every system change ships with a changelog entry: token renamed, component prop added, variant deprecated. The changelog lives in the same repository as the production code.

Outcomes

Components in system

[TBD]

Total components shipped and in active use

Tokens across three tiers

[TBD]

Primitive, semantic, and component tokens combined

Themes supported

2

Light and dark — one component definition each

First-pass dev accuracy

[TBD]

Components matching design system on first implementation

Handoff time saved

[TBD]

Per component, compared to previous screenshot-based process

What is next

Where the system is heading

The pipeline works. The next step is documentation good enough that a new engineer can use it without asking the designer. The MCP server connection, the Figma file key, the prompt structure — all of it needs a README that stands on its own. The goal is zero onboarding conversations needed.

What I learned

The token tier structure is right, but the semantic layer is still under-specified in places. Some component tokens skip semantic entirely and reference primitives directly — a shortcut that made sense early and now needs cleaning up. Building a system in parallel with a product teaches you which decisions age well and which ones don't. Naming ages well. Shortcuts don't.

Next case → Data Marketplace — Halliburton
01 Context 02 Problem 03 Approach 04 Tokens 05 Naming 06 Pipeline 07 Themes 08 Governance 09 Outcomes 10 Reflection