Figma to Next.js: shipping design without a handoff
Going from Figma to Next.js with no handoff: why one person designing and coding preserves design intent, plus the real workflow and the honest tradeoffs.
The expensive thing nobody puts in the invoice
A design dies a little every time it changes hands.
Not in a dramatic way. The build ships, the client approves, everyone moves on. But if you put the original Figma file next to the live site, you can feel the gap. The spacing is a little tighter here, a little looser there. The button that was supposed to lift on hover just sits there. The empty state, the one the designer never drew, is a sad centered sentence in gray. Nothing is technically broken. The thing just feels less alive than it was meant to.
I build the whole thing myself, design and code, so I never hand a file over a wall. That is the whole pitch. And I want to be honest about why it works and where it stops working, because "one person does both" gets sold as magic and it is not magic. It is just fewer translation errors.
Pixel-perfect was never the problem
People think the handoff breaks because the developer gets the numbers wrong. Wrong padding, wrong font weight, color off by a shade. That stuff happens, but it is the easy half. You can catch it with a ruler and a screenshot diff.
The hard half is intent, and intent does not live in the file. It lives in the head of the person who made the file.
A few things that almost never survive the trip:
- Spacing rhythm. A good layout has a pulse. The gaps relate to each other: this is twice that, this section breathes more than that one on purpose. A developer reading individual pixel values sees a list of unrelated numbers and rounds them to whatever the component library already does. The rhythm flattens into "looks about right."
- Motion. Most Figma files have no motion in them at all. So motion gets invented at build time, by someone who did not design the page, usually as a default fade because that is what is fast. The thing that was supposed to feel deliberate feels like a template.
- The states nobody drew. Hover, focus, empty, error, loading, disabled. A static design shows the happy path: a list with three items in it. Real software shows zero items, then a spinner, then a failed request. If those screens were never designed, the developer designs them, on a deadline, with no design system to lean on. That is where products start to look cheap.
- Responsive intent. A design at 1440 and a design at 375 do not tell you what happens at 900. The designer knew. The two-column grid was supposed to stack, the headline was supposed to drop a size, the image was meant to crop from the center, not shrink into a stamp. None of that is written down. The developer guesses.
Pixel-perfect copies what a design looks like. Preserving intent copies what a design is for. The handoff loses the second one because it was never in the file to begin with.
One head, one set of decisions
Here is the actual reason doing both works, and it is boring: decisions get made once, with full context.
When I design a card, I already know what it costs to build. I am not going to spec a layout that needs three nested grids and a magic number to line up, because I am the one who has to make it line up at 2am. So I design things that are good and buildable. The constraint makes the design better, not worse.
It runs the other way too. When I am in the code and I hit a choice the design did not cover, I am not guessing what past-me wanted. I know why the section breathes the way it does, so I know what to do at the in-between width. There is no Slack thread, no "hey can you clarify the hover," no compromise that quietly drifts off the original idea. The idea and the implementation are the same conversation.
That is what "design and code, same person, no handoff" actually buys you. Not speed, though it is faster. Coherence. The thing feels designed because the person deciding how it looks and the person deciding how it behaves are not two people with a meeting in between. You can read more about how I work on the about page.
What Figma to Next.js looks like for me
The workflow is less "design fully, then build" and more "design knowing exactly what I'm about to build."
I design with the framework already in mind. I am building in Next.js with Tailwind, so I design in the same units the system thinks in. My spacing scale in Figma is the Tailwind scale. My type ramp is the type ramp. When I draw a component, I am drawing it close to how it will decompose into actual components, props and all, so there is no awkward re-architecture when I move to code.
Design tokens map straight to the theme. The colors, spacing, radii, and type sizes I pick are not arbitrary swatches. They are the values that will live in tailwind.config. So the translation step is mostly mechanical:
// tailwind.config.ts - the design tokens, made real
export default {
theme: {
extend: {
colors: {
ink: "#11110f", // body text
bone: "#f4f1ea", // surface
cool: "#6b7280", // muted / secondary
},
spacing: {
gutter: "1.5rem", // the page rhythm, named once
},
borderRadius: {
card: "1rem", // every large surface uses this
},
},
},
}
Once the token is named, the rhythm is enforced by the system instead of remembered by a person. A card radius is rounded-card everywhere, not rounded-[15px] here and rounded-2xl there because two people read the file differently. There are no two people.
Motion is part of the design, not a topping. Because I build the animation myself, in GSAP, I design with it in mind from the start. A reveal is not "fade everything in"; it is a choice about what moves, how far, with what easing, and in what order, because order is meaning. The hover on a card is decided when the card is decided, not bolted on by a developer who never saw the intent.
I design the states because I have to build them anyway. This is the part the handoff model structurally cannot do well, and the part I care about most. I design the empty state, the loading skeleton, the focus ring, the error message, the disabled button. Not because a brief asked for them, but because the moment I sit down to build the component, those screens exist whether I drew them or not. I would rather decide what they look like on purpose. A site where the empty state and the error state look as considered as the homepage is a site that was built by someone who had to live in all of it.
Where this model stops working
I am not going to pretend the same-person model wins every fight. It does not, and a founder hiring me should know exactly where the edge is.
It does not scale to a huge product. One person is one throughput. A fifty-screen enterprise app with a team of twelve does not want a single human as the bottleneck on both craft and code. At that size you need specialists, a design system team, a frontend platform team, the whole machine. The handoff exists because at scale you cannot avoid it; you can only make it less lossy with good tokens and good documentation. I am not the answer for that org. I would be lying if I said otherwise.
There is a capacity ceiling. I can hold one or two builds in my head at full depth. Past that, quality is the thing that gives, and quality is the only reason to hire me, so I would rather say no than ship something thin.
"Both" only beats "two specialists" when the both is genuinely good. A person who is mediocre at design and mediocre at code is worse than a strong designer plus a strong developer, even with the handoff tax. The no-handoff advantage is real only if the single person clears the bar on each craft independently. That is a high bar and it is fair to ask me to prove it. Four years in graphic design and two in UI/UX before I shipped a single production frontend is how I got there, but the proof is the work, not the resume.
So the honest version is: this is not the universal best way to build software. It is the best way to build a certain kind of thing.
Who should actually want this
If you are a founder or a small team and you want one site, app, or marketing surface that feels designed and actually works, this is the model that gives you the least friction and the most coherence. One person to brief. One person accountable. No diff between the mockup and the live thing, because there was never a moment where the idea got translated by someone who did not have the idea.
You get a result where the motion was intended, the empty states were designed, the responsive behavior was decided and not discovered. The feel survives, because the feel never left the building.
If that is the kind of thing you are making, that is the kind of thing I do. Have a look at how I work and what it costs, and if it fits, let's talk.