An architecture decision review board at Cigna spent two years designing a platform and never built it. The design wasn’t the gap. “They had actually a really nice design that looked professional,” and “within each workflow, they would have each one of the steps outlined, kind of different options that they wanted for each part of the workflow. Different branching strategies.” The gap was one person: “what they didn’t have was an engineer that would be able to sit down and take all that information and actually build out a site.”
I got two weeks. React and Node.js on an ECS container, because that’s the stack the team named — “first thing I did was I asked the team what kind of tech stack they cared about” — and Cursor, driven by screenshots out of their Figma file. And nobody else on it: “this was me alone at the keyboard for two weeks, and didn’t really need to interface with the team.”
The method is the part that travels, and it isn’t a tool. “Kind of decompiling or decomposing everything myself instead of expecting an agent to do it.”
Whole pages didn’t work
Converting a Figma design to React starts at the top, with the whole page in one prompt. That’s where I began. “I started out with the general big picture screenshot on what the main page looked like, and dumped that into Cursor, just copy and paste a screenshot into the prompt” — then told it we were going to build this out, this is what I want it to look like. It got close. “It’s not perfect, but I was able to iterate over time to be able to get it to look like what they had in Figma.”
Then it stopped scaling. “Because Sonnet 3.5 was not super powerful, that doing entire pages didn’t work out as well as it should.” The model couldn’t hold a page. It could hold a component.
“It just wasn’t all that smart, so it was more than capable to get you to solve incremental problems, but you as the engineer had to break down the problems and figure out how to force-feed it these things to solve.” That’s the whole method in one sentence. The breakdown is the input, and the breakdown is mine.
The unit of work
The unit of work is a leaf: one component, or one workflow with its steps in order. By the end it was “roughly two dozen components ended up being in the library, and for the workflows there was, I want to say, 7 or 8 workflows that were created, and each one of those had various branches throughout the workflows.”
I never wrote the breakdown out as a file — it lived in the order I took the screenshots. Written out, it’s a list of leaves and what each one is allowed to assume. Nothing below is the review board’s — the schematic and the prompts are reference, with synthetic names:
# Schematic only — synthetic names, not the real design.
page: request-intake
components:
- AppShell
- StepHeader
- FieldGroup
- OptionCard
- BranchSummary
- SubmitBar
workflows:
- name: new-request
steps: [scope, scale, data-class, review, submit]
branches:
scale:
small: review
large: data-class
Components first, then workflows, and they get built in that order. A workflow that has to invent its own buttons mid-flow invents a different button every time.
The component pass
Each component got its own screenshot and its own prompt. “Hey, I need to create a React component that looks like this” — “and then provided a screenshot of specifically that React component. And I would do that for all the major components that they had throughout the site.”
One hurdle is the reason this pass carries a standing instruction. “Historically, and especially at that age and that model, like, it would go and rebuild its own components all the time and it wouldn’t reuse the ones that you already had in your project. So that was a hurdle that I had to get over.” The fix went into the next prompt and every one after it: “hey, make sure that you reuse any previously built components.” “Over the course of several days, I had all the component library built out.”
Written the way I’d hand my standing instruction to someone else:
Build one React component matching the attached screenshot.
Before writing anything:
- list what already exists in src/components/ and reuse it
- if an element is close to an existing component, extend that
component with a prop; do not create a near-duplicate
- name a new component only after ruling reuse out
Scope is this component only. Do not build the page around it.
When you're done, tell me which existing components you reused.
The workflow pass
A workflow gets its steps in order, in one prompt. “I would take screenshots of each one of the workflows, like, incrementally 1, 2, 3, 4, 5 different screenshots.” Then an instruction the component pass never needed: “hey, I need you to help build this workflow. Help guide me through it. Ask me questions.”
The last sentence is the important one. “When you’re talking with an AI, to ask it to prompt you for any questions that it may not have answers to is always a very important feedback loop that you give the AI.” A screenshot shows a branch — not what the branch tests, not where the state between steps lives, not what happens after the last screen. The model either asks or guesses, and only one of those is recoverable.
The workflow prompt:
Attached: one workflow's screens, in order, including the branch
each option leads to.
Build it from components that already exist in src/components/.
Add a new one only if nothing fits, and say so when you do.
Before you build, ask me every question the screenshots don't
answer — what each branch condition actually checks, where state
lives between steps, what happens after the last step. Wait for
my answers. Then build.
Week one was the whole thing clicking through: “I built out the majority of the site and had things clicking through within a week.” Week two was scope added on top, not slack consumed — the sponsor’s bonus asks, including an in-app assistant that read the page state and drove the UI.
Why not a design-to-code tool
Design-to-code tools existed, and this is the field’s record on them, not a bake-off I ran. I never put Dev Mode, v0, Builder.io, or Anima side by side against the screenshot method. What follows is what those vendors published, checked against their own pages.
Figma Dev Mode is a handoff surface, not a generator. Figma’s own guide describes it as a place to “navigate design files and transform designs into code,” where the code snippets are “autogenerated” — and it ships Code Connect precisely so teams can “bring component code into Dev Mode” and let developers “see design system code from their libraries instead of auto-generated code.” Code Connect’s April 2024 announcement names the problem directly: “Since developers aren’t rewriting components, there’s less code to maintain.” That is the same hurdle my standing instruction was patching, sold as a feature — and it’s limited to Organization and Enterprise plans.
Builder.io’s Visual Copilot is the closest thing to an end-to-end converter. Its launch post describes a real pipeline: a model “trained with over 2 million data points” flattening design structure into code hierarchies, the open-source Mitosis compiler emitting framework code, then “a finely tuned Large Language Model (LLM) refines the code.” Its headline number is a time claim, not a fidelity claim — “save developers 50-80% of the time they spend turning Figma designs into clean code” — and component mapping, the reuse mechanism, shipped as “coming soon” in that post: it “uses AI to map reusable components in your Figma file to those in your code repository.” Anima converts a design “carrying its structure, assets, and visual details into the result,” emitting HTML or React.
The interesting part is what the tools tell you to do with the design first. v0’s own Figma documentation says to “keep each screen or state in its own frame,” to “give pages, frames, and components clear names,” and to “use a frame link when you need an exact screen or component.” That’s decomposition. The tool doesn’t remove the job. It moves the job upstream into the Figma file — and the Figma file wasn’t mine.
| Tool | What it is | Reuse mechanism | Headline claim | Caveat |
|---|---|---|---|---|
| Figma Dev Mode | Handoff surface — “transform designs into code,” snippets “autogenerated” | none on its own; ships Code Connect for that | — | — |
| Code Connect | Brings real component code into Dev Mode instead of auto-generated snippets | maps design components to code components already in the repo | “Since developers aren’t rewriting components, there’s less code to maintain” | Organization and Enterprise plans only |
| Visual Copilot | A model, the Mitosis compiler, then an LLM refinement pass | AI component mapping — “coming soon” at launch | “Save developers 50-80% of the time” turning designs into code | reuse mechanism unshipped at launch |
| Anima | Converts a design to HTML or React | — | “Carrying its structure, assets, and visual details into the result” | — |
| v0 | Design-to-code generator | — | — | reads structured Figma frames; moves the decomposition job upstream into the file |
Two honest gaps. I found no independent benchmark scoring these tools against each other on the same design. The published percentages are vendor time-savings claims with no stated sample or baseline. The reuse problem also outlived the fix. A bug filed against Figma’s Code Connect repository in April 2026 reports that Figma Make, Figma’s own AI page generator, “does not use the custom components from my published library that are mapped via Code Connect. Instead, it uses default base components” — which the reporter calls “breaking the design-to-code workflow.” The instruction I was typing by hand in Q2 2025 was still being filed as a bug a year later.
First make it work, then pay the debt
Nothing was quietly broken underneath, and the reason is batch size, not model quality. “I was working in such small batches on trying to get things done — and along the way having the agent write proper unit tests and using Playwright to be able to validate the UI as it was being built — like, it worked well.” That’s the same rule I run on now: autonomy expands with what you can verify, not with what the model can do.
What did break was consistency. “There was a combination of TypeScript and plain JS, and naming conventions were not the same all throughout. Which really was frustrating for me.” Before the handoff, “I did many, many passes to clean up the code base so that it looked uniform, everything was switched to TypeScript.”
I don’t treat that as a failure of the method. “I don’t think that it’s smart or safe to say that we should build AI and have it perfect on the first shot. I think it’s an iterative process.” First get it to work, “even if it’s not following all the conventions that you want, and then once it works, then you take a period to deal with all the tech debt” — all of it while making sure it still works.
The refactor pass paid off twice. “It forced agents to look at it from a different lens. Which is important, right? And it sees things differently from that perspective.” Build and refactor are different tasks, so they surface different problems on the same code. The cleanup pass was a second reading of everything the build pass had shipped, done by an agent with a different job.
Underneath
Docs checked 2026-09-02. The quoted instructions inside the prompts are mine; no client code appears anywhere here.
Pasting a screenshot into the prompt is a documented capability, not a trick. Cursor’s own prompting guide
says to “attach images to your prompt to provide visual context for UI work, debugging, and design
implementation,” by “drag and drop” or “paste from clipboard with Cmd+V, including screenshots” (Cursor, prompting agents). On the model side, images are a first-class content type — Anthropic’s
vision documentation describes
sending images as image content blocks alongside text.
On the model version: I remember this as Cursor with Sonnet 3.5, in Q2 2025, and the minor version is the
part I won’t pin. Cursor’s own forum shows the dated claude-3-5-sonnet-20241022 identifier
leaving the default picker in November 2024
while the generic claude-3.5-sonnet selection kept routing to it, with
Claude 3.7 Sonnet available from February 2025
and
Claude 4 from late May 2025. Read the quotes above as the model I selected, not as a version claim.
The design-to-code sources. Figma’s guide to Dev Mode, for what Dev Mode inspects and generates. Figma’s Code Connect announcement (April 16, 2024), for the reuse mechanism and the rewriting problem it targets. Figma’s Dev Mode MCP server post (June 4, 2025), for the agent-facing interface that arrived at the very end of that quarter, exposing “three tools in the MCP server… one for code, another for images, and a third for variable definitions.” Builder.io’s Visual Copilot launch post (October 12, 2023), for the Mitosis pipeline, the 50-80% time claim, and component mapping. v0’s Figma documentation, for what it reads out of a file and how it tells you to structure one. Anima’s product page, for its HTML and React output. The Code Connect bug is figma/code-connect#393, filed 2026-04-27 and since closed.
Related system
More field notes
Traffic shifts to the new version and back on bad health, while the repository only moves forward
AWS Lambda, AWS CodeDeploy, Amazon CloudWatch, AWS SAM
Newer · Sep 2026
Page state in, a JSON action list out, executed by the client and held by two allow-lists
React, Node.js, Claude API (Anthropic SDK), JSON Schema
Older · Sep 2026
Start
I’ll tell you in about a day whether I’m the right person. The first conversation is fit, not a free architecture review.