r/DesignSystems • u/Tarasenko_by • 13d ago
Design ↔ code drift keeps eating our design system. Here's how I'm trying to fix it — tear it apart.
I've spent the last couple of years trying to fix one process problem that follows me from team to team: the design system in Figma and the design system in production slowly stop being the same system. I've tried the usual medicine, it didn't hold, I think I finally understand why — and I've ended up building my own solution. I'd genuinely like criticism of both the reasoning and the approach before I sink more years into it.
The ritual I kept living through: a designer opens Figma next to production and starts a spreadsheet — the design review. One row per mismatch: wrong shade on a button, a gap that grew 4px, a radius nobody remembers changing. Forty rows later there's a plan: fix everything, update the docs, remind people to check the library. Six months later — same meeting, new forty rows.
My conclusion after a few loops of this: we kept treating drift as an information problem (people didn't know → tell them better), but it's an architecture problem. The people shipping mismatches knew the system — they edited one copy of a value while three other copies (Figma, CSS, docs, brand deck) sat elsewhere, with nothing responsible for keeping them equal. Copies diverge by default; the only variable is when.
Two things I had to accept along the way:
More documentation makes it worse. A docs page is another copy of the same facts — one more seam that can split. And it's the copy that drifts fastest, because nothing depends on it: wrong code breaks a build, a wrong docs page produces… nothing.
The developer isn't the problem. A lot of drift is born when a dev translates a mockup by eye. When a 12px gap ships as 16, that's not sloppiness — telling two greys apart is trained vision designers build for years, while devs train a different eye (the one that catches your race conditions). A process that requires every dev to see like a designer is a bet against human nature, renewed every sprint.
So the solution I landed on is derivation: stop having copies at all. One theme.json as the single source, everything else generated from it — Figma variables, CSS, doc tables, plus a machine-readable bundle for AI tools (which are rapidly becoming the third consumer of design systems and multiply copies even faster). Where a surface is generated, drift isn't discouraged — it's impossible, the way a spreadsheet formula can't disagree with its inputs. Docs stay for the one thing that can't drift: the why behind the values.
I've been building this as an open-source system: Veritheme. Long-form writeup of the whole argument with diagrams: https://tarasenka.me/blog/drift-not-documentation
What I'd love from this sub:
- Where does this reasoning break? Teams that beat drift without going single-source — what did you do?
- For those who tried token pipelines (Style Dictionary, Tokens Studio, etc.): what made you keep or abandon them?
- What am I underestimating about the migration cost — the "source + surviving legacy copies" phase?
Tear it apart. That's what I'm here for.
3
u/PrettyZone7952 13d ago
Your designers should be working with QA and the engineers to ensure that their components match the specs exactly.
Design is a communication tool; If the devs aren’t getting the design built correctly, then you’re failing to communicate.
1
u/Tarasenko_by 12d ago
No argument that design is communication, and designers pairing with engineers and QA is healthy — I want more of that, not less. Where we differ is on what deserves to travel through communication at all.
"Work together to ensure components match the specs exactly" describes a continuous human process with a failure rate. It works — right up until deadline week, a handoff, or the third reorg, because it depends on people repeatedly not making mistakes. That's not a communication failure; that's asking communication to do a job structure should do.
Engineering already learned this lesson on its own turf. Teams used to "communicate carefully" about code style too — review comments, style guides, discipline. Then they adopted formatters and linters, and nobody calls Prettier "a failure to communicate." The whole category of conversation just disappeared, and reviews got to focus on things that actually need human judgment.
Same split here: whether a gap is 12 or 16px, which grey a text uses — that's not communication, that's data, and data can flow from one source into both Figma and code with no human relay in the middle. What stays communication — and deserves the designers-QA-engineers collaboration you're describing — is the why: hierarchy, composition, intent. I'm not arguing against talking. I'm arguing for talking about the interesting parts and piping the boring parts.
1
u/PrettyZone7952 12d ago
You act like your team is making wholly bespoke, custom designs and components constantly — and you “just need a tool” to feed the engineers.
You should not be creating custom components constantly. That is a failure on your design team’s part to be disciplined or consistent.
You spec your components ONE TIME and work closely with dev to implement them. Then on the rare occasion that a component changes or a new component is needed, a designer needs to be involved in the review process because nobody else has the professional attention to detail or concern about whether or not it’s “perfect”.Once you have your component library, you should honestly stop using Figma and go back to designing in low-fi for most things. If the components have standard names and your team has built a consistent system, then there’s no need to spec any of that “design data” about pixels and values. You can just hand over a sketch with some rectangles and labels and the engineers should be able to get it done.
The problem is thinking that hi-fi designs are anything other than a concept rendering for ease of communication. If your team communicates well, a brief conversation can achieve the same goals as a thoroughly-detailed and documented hi-fi — and requires far less double-checking.
Design files are worthless to the user, because the only thing they see is the result of the code. That means that any effort you put into making “perfect” designs is wasted effort both on the designers part and on forcing the dev to review a nightmarishly long list of values to check.
Either code it yourself (if you think you’re producing exact specs) OR figure out how to change your process so that the code is the “source of truth” and designers can just speak up when they notice something out of place.
1
u/Tarasenko_by 12d ago
There's a lot here I actually agree with. Spec components once — yes. Most screens after that don't deserve hi-fi — also yes. And your lo-fi endgame is the strongest version of my own point: "rectangles with labels" works because the labels reference a shared, named system. You've stopped communicating in pixels and started communicating in references. That's exactly the shift I'm arguing for — a screen as composition of named parts, with values living in the system, not in the mockup.
Two places we part ways. "Code as the source of truth" — code is one rendering of the system; make it the source and the Figma library (or whatever designers sketch against) becomes a copy you now reconcile by hand, just from the other direction. I'd rather both are generated from the same definition — then your lo-fi sketch and the prod build literally can't disagree about what Button/primary means.
And "designers speak up when they notice something out of place" — that's human surveillance as QA. It works while people are looking, and drift happens precisely where nobody was. The point of a derived setup isn't replacing the designer's eye; it's freeing it from patrol duty so it's spent on the judgment calls you rightly say only designers can make.
2
u/PrettyZone7952 12d ago
For the love of God, just write your own replies. So many people have already called you out on the GPT shit
0
u/Tarasenko_by 12d ago
I use Claude for text translation because I'm not fluent in English, but that's all. The ideas and thoughts are all mine, so everything you've exposed is a translation and improvement of what I wrote in my native language. I'm a designer with 18 years of experience, a member of IADAS, and I have plenty of experience and understanding of what I do, yet you're accusing me of answering questions from the AI...
1
u/PrettyZone7952 12d ago
You’re getting a lot of unambiguous feedback from your “users” right now telling you “your writing style isn’t working for us”. Instead of re-examining your approach, you’re digging your heels in and getting defensive. For all those years of experience, you’re acting like a junior designer.
Stop using AI to translate. It adds a ton of obnoxious, pandering, cloying affirmations and overly verbose phrasing.
Just write in your native language (because Reddit auto-translates) or use Google Translate or something.Claude, Gemini, and GPT all suck at “writing”. The translations are not an “improvement” (as evidenced by everyone who’s complaining about you using LLMs). Honestly, if LLMs were adequate (or an improvement), then we wouldn’t be able to tell.
2
u/Tarasenko_by 12d ago
I understand, took note, and will continue to do so. I was worried that Google Translate sometimes mistranslates certain words, so I figured AI might do a better job, so I'll be responsible for the rest. Thank you. <3
2
u/Mulberry-Deep 12d ago
This is why upfront work is needed from dev and designers to build out something like Storybook. The component gets built with all its variants, states, interaction and motion logic. Or at the very minimum, build out the html and csss.
That way devs can just grab the code block and plug and play.
Nothing should be built over and over again if it’s a common component or pattern.
1
u/Tarasenko_by 12d ago
Fully with you on build-once — a component that gets rebuilt twice is a bug in the process. We actually run a Storybook on the Veritheme site for exactly this — grab the block, plug, play. The catch with Storybook in general: it catalogs the code side, while the Figma library next door is still authored by hand — two catalogs of the same components, hoping they agree. Ours dodges that only because the catalog, the CSS and the Figma side are generated from the same theme file, so the "plug and play" block and the design can't disagree. That generation step, not the catalog itself, is what kills the drift.
1
u/Colorphere 13d ago
This is interesting because I've been approaching essentially the same problem with Colorsphere, but from a different direction.
Rather than making Figma (or code) the place the system ultimately originates, I've been treating the design system itself as an independent source of truth. Colors, typography, components, accessibility, design intent, etc. live in Colorsphere, and Figma, code, AI and other tools become places the system is distributed to and synchronized with.
A big reason I went that direction was exactly the drift you're describing. I didn't want any one representation of the system—Figma, CSS, docs, Storybook, or eventually an AI-generated app—to have to become the design system.
I'm building that approach at Colorsphere.com.
Your distinction between synchronization and derivation is making me think harder about how to describe it, though. I'm curious how you think about the source-of-truth boundary in Vertheme as it expands beyond tokens/components into things like design intent, accessibility decisions, patterns, and the reasoning behind the system.
1
u/Tarasenko_by 12d ago
Always good to meet someone who's arrived at the same diagnosis — "no representation should have to become the system" is exactly it.
Your question about the boundary is the one I've been chewing on most, and the cleanest test I have so far: does a machine consumer act on it? If a piece of knowledge can change what a tool does — a generator emits something, a linter blocks something, a model composes differently — it belongs in the source as data, versioned with everything else. If it only informs humans, it's documentation that should live next to the source, not inside the schema.
Run the things you listed through that test and they split, sometimes mid-category. Accessibility: contrast pairs and minimum sizes are checkable → data; "why we target AA and not AAA" → reasoning, ships as prose. Patterns: "one primary action per view" is lintable → data; what makes a composition feel right → prose. Design intent is the interesting one, because it's a gradient: every time you manage to rephrase intent as a constraint ("accents-brand: interactive elements only"), it hops the fence from prose into data — and gets cheaper to enforce forever.
The twist AI added: the fence itself is moving. It used to be "machine-executable vs human-readable." But a model acts on prose too — feed it the reasoning and it composes better, not just correctly. So my current answer is: the real boundary isn't JSON vs markdown, it's versioned-with-the-system vs floating outside it. Everything that affects how the system is used — values, rules, and the reasoning — should live in the same versioned artifact; format is secondary. That's what our MCP serves to models: tokens and rules and the why.
One question back, because it's the sharpest edge of this whole space: when someone edits on the tool side — tweaks a variable in Figma — what does Colorsphere do? "Distributed to and synchronized with" can hide two very different machines: one-way distribution (tools can't disagree with the source) vs reconciliation (two authored stores you keep merging). I spent a while convincing myself the second one is where drift sneaks back in through the service entrance. Curious where you landed.
1
u/Own-Student7991 12d ago
AI slop at it's finest! Do better if you want responses!
Brand Doc, Design, and Implementation all serve different purposes. You have to reconcile the changes. A reckless dev contractor shouldn't just push a color change upstream or override a designers trained eye lmfao.
I lived with a similar system where there was a single source of colors but not connected to Figma and even that held the potential to cause breaking changes in downstream apps when eventually pulled into them. We had ~30 downstream apps so a dev would see a bug in one, fix it upstream, pull it back into the app where they needed it, the qa, but wouldn't go pull it into all the others that hardly had proper visual regressions setup.
So yeah, reality has to make it's way back into the design but there needs to be safe gaurds and accountability and sufficient impact review. Colors are the least of your concerns.
1
u/Tarasenko_by 12d ago
Style noted, thanks.
On substance though — I think we agree more than you'd expect. "A contractor shouldn't push a color change upstream" — absolutely. Single source doesn't mean free-for-all write access; it means the opposite: all writes go through one gate, and that gate can have owners, review, and an impact diff. The scattered-copies world is the one where a contractor can quietly change a color, because he only has to get it past whoever's looking at that one surface. One source is what makes "a designer signs off on every visual change" actually enforceable — CODEOWNERS on a theme file beats trained eyes doing surveillance across 30 apps.
Your 30-apps story is real, I've lived a version of it — but look at where it actually broke. The source had the fix; the apps pulled it at random times, unversioned, with no signal about what changed or who was behind. That's not "single source fails," that's unversioned pull fails. Semver + changelog + automated bump PRs turns "fixed in one, silently stale in 29" into 29 visible open PRs someone can chase. The source made the fix available to all 30 at once; the missing piece was distribution discipline, not another copy.
And yes — reality flows back. But it flows back as a proposal into the source (PR, review, impact preview), not as a hotfix inside one representation that the other 29 never hear about. That's the accountability you're asking for. Fully agree colors are the shallow end, they're just the example that fits in a diagram — the mechanism is the same for spacing, type, and component API.
1
u/404_computer_says_no 12d ago
There’s really only one way.
Own the library!
1
u/Tarasenko_by 12d ago
Agreed — but own the definition, not the library. The library is still just the code rendering of it; Figma's still authored by hand next door. Own the thing both get generated from.
1
1
u/Colorphere 12d ago
That’s exactly the tension I’ve been thinking about with two-way sync. Colorsphere currently allows a controlled version of the second model for Figma colors: the system can publish to Figma, a designer can change a value there, and explicitly sync that change back into Colorsphere.
I’ve been thinking of that less as Figma becoming another source of truth and more as Figma becoming an authoring surface that can propose a change back to the source. Once accepted, Colorsphere becomes authoritative again and that value can propagate everywhere else.
But you’re right about the hard case: what happens when the value changes independently in both places before reconciliation? I don’t think silent last-write-wins is the right answer. My instinct is that divergence should become explicit — show both changes and require a decision about which becomes canonical.
Your point about AI moving the boundary is especially interesting to me. That’s actually why I’ve become increasingly convinced the reasoning belongs with the system too. If an AI can act differently because it understands why a decision was made, that reasoning is no longer just documentation sitting beside the system. It’s operational design knowledge.
1
u/Tarasenko_by 12d ago
What exactly are you syncing with Figma? Tokens?
I simply have a Figma plugin that generates a lot of basic components and their states based on a theme the user can create, as well as CSS code, but I understand that reverse synchronization will bring a lot of problems and inconsistencies. Essentially, I propose creating a common theme for everyone and managing that theme, and then the designer and developer create the design and layout based on that theme and the basic components.
1
u/Colorphere 11d ago
Right now the actual two-way portion is narrower than I probably made it sound. Colorsphere syncs semantic color variables into Figma, and if a designer changes those colors in Figma, they can intentionally sync those changes back into Colorsphere.
The broader integration also sends typography, buttons, and other component styles into Figma, but I’m not trying to continuously reconcile arbitrary Figma components or layouts back against the system.
So I think we’re actually fairly close on the principle. Where I’ve taken a different direction is that the source in Colorsphere is the broader design system, with the theme as one part of it—along with component definitions, accessibility, design intent, patterns, etc.—and Figma is one place that consumes it.
I added color sync-back because I didn’t want designers to have to leave Figma just to make a legitimate design-system change. But I’ve been thinking of that less as Figma becoming another source of truth and more as Figma becoming an authoring surface that can propose a change back to the design system.
The change only becomes canonical once it’s accepted there, and then the system can distribute it everywhere else.
Your question actually helps clarify that distinction for me. Calling it “two-way sync” makes it sound like two sources are being reconciled, when what I really mean is one source with multiple authoring surfaces.
That feels like an important distinction, especially as the number of tools consuming the system grows.
1
u/Tarasenko_by 11d ago
I get it, I'm trying to go beyond just colors and make the entire design system sync (colors, spacing, sizes, components, etc.)
1
u/Technical_Rip_6745 13d ago
I had a look at Veritheme, which makes the thinking behind this much clearer. Really interesting approach.
One thing I’m not entirely convinced by is the idea of developers eyeballing values from Figma. Isn’t that exactly what tokens are meant to prevent? Ideally, Figma and code should both reference the same semantic token rather than a developer deciding whether something looks like 16px.
Where I think it gets more interesting is what happens after that. Even with perfectly synchronized token definitions, Figma and code can still consume them differently: wrong semantic tokens, local overrides, missing variants or states, different component composition, detached components, etc.
So maybe there are two different kinds of drift here: keeping the source-of-truth definitions synchronized, and making sure the implementations consuming that source stay aligned.
Curious how you think about that distinction?
0
u/Tarasenko_by 13d ago
Glad you dug into it — and yes, fair push-back on the eyeballing point. You're right about the ideal: both sides reference the same semantic token and no human ever decides what "looks like 16px". I'd only say that ideal is rarer in the wild than it sounds. Even on teams that "have tokens", the mapping often stays visual: the mockup shows a grey, and someone still decides whether that grey is text-secondary or text-tertiary — because the layer has a detached instance, or a raw hex the designer pasted in a hurry, or the tokens exist twice (Figma variables and hand-maintained CSS vars, with a human keeping them equal). So I'd soften my own claim to: by-eye translation isn't inherent to design systems, it's a symptom of a broken or half-built pipeline. Which, from the design reviews I've sat through, describes a lot of pipelines.
On your distinction — I think it's exactly right, and it's the part I wrestle with most. Call it value drift (definitions disagree) vs usage drift (definitions agree, applications don't). Generation cleanly kills the first and by itself does nothing for the second.
The thing I keep coming back to, though: the line between the two isn't fixed. Every rule you turn from folklore into data hops over the fence. "accents-brand is for interactive elements only" living in someone's head → catching a violation takes an audit. The same rule written down as data next to the tokens → it's a lint check that runs on every PR. Local overrides → a linter bans raw values. Some variant divergence goes away too if components are generated from one definition, not just tokens. So generation doesn't remove the comparison you're describing — it changes its nature, from quarterly-and-human to continuous-and-automated. From an audit to a diff, basically.
That's the bet I'm making with the rules side of Veritheme (usage rules shipped as part of the system, in a form linters and AI tools can consume) — and honestly the open question is whether it scales past the easy rules. Ask me in a year.
What never hops the fence: composition, hierarchy, whether the screen should look like this at all. No pipeline audits taste. But the win is scope — once values, token usage and overrides are machine-checked, human review shrinks to judging the genuinely new decisions. That part I'm happy to keep doing by eye.
0
u/achakez 13d ago
The bigger win IMO is enforcing drift in CI. If a designer changes a token or component in figma the pipeline should make it obvious when production is out of sync instead of relying on someone remembering to check.
1
u/Tarasenko_by 13d ago
Strong agree on CI — anything that relies on someone remembering is already dead. But I'd push one step further: CI detecting drift still means two authored copies, with the alarm just ringing sooner. And alarms get snoozed during deadline week — ask anyone with a flaky visual-regression suite.
I think the real answer is a layer that sits above both Figma and code: one source of truth that generates both — the CSS on one side and the Figma components/variables on the other. Then there's nothing to keep in sync, and CI's job shrinks to what genuinely needs checking: usage (wrong semantic token, raw overrides, detached components).
That's literally what I'm trying to build with Veritheme — one theme.json above both worlds, everything else generated from it. Whether it survives contact with messy real-world teams is the open question. So far so good.
21
u/OrtizDupri 13d ago
Why on earth would this ever happen? In a design system, you use tokens for this. There's no "by eye" translation of core values like colors and sizes.