Why you need to write a spec before you vibe code
You need a spec because your AI agent cannot read your mind, and without one it fills every gap with a guess you never got to approve. A spec is a short, living document that states the problem, who it is for, the scope, the app's main pieces, its data model, and the performance and security targets you are aiming for. It becomes the single source of truth your agent reads before it builds, so ambiguous decisions resolve against what you actually wanted instead of whatever sounds plausible to a model in the moment.
I'm Mahmoud Zalt, an independent senior AI systems architect who has shipped production software since 2010, that's 16 years. I founded Sista AI (sistava.com), where autonomous AI agents run in production, not demos. Writing a spec before generating a line of code is one of the least exciting habits in The Vibecoder's Handbook, and one of the ones I've watched save the most rework once real users show up.
What a spec actually is
A spec, short for specification, is a single document describing what the software must be and do. If you've heard the term PRD, product requirements document, that's the same idea wearing a heavier name. It is not the code. It is not a wishlist of features you might add someday. It is the shape of the thing you're building, written down in plain language, before you ask an AI agent to build it.
Think of it the way you'd brief a contractor. You wouldn't hand someone a pile of sticky notes and expect a finished kitchen. You'd write down what rooms exist, what connects to what, and what has to hold up under real use. A spec does the same job for software, except the person reading it is an AI agent that will happily start pouring the foundation the moment you say go, gaps and all.
It also isn't the same as a prompt. A prompt asks for one task: build this form, add this endpoint, fix this bug. A spec sits above all of that, it's the context every prompt should be checked against. When you ask your agent to add a feature, the spec is what tells it whether that feature fits the scope you agreed on, or quietly expands it.
Why this matters more with AI than it ever did with a human developer
A human developer who hits an ambiguous requirement usually stops and asks. They notice the gap, because filling it wrong costs them time and looks bad in a code review. An AI agent does not reliably do that. It fills the gap with something confident and plausible sounding, and moves on, because producing an answer is what it's built to do. You don't find out the assumption was wrong until you're testing the feature, or worse, until a user hits it.
Without a spec, this happens on every single prompt. Scope drifts session to session. A decision you made on Monday about how signups should work gets quietly reinvented on Thursday, because nothing wrote it down anywhere the agent reads. Two people working from memory instead of a shared document eventually contradict each other, and an AI agent with no memory of your last conversation is worse than two people: it starts from zero every time unless you give it something to read first.
A spec fixes this by giving the agent one place to check before it decides. It doesn't eliminate every judgment call, but it turns most of them from a coin flip into a lookup.
Here's a concrete version of the problem. Say you're building a booking app and never wrote down that cancellations need a 24-hour window. Ask an agent to add a cancel button today and it'll build one that cancels instantly, because nothing told it otherwise, and that reads as a perfectly reasonable default. Ask it to add refund logic next month, in a different session, and it might invent a completely different cancellation window, because the first decision only ever lived in your head. A spec is where that 24-hour rule gets written down once, so both sessions build the same app.
The five sections a working spec needs
You don't write a spec from a blank page. If you've already worked through the problem, the scope, the app's structure, its data, and its performance and security targets, the spec is mostly assembly: pulling what you already decided into one document your agent can open every time.
| Section | What goes in it |
|---|---|
| Problem & audience | The problem you're solving and who it's for, in a sentence or two each |
| Scope | The MVP, written as the must-have user stories, nothing you'd like to add later |
| Main pieces & structure | The app's components and how they're organized |
| Data model | The entities in your system and how they relate to each other |
| Non-functional targets | The speed, security, and scale commitments you're building toward |
Five headings, filled honestly, beat fifty pages of prose nobody, including the agent, will actually use. If any section is empty because you haven't thought it through yet, that's useful information too: it tells you exactly what to figure out before you start building, not after.
A minimal filled-in example, for a small internal tool, might read: problem and audience, "our support team needs to see refund requests in one place instead of three inboxes." Scope, "list requests, approve, deny, add a note, nothing else for v1." Main pieces, "a request list, a detail view, an approval action." Data model, "a request belongs to a customer and has a status." Non-functional targets, "internal tool, ten users, no uptime guarantees needed, but customer data must never leave our own database." None of that took more than a few minutes to write, and every sentence closes off a guess your agent would otherwise have to make on its own.
Keep it short, and keep it alive
A spec is not a contract you write once, sign, and freeze. It's a working document you keep tight and update as you learn things the plan didn't anticipate, which is most of them.
| Forty-page document | Living spec |
|---|---|
| Written once, stale within two weeks | Edited whenever scope or data changes |
| Tries to cover every edge case up front | Covers the shape; details emerge while building |
| Nobody rereads it | Short enough to reread before every task |
Aim for something you and your agent can both hold in your head at once. A page or two that stays accurate beats a chapter that impresses nobody and describes a version of the app that no longer exists.
Where the spec lives matters as much as what's in it
Put the spec in the project itself, in the repo, the folder that holds all your code, as a plain markdown file your agent can open every single time. A spec sitting in a chat thread, a Google Doc, or a Notion page somewhere else is one your agent cannot reliably read, and one you'll forget to update because it's not where the work happens.
Keeping it beside the code means every change to scope or data lands in the same place the build happens. The moment the spec and the software live in different homes, they start drifting apart, and a spec that's drifted from reality is worse than no spec: it actively misleads whoever, human or agent, trusts it next.
The mistakes that turn a spec into shelfware
Most specs fail for the same handful of reasons, and all of them are avoidable.
- Writing it once and never touching it again. The first version is always wrong in small ways. If you don't update it, the agent keeps building from an outdated picture, and every future task inherits that drift.
- Trying to cover every edge case up front. You'll spend a week writing prose nobody rereads, and you'll still miss the edge case that actually shows up.
- Keeping it somewhere other than the repo. If the spec isn't in the same place as the code, it isn't in the loop, and it will fall out of date within a sprint.
- Skipping the non-functional targets. Speed, security, and scale are the section people leave blank because it feels premature. It's exactly what an agent needs to know before it picks shortcuts that bite you later.
- Writing the spec after the build instead of before. A spec written to document what you already shipped isn't a spec, it's a changelog. Its value is in shaping the build, not narrating it afterward.
Do this now: create a spec.md file in a specs folder in your repo, and fill in the five section headings above with what you already know: the problem, the scope, the pieces, the data, and the targets. That single file is what turns your next AI coding session from an improvisation into a build.
Frequently Asked Questions
What's the difference between a spec and a PRD?
Nothing meaningful. PRD, product requirements document, is the same idea under a heavier, more corporate name. For vibe coding purposes, use whichever term you like. What matters is that it's short, it's written down, and your agent reads it before building.
How long should a spec be?
A page or two for most small to mid-sized projects. If you can't hold the whole thing in your head, it's too long, and you'll stop rereading it, which defeats the point. Cover the shape of the problem and let the details emerge as you build.
Do I need a spec for a tiny weekend project?
Even a few bullet points under the five headings beats nothing. The smaller the project, the faster this takes, five minutes, not five hours, and it still saves you from an agent inventing scope you didn't ask for.
Should I write the whole spec before writing any code?
Write enough of it to start, especially the problem, audience, and scope. The data model and non-functional targets can sharpen as you go, but they should exist in some form before you lean on an agent to build the pieces that depend on them.
Where exactly should the spec file live?
Inside your project's repo, as a plain markdown file, ideally in a dedicated specs folder. Not in a chat window, not in a separate doc tool. It needs to be somewhere your AI agent can open it every time it starts a task.
The short version, and where the long version lives
A spec is not busywork. It's the one document that keeps your AI agent building the thing you actually meant, instead of the thing it guessed at. This article covers the short version. The full chapter in The Vibecoder's Handbook goes deeper, with the exact templates and prompts to hand your AI agent so it builds from your spec instead of around it.







