Portfolio/Writing/Giving developers Claude Code is not a design handoff

Giving developers Claude Code is not a design handoff

Handoff was never "here is a tool that can read Figma and write code." It was a transfer of intent, constraints and edge cases from one head to another, and most of that transfer still happens nowhere. Seating an agent between design and engineering does not close the gap, it moves where the gap gets discovered, usually into production. What handoff was actually for, where it breaks now, and what a contract that a human and an agent can both build from looks like.

A team ships Claude Code to its front-end devs, points it at a Figma file, and calls the handoff problem solved. It is not solved. It is deferred, and it comes back at a worse time: in review, when the screen looks right and behaves wrong, or in production, when an operator hits a state nobody specified. Handoff was never "a tool that can turn a design into code." It was a transfer of intent: what happens when the list is empty, why that field is disabled on Tuesdays, which of these three visually identical buttons is destructive. Giving an agent design-file access does not transfer any of that. It just gives the gap a faster way to become code.

The tool didn't remove the gap in the handoff. It just removed the moment someone used to notice the gap existed.
Scope
This is not an argument against agent-assisted front-end work: back-office is where it already pays. It is an argument against treating tool access as process. The companion piece on designing and building becoming one activity covers what changes when one person does both. This one is about the more common case: separate people, separate tools, and a handoff step that has to actually transfer something.

What handoff was actually supposed to transfer#

Before there was a Figma link, handoff was a conversation. A designer walked a developer through the screen, and in doing so answered questions nobody had written down: what happens on error, what the loading skeleton looks like, whether the empty state is an illustration or a one-liner, which validation blocks submit and which just warns. The artifact (the file, the spec, the ticket) was never the whole transfer. It was a reference for a shared understanding that mostly lived in people's heads and got filled in by asking.

That already degraded once design and engineering stopped sitting next to each other. A link replaced the conversation, and everyone pretended the file was self-describing. It mostly wasn't. It just had a human on the other end who could infer the missing states from experience, or walk over and ask. An agent has neither. It will happily infer an empty state, and it will be wrong in a way that compiles, reviews clean, and ships.

Same style, opposite consequence
Three order actions. Only one can't be undone.
๐Ÿ“ฆACTION
Archive order
Hides it from the active queue
๐Ÿ“‹ACTION
Duplicate order
Creates a new draft with the same lines
๐Ÿ—‘๏ธACTION
Cancel & refund
Reverses payment, releases the stock hold
!One of these three is irreversible. The mockup does not say which, and neither did the ticket.
Same size, same color, same border, same weight. Nothing in the file says which one is reversible, which one needs a confirm dialog, and which one is not coming back.

The tool-access mistake#

"Give the devs an agent that can read the design file" treats handoff as a format problem, as if the reason things got lost was that a human had to manually translate a picture into JSX, and a model doing the same translation faster removes the loss. It doesn't, because the loss was never in the translation step. It was upstream, in everything the picture never said.

What a Figma file showsWhat the build actually needs
The happy path, once, at one viewportEvery state: loading, empty, error, partial, offline
A static value in a text fieldWhat happens when that value is null, huge, or stale
A buttonWhether it is disabled, and by what rule, from which source of truth
A layoutWhat reflows, truncates, or wraps at real content lengths
A color and a spacing valueWhether that is a token or a one-off, and which token
One happy-path clickThe permission, ownership and role checks behind it

An agent pointed at the left column will confidently produce the right column anyway, it has seen ten thousand admin screens and knows what an error state usually looks like. Usually is the problem. It will guess plausibly and consistently, which is worse than guessing badly, because plausible-and-wrong survives review.

Where it actually breaks now#

The backend contract is assumed, not settled

An agent building a screen from a Figma file and a vague sense of the API will invent the shape it wishes existed, the same way a junior dev would, except it does so fluently and fills every gap instead of stalling to ask. The fix predates AI: curl it before you build the UI, and settle what the backend owns, what the front end owns, and the schema in the middle before anyone, human or agent, opens an editor. AI made this more urgent, not less: the agent will not push back on a bad contract the way a person is supposed to.

The contract, guessed vs settled
A two-state guess ships a toggle. The field has four states.
What the agent assumed
{
  "status": "active" | "inactive"
}
Two states. Renders a toggle. Ships.
What the API actually returns
{
  "status": "active"
          | "inactive"
          | "pending_review"
          | "suspended"
}
Two states nobody built a UI for.
The gap surfaces as a support ticket, not a build error: an order sitting in 'pending_review' renders as a plain toggle nobody designed for.

The design system is the constraint, and it is often half-real

If the component library only covers the happy path, the agent fills the rest by inventing: a hand-rolled table, a one-off hex, a bespoke empty state that matches nothing else in the product. This is not a model failure, it is a missing constraint made visible faster. The fix is the same one that made back-office generation viable in the first place: a real system the agent may only compose from, states included, not just the primitives.

Intent still lives in a Slack thread

The reason the button is disabled on Tuesdays is a business rule someone explained once, in a meeting or a message, and never wrote into anything a build process reads. A human dev might remember it or ask. An agent will not go looking for a Slack thread, and mostly shouldn't have to. The fix is to stop storing intent somewhere unstructured and start writing it into the artifact that feeds the build.

Handing an agent a Figma link and calling it handoff is like handing a new hire a screenshot and calling it onboarding. The picture was never the documentation. It was a pointer to a conversation that used to happen around it.
Same gap, two outcomes
Nobody drew what happens when the order queue is empty
Before, a person in the loop
"What happens when there are zero open orders?"
๐Ÿ“ฆ
No open orders
Every order for today has shipped. Nice work.
Now, an agent alone with the file
(no question asked)
Publication result
Renders something, plausibly
Shipped as-is, nobody checked what an empty queue should say
The gap doesn't close when an agent joins. It just stops being asked about.

