← All workRead the case ↓

Figma Systems Mastery

Primitives, semantic roles, and layout structure that were never email-specific.

Email production needed a component library. What it needed underneath was a decision about how any library here would be built, because there was going to be more than one. I built the universal layer first — primitives, semantic roles, layout structure — enforced it structurally rather than by convention, and then refactored it under live use without breaking the work already depending on it. The same foundation has since been documented outside my employer's systems entirely.

Sur La Table · Figma Systems

Color foundations board: a rules block requiring colors to be picked from semantic roles rather than raw primitives, a set of primitive swatches grouped by family, and a table of semantic roles for text, surface, state and overlay, each mapped for light and dark.

Color architecture: raw primitives kept separate from named semantic roles, each mapped for light and dark, with the usage rule stated on the board.

The email library was the occasion, not the scope.

The immediate need was a component library for email production. The durable question was different: what should the layer underneath any library here look like, given that email would not be the last one.

So I built the part that has nothing to do with email — 19 colour primitives in five groups, 20 semantic roles, 22 text styles in six role folders, one spacing scale. Email became the first consumer of that foundation rather than its definition.

The structure enforces itself.

Components bind to semantic and layout roles only. Direct use of a primitive is prohibited — not discouraged in documentation, blocked in the structure — so the role layer has to exist before anything can consume it.

The semantic layer is deliberately incomplete. A role gets added when a component actually needs one, never in advance to make the system look finished. A foundation that guesses at future roles is a foundation full of entries nobody uses and everybody has to read past.

Improving it without charging the cost downstream.

Once a system has consumers, every improvement has a bill and somebody else usually pays it.

I renamed 31 components because the old naming forced three to four clicks of pure scaffolding in the Assets panel — the cost was countable, which took the decision out of the realm of preference. Five spacing families came out only after 111 existing consumers had been rebound to their replacements. Twenty-two text styles were reorganized while their style IDs were preserved, so every existing binding survived the restructure.

That last one is the discipline the whole card rests on. Renaming without breaking links is a choice, not a default. It carries accumulated context forward instead of billing the next cycle to rebuild it.

Deprecation is reversible on the same principle: retired assets move to an archive that keeps the notes needed to restore them, and a dated change log keeps the current state legible to someone who was not there.

It already runs where email cannot reach.

The test of whether a foundation is universal is whether it works outside the system that produced it.

Outside my employer's environment entirely, in an independent build, I documented a one-to-one naming rule binding Figma variables to CSS variables, with tokens in DTCG format and the importer's limitations written down at the point where the next person meets them. Same primitives-and-roles structure, no email anywhere in it.

Web production is the next surface it is intended to carry, and my own scope has moved there. That extension is underway rather than finished, and I would rather say so than describe it as done.

← Back to selected workBack to top ↑