There's no handoff between my designs and production anymore
7 min read
I changed one line in a CSS file and every button on my site turned into a pill. I refreshed the browser, looked at it for a second, and moved on. Nobody had to update a spec, and nobody had to ask a developer if they had five minutes before lunch.
That still feels a little strange to me. I’ve been in design for almost eight years, and for most of that time the hardest part of the job came after the design was finished.
The gap I used to live in
If you’ve worked on a product team, you know the routine. You finish a screen in Figma and annotate it: the spacing, the font sizes, the hover states, what happens when a name is too long. You hand it over. A week later you open the staging build and something is off. The padding is a little tighter, and the corners are rounder than you drew them.
So you leave a comment. It gets fixed, and by then something else has drifted. The Figma library says one thing and the codebase says another, and after a few months nobody is sure which one is right. I’ve had more conversations than I can count that started with “that’s not what the mockup looked like,” and honestly I’ve been on both sides of that sentence.
None of it was anyone’s fault. A design file and a codebase are two copies of the same idea, and keeping two copies in sync is a job everyone shares and nobody owns, so they slowly drift apart.
Describing a system instead of drawing it
What changed for me is that I stopped making the second copy. These days I lead product design at Mutolaa and build small apps and tools on the side, and when I start something new I work with a coding agent. I describe the design system in the pieces it’s actually made of. Tokens come first: color, the type scale, spacing, radius, motion. Then components, built only from those tokens. Then compositions, the bigger pieces like a page shell that arrange components into something you can use.
The agent writes all of that as code from the start. There’s nothing to translate later, because the first version already lives in the browser. What I’m looking at while I design is the product itself, running at real sizes with real text.
If “tokens” sounds abstract, it’s simpler than it sounds. A token is a named value. Rather than pasting the same hex code into fifty places, you write it once, give it a name, and everything else points at the name. On my site the token file has two layers. The bottom layer holds raw values, called primitives. On top sit semantic tokens, which say what a value is for: ink for headings, body for running text, muted for labels and dates, edge for the borders around components. Tailwind reads the semantic layer through a block called @theme, so the classes I use in components only know those names.
:root {
/* Primitives */
--gray-0: #ffffff;
--gray-600: #595959;
--gray-900: #212223;
/* Semantic */
--bg: var(--gray-0);
--ink: var(--gray-900); /* headings, emphasis */
--body: var(--gray-600); /* running text */
}
@theme inline {
--color-ink: var(--ink);
--color-body: var(--body);
}
The extra layer is there so components never touch a raw color. A heading is ink, and what ink happens to be today gets decided in one place.
How this site got built
My own site is the clearest example I have. I’d found a site I really admired, the kind where you can tell someone cared about every shade of gray. I showed it to the agent and asked it to break the design down into tokens, components and compositions before it wrote a single page.
That first step mattered more than I expected. The agent had to name things before it could build them: this is the body text color, this is the border, this is the radius on small controls. Once things had names, I could argue with them one at a time.
Within one session the site had a token file, a set of components like Button, Row, Section and PageHeader, a shell composition with rails on the sides and a pill menu that every page sits inside, and a /system page. It’s built with Astro and Tailwind CSS 4, and the tokens are plain CSS variables in a file called tokens.css that I can open and read like a list.
The /system page is my favorite part. It documents the tokens and the components, but it doesn’t keep its own copy of any value. It reads them live from the CSS. When a token changes, the documentation changes with it, because there’s nothing separate to forget. After years of style guides that were out of date the week they were published, I sometimes open that page just to watch it be right.
Then I iterated, mostly in the browser. I’d look at a page, decide something was off, and change a token. I switched the page background to pure white and the whole site followed. I turned the palette monochrome, so hierarchy comes from shades of gray, weight and size rather than hue. I made every button fully rounded, which is the pill from the top of this post. And I gave one button an iridescent, animated sheen, an indulgence I’d have felt guilty asking a developer to spend an afternoon on.
Each of those was a change in one place. I didn’t go hunting through components, and nothing got missed, because the components only knew the names.
There’s also an Agent view toggle that outlines the page the way an AI agent reads it. The outlines use Figma’s selection blue, so in a small way Figma made it into the code after all.
Where it still needs me
I don’t want this to sound like magic. The agent is quick and careful with structure, but it has no taste of its own. Left alone, it’ll happily build something generic, the same rounded cards and safe grays you’ve seen on a thousand landing pages. It does it neatly, which almost makes it worse, because neat and generic is very easy to accept.
So a lot of my time goes into corrections. That weight is too heavy. This label should be muted, not body. The gap between these rows is wrong, and here’s why. No, smaller than that. The agent takes corrections well, and once a decision lives in a token it stays decided, which is more than I can say for most of the redlines I’ve written.
You also have to review what it builds, properly, the way you’d read a colleague’s pull request. Sometimes a component quietly uses a raw value where it should use a token, or a new pattern shows up that does almost the same job as an existing one. Those things are small today and expensive later. I read the code the way I used to check a staging build, with one difference: I can fix what I find in the same minute, while my opinion is still fresh.
What Figma is for now
I still open Figma. When I don’t know what I want yet, a canvas is the best place to think. I can put several directions side by side and try layouts that would be silly to build. I make Framer templates for Anabios too, so I’m hardly against visual tools. Exploring is cheap on a canvas, and I want to keep it that way.
But once I know what I’m making, the code is what counts. The tokens live in tokens.css, and the /system page shows what’s true right now. Figma has turned into my sketchbook, and the finished drawing lives in the browser.
The part I keep thinking about is that /system page. On a personal site it’s a nice touch. On a product with a whole team behind it, documentation that can’t fall out of date could make a lot of those “that’s not what the mockup looked like” conversations unnecessary, and I’d like to find out how far that idea can go.