We vibecode too. Plenty of what we build starts as something generated in an afternoon, and that isn’t a confession, it’s just faster than sketching. The demo works, it looks like the thing, and for a day it feels like you skipped six weeks.
Then you try to put it in front of people who don’t know where not to click.
A vibecoded prototype is a demo of the happy path
That’s the whole definition. A vibecoded prototype is software that proves the path where everything goes right: someone signs up with a real email, uploads the file you had in mind, pays with a card that works, and the screen does what the screenshot promised.
A product is mostly the other paths, and there are more of them than anyone expects. In roughly the order they tend to bite:
- Money. The card declines, the subscription lapses mid-month, someone asks for a refund, a promo code has to apply to one seat and not another. Every one of those is a branch, and each branch touches what the user is allowed to see.
- Identity and permission. A second person joins the same account. Someone gets invited, then removed. A trial ends. The question “is this person allowed to do this” turns out to be asked in forty places, and a prototype usually asks it in none.
- Concurrency. Two people open the same record and one of them is about to lose their edit without being told.
- Email that arrives. Your confirmation lands in spam and the user is certain the signup failed. Deliverability is its own discipline and it does not come with the generated code.
- Time. Somebody’s clock isn’t your clock, so the reminder fires at 3am. Daylight saving moves and every stored time shifts an hour, or doesn’t, and you find out which in April.
- Files people actually have. Not the clean sample you tested with. The wrong format, the one that’s ten times too big, the one that’s technically the right format and full of garbage.
- The bad row on a Sunday. Something is wrong in the data and there is no screen that can fix it, so the fix is you, in a console, on a weekend.
- Knowing it broke. A prototype has no error reporting, so the first person to tell you about a failure is a user, if they bother.
None of that shows up in a demo, which is exactly why demos got so cheap. The generated prototype isn’t lying to you. It answered a smaller question than the one you’re about to ask it.
Can you take a vibe coded app to production?
Usually not as it stands, and that matters far less than it used to.
The instinct is to treat the prototype as an asset to be salvaged, because that’s how it worked when building was expensive. Ten years ago throwing away a working codebase meant throwing away months of somebody’s salary, so people held onto architectures they’d outgrown for years. That math is gone. Rebuilding the same product properly is now a fraction of what the original build cost, and the second attempt starts with knowledge the first one didn’t have.
The signs you’ve reached that point are consistent enough to list. You’re afraid to change things, because you can’t predict what else moves. You can’t explain why a particular part works, only that it does. Nothing would tell you if a fix quietly broke something else. Adding a second type of user, or a second organization, seems to touch everything. You’re editing data by hand more often than you’re shipping.
Those aren’t signs you chose the wrong tool. They’re signs the prototype finished its job.
You keep the decisions, not the code
Here’s the part that gets skipped. What you want to carry across isn’t the implementation, it’s every decision buried inside it.
Why onboarding asks for this field and not that one. What the product deliberately refuses to do. How the empty state should feel when someone arrives with nothing. Which trade you already made, argued about for a week, and then completely forgot you made.
Almost no prototype writes any of that down. The decisions are real, they’re just implicit, sitting inside a layout nobody ever explained. Rebuild without them and you rediscover every one by getting it wrong first, which is the actual reason second builds sometimes go badly. Not lost code. Lost reasoning.
What does carry over
The prototype isn’t worthless, and pretending otherwise is its own mistake. Several things survive intact:
The copy, usually. Words you wrote while thinking hard about a screen tend to be better than words you write later while thinking about a deadline. The flows, once you’ve watched people move through them. The visual direction, if it earned any affection. And the screens themselves, which are a specification that happens to be executable, and a far more precise one than the document you would have written instead.
What doesn’t survive is the part underneath: the data model that assumed one user, the auth that assumed one role, the jobs that assumed nothing ever fails.
The written layer is what survives
Every repo we run now carries a file that reads like a spec. Palette with roles, type hierarchy, component recipes, an explicit list of the things we don’t do. It’s written for whoever builds next, and increasingly that reader is an agent rather than a person, which has made the writing sharper. Vague rules produce vague output fast enough that you notice.
We tested it by accident when we replaced this site’s entire theme. New layouts, new components, a full visual rebuild, nothing reused. The system came through intact, not because any code survived, but because it was written down somewhere the deleted code couldn’t take with it.
tidi went through the same thing this year, rebuilt from scratch with not one file kept. What made the second pass quick wasn’t anything we salvaged. It was that we finally knew what the thing was, and had said so out loud.
That’s the asset. Generated code is disposable and getting more so. The written layer is the part nobody generates for you.
When the prototype is enough
Sometimes the honest answer is to keep shipping it, and this deserves saying because the rebuild advice gets applied too broadly.
If the thing is internal, if it serves a handful of people who can be told “don’t do that,” if its whole job is to answer a question and then be deleted, then production standards are overhead you don’t need. Plenty of useful software should stay a prototype forever.
The wall only matters when strangers arrive, when money moves, or when the data becomes something you’d be embarrassed to lose. Those three, not code quality, are what turn a demo into a product with obligations.
How to harvest a prototype before you rebuild
If you’re sitting on something generated that demos well and can’t ship, the move is neither to salvage it nor to feel bad about it. Spend an afternoon taking the findings out first.
Write down the flows you kept changing, and what finally settled them. The screens you opened once and never again, which are features you can cut without grief. The feature you were certain was essential that turned out to be decoration. Every rule you enforced by remembering rather than by code. The questions real users asked that the interface should have answered.
Then screenshot everything, because in six weeks you will not remember why a particular button was there and the picture will tell you.
That document is worth more than the repository, and it’s why the second build is faster and calmer than the first.
The prototype was never the product. It was the research, and research is only wasted if you throw the findings out with the code.