The drift starts small. The button is 8px of radius in Figma, 6px in code; the heading is 24px there, 22px shipped. None of it is a bug, so none of it gets caught, and the product slowly stops matching the design. Here’s the workflow that kills drift before it starts.
Tokens first
Translate tokens, not pixels. Before you write a single component, pull the design’s primitives — color, spacing, radius, type scale — into shared tokens that both sides agree on.
:root {
--space-4: 1rem; /* 16px */
--radius-md: 0.5rem; /* 8px */
--text-lg: 1.125rem; /* 18px */
--primary: 240 6% 10%;
}Now 16px isn’t a number you eyeball off the canvas; it’s --space-4 in both places. When design bumps the scale, you change one line, not forty components.
Name parity
The fastest way to lose a design is to rename it in code. If the Figma layer is Card/Header, your component is CardHeader — same words, same structure. A Large variant in Figma becomes size="lg" in the API.
When names match, a new engineer can read a Figma file and already know the component tree. Search works across both. Reviews stop being a game of guess-which-thing-this-is.
Build states, not screens
A screen is a snapshot; a component is a state machine. Don’t rebuild the “Dashboard — Filled” frame. Build the DataTable and give it empty, loading, error, and populated states.
Designers hand you three frames; you owe the product all four states, including the one they forgot to draw. Ask for the empty state on day one — it’s the one that gets skipped and the one users hit first.
The workflow
Tokens in a shared file. Names that mirror the design tree. Every component built as its full set of states. Do those three and the mockup and the running app stay in sync on their own — no pixel-diffing, no “why doesn’t it match” thread in review.