When a prototype needs to become a product, the question I hear most is whether to keep the code or start again.

I think that's the wrong question. The code is the least valuable thing in a quick prototype. It was generated quickly, on foundations that were never meant to hold real users.

What took real time was everything you decided along the way. The screen you reworked until it made sense. The label a customer misread. The step you cut because nobody needed it. Those decisions came from thinking and from watching people react, and they're the part worth keeping.

So I keep the prototype as the spec and rebuild the foundations underneath it.

What a prototype actually settles

A good prototype has answered questions that are slow and expensive to answer any other way:

  • The flows. The order of steps, what happens on which screen and where people start.
  • The screens. Layout, hierarchy and what belongs on each page.
  • The copy. Labels, button text and explanations people understood.
  • What users reacted to. What confused them, what they asked for and what they ignored.
  • What you cut, and why.

It has also left questions open. A quick prototype rarely has to decide who can see what, what happens when data is missing or how the product behaves when something fails. Those are gaps to fill, not decisions to keep.

Capture it before anyone touches the code

Prototypes drift once work starts. Someone tweaks a screen, a link changes, an old version gets overwritten. Capture the decisions first.

  1. Screenshots of every screen and state. Walk every flow at phone and desktop sizes, and name each image by flow and step. Save a copy of the code somewhere you control, and keep a version of the prototype running that nobody edits.
  2. A short recorded walk-through. Click through each flow and say out loud why it works the way it does. The reasons are the first thing to get lost.
  3. A decisions list. One line per decision: what was decided, why, and the evidence behind it, such as a user session, a customer's comment or a constraint. Include what you rejected, or a future developer or coding agent will suggest it again.
  4. Acceptance criteria for each flow. Turn each flow into statements someone can check, such as "a new user with no projects sees a short explanation and one button to create a project." Add the states the prototype never had, like empty, error and no permission, and mark them as new.

The test for this step: could someone who never saw the prototype rebuild its flows from what you wrote down?

What to keep and what to rebuild

My rule is simple. Keep what the user sees and said yes to. Rebuild what the user can't see but depends on.

Keep:

  • The flows and the order of screens.
  • The layout and visual hierarchy.
  • Copy that people understood.
  • The list of components the screens need: tables, forms, cards, dialogs.
  • Markup and styles, as a starting point when you port each page, if they're clean enough to read.

Rebuild:

  • The data layer. Sample records and browser storage become a real data model and database.
  • Sign-in, roles and access rules.
  • Anything that calls a model or holds a key.
  • State and logic that grew by accident.
  • Error handling, which usually isn't there yet.
  • Anything nobody can explain.

The order I port all of this in is in port it in steps.

How the prototype feeds the spec

The prototype answers "what should this look and feel like?" A spec also has to answer "what has to be true underneath?"

In my process, the spec comes before the code. The screenshots, decisions list and acceptance criteria go into the requirements brief alongside everything else: call transcripts, the map of how the work is done today, sample files, constraints, regulations and the one metric that matters. I've written about putting it all in one requirements brief.

The brief goes into Perplexity's deep research, which comes back with a detailed spec covering what the prototype skipped: users and roles, the data model, integrations, edge cases and security, with acceptance criteria for every core flow. I review it, push back where it's wrong, and lock version one.

Where the spec and the prototype disagree, decide on purpose. Sometimes the prototype was right and the spec is generic. Sometimes the prototype dodged a hard question. Either way, write the decision down and update the list.

Check the rebuild against what you captured

During the port, review every preview against the screenshots and the decisions list, not against anyone's memory.

Once a ported screen is approved, lock it in. Playwright can generate reference screenshots on the first run and compare later runs against them, which catches a change that quietly moves a screen away from what was agreed. Its docs note that screenshots differ between browsers and platforms, so generate and compare them in the same environment.

The acceptance criteria become your end-to-end tests. When they pass, the flow works the way the prototype showed it should, on foundations that can hold real users.

The short version

  1. Treat the prototype's decisions as the asset, not its code.
  2. Before work starts, capture screenshots, a walk-through, a decisions list and acceptance criteria.
  3. Keep what users saw and approved. Rebuild the data, access rules, AI calls and error handling.
  4. Feed what you captured into the brief and the spec, and settle conflicts on purpose.
  5. Check every preview against what you captured, and lock approved screens with tests.

The code got you to the first version fast. The decisions are what make the next one right.