What a real handoff artifact looks like#

The test is simple: if a competent person could not unambiguously build the screen from the artifact alone, without asking a follow-up question, an agent cannot either. It will just fail silently instead of asking. Build the artifact to pass that test and both audiences are served by the same document.

  • States, not just layout. Loading, empty, error, partial, offline, permission-denied: each one specified, not assumed to look "however that usually looks."
  • The contract, not a guess at it. The real response shape, the real write schema, the real capability flags: linked or pasted in, not paraphrased.
  • Behavior at the edges. What a null does, what a 400-character name does, what happens when the list has one item versus ten thousand.
  • The rule, not just the outcome. Not "this button is sometimes disabled" but the exact condition and where it is evaluated: client capability check, or trust the server and just render what it says.
  • Which parts are system, which are new. Explicitly: compose these from existing primitives, this one interaction has no precedent and needs a human design pass.
State coverage, a typical handoff
One SKU screen. Five states it can be in.
ORDER-DETAIL ยท v1 spec
What the handoff file covers
1 / 5 SPECIFIED
Happy pathโœ“ Drawn, reviewed
Loadingร— Not in the file
Emptyร— Not in the file
Errorร— Not in the file
Permission-deniedร— Not in the file
What ships wrong
The four rows nobody checked
An agent fills them in anyway. Plausibly. Silently.
A publication state is usually the result of several checks agreeing a screen is actually ready to hand off, not just drawn.

None of this is exotic. It is what a good spec always contained. The difference is that a good spec used to be optional, because a human developer could absorb the gaps through experience and a hallway conversation. With an agent in the loop, the gaps do not get absorbed. They get filled with something that looks finished.

Settle the contract before anyone opens a tool#

The actual fix is sequencing, not tooling. Design, front end and backend agree on the contract (the states, the schema, the rules) before Figma gets polished or an agent gets prompted. This is slower on day one and faster on every day after, for the same reason a reviewed API contract is faster than three rounds of "wait, what does this field actually mean" discovered in a PR. An agent can help draft that contract and even help stress-test it by listing the states it does not yet cover, that is a genuinely good use of the tool. What it should not do is stand in for the contract not existing.

Sequence, not tooling
The order that actually saves time
๐ŸŽจROLE
Design
States, flows, what "done" looks like
๐Ÿ’ปROLE
Front end
What renders for each state
๐Ÿ—„๏ธROLE
Backend
The real response and write shape
One settled contract
Then: Figma, a prompt, or both, human or agent
Slower on day one. Faster on every day after.
Three roles agree on one contract before anyone opens a design tool or a prompt, human or agent.

What still needs a human relay#

  • Deciding the states that matter. An agent can enumerate "here are states you have not specified." A human decides which of those are worth designing for versus safe to default.
  • The contract review. Someone has to actually read the schema and catch that it is wrong, before it becomes twelve generated screens built on top of it.
  • Novel interaction. Anything with no prior art in the system is a design judgement call, not a composition of existing primitives.
  • The tacit business rule. Getting it out of the Slack thread and into the artifact is a human writing task, and usually the most valuable ten minutes in the whole process.
  • Saying the screen shouldn't exist. Agents fill in whatever they're pointed at. Nobody points them at "maybe don't build this."

How to actually close the gap#

  1. Settle the API contract first, reviewed by a human on both sides, before any screen (human- or agent-built) gets started.
  2. Write states into the design artifact, not just the happy path: loading, empty, error, partial, permission-denied.
  3. Move tacit rules out of Slack and into the spec the build actually reads from.
  4. Constrain the agent to the design system's primitives and mark explicitly what is genuinely novel and needs a human pass.
  5. Use the agent to find gaps before code exists: ask it to list the states the spec doesn't cover, not only to fill them in after.
  6. Review for contract mapping and edge-case coverage, not line count. A clean diff can still be built on an assumed shape.
text
# before a screen gets built, human or agent, settle:
โœ“ the contract: real response shape, real write schema, capability flags
โœ“ every state, not just the happy path
โœ“ the business rule and its exact condition, written down, not verbal
โœ“ which parts compose from the system vs. genuinely new
โœ“ who reviews the contract mapping before anyone reviews pixels

The honest bill#

  • Writing states and rules into the artifact is real, unglamorous work, and it was already the part everyone skipped before AI existed. It doesn't get easier now. It gets more necessary.
  • A settled contract slows down day one. It removes the far more expensive round-trip of a screen built on a guess, discovered three sprints later.
  • An agent that fills gaps plausibly will pass review more often than a human who stalls to ask a question, which makes the gap-filling failure mode harder to catch, not easier.
  • None of this replaces the designer or the backend owner. It moves the point where their judgement gets applied: earlier, into the contract, instead of later, into a bug report.
Summary
The gap in design-to-dev handoff was never a translation problem between a picture and code. That part an agent genuinely speeds up. The gap was, and still is, everything the picture never said: the states, the edge cases, the rule someone explained once out loud. An agent with access to your design tool fills those gaps with a plausible guess instead of leaving them open, which makes the underlying problem quieter, not gone. Fix the artifact (states, contract, rules, written down) and the same document serves the human and the agent. Skip that and Claude Code is just a much faster way to build the wrong screen.

Next up
Back-office is where AI-built UI belongs first

The "can AI build the front end" argument keeps using the consumer product as its test case โ€” the one place models are weakest. Back-office is the inverse: templated screens, a design system that constrains the output, a spec that already exists in the API contract, users who file tickets instead of leaving, and enough volume to pay back the scaffolding. Where agent-built UI is already net-positive, what still needs a human, and how to set it up.

Read next โ†’