Part 2 — Building · 22 min read
Idea to MVP
Spec-driven building: how to slice a product into pieces an AI can finish without wandering.
You can now build a page, prompt properly, and keep your project safe. This page is about the thing that actually decides whether you finish: cutting a product idea into pieces small enough that an AI can complete each one, and you can verify each one.
The failure mode here isn't technical. It's that founders try to build the whole thing at once, end up with forty half-working features, and can't tell which parts are real.
What an MVP actually is
Not "a smaller version of my product". It's the smallest thing that proves or disproves your riskiest assumption. Those are very different, and the difference is usually three weeks of work.
If your assumption is "dog walkers will pay to stop managing bookings over WhatsApp", the MVP needs: a walker can add a booking, see their day, and a client can request one. It does not need: invoicing, recurring bookings, multi-walker teams, a client app, notifications, or a settings page.
Slicing vertically, not horizontally
The instinct is to build in layers: all the database first, then all the pages, then wire it together. Don't. You'll work for two weeks with nothing you can look at, and find out at the end that your schema was wrong.
Build in vertical slices instead — one complete user action all the way through the stack, working end to end, before starting the next.
| Horizontal (avoid) | Vertical (do this) |
|---|---|
| Week 1: all database tables | Day 1: user can sign up and see an empty dashboard |
| Week 2: all API routes | Day 2: user can add one booking and see it in the list |
| Week 3: all pages | Day 3: user can edit and delete a booking |
| Week 4: connect it up, discover everything's wrong | Day 4: bookings show on a calendar view |
Every slice ends with something you can click. That means every slice ends with something you can verify, and something you can commit.
The build loop
- Write a small spec for the slice. A dozen lines in
docs/. What the user does, what they see, what the rules are, what "done" means. - Plan mode. Have the AI propose an approach. Read it. Argue with the bits that look wrong.
- Build one piece. Not the whole slice — one piece of it.
- Verify in the browser. Click it yourself. Try to break it.
- Commit.
- Next piece. When the slice is done,
/clearand start the next one clean.
A worked example
Say the riskiest assumption is that dog walkers will log bookings at all. Here's the whole MVP, sliced:
| # | Slice | Done when |
|---|---|---|
| 1 | Project set up, deployed, custom domain, one page live | A stranger can load your URL on their phone |
| 2 | Sign up, log in, log out | You can make an account, close the browser, come back and still be logged in |
| 3 | Add a booking (client name, dog, date, time, duration) | You add one, refresh, and it's still there |
| 4 | See today's bookings on the dashboard, in time order | Three bookings appear in the right order; empty state reads sensibly |
| 5 | Edit and delete a booking | You can fix a typo and remove a cancellation, with a confirm step on delete |
| 6 | Week view | You can see the week and click through to a day |
| 7 | Polish: mobile layout, loading states, error states, empty states | It works one-handed on a phone in the rain |
Seven slices. Each one is an evening or two. Each one ends with something real. And crucially — you could stop after slice 5 and still learn something true about your idea.
The states everybody forgets
AI-generated features usually handle the happy path and nothing else. For every screen, ask about these four, because your users will find all of them:
- Empty — a brand-new user with no data. This is the first thing every user sees, and it's usually an afterthought. It should explain what to do next.
- Loading — data on the way. Without this, the app looks broken for a second on every action.
- Error — it failed. The user needs to know what happened and what to do, not a raw technical message.
- Too much — a user with 500 bookings, or a name 80 characters long. Does the layout survive?
Knowing when a slice is genuinely finished
Run this list before committing anything user-facing. It takes two minutes and catches most of what would otherwise reach a user:
- Does it work when you do the obvious thing?
- Does it work on a 375px-wide screen?
- What happens if you submit the form empty?
- What happens if you double-click the button?
- What happens if you refresh mid-way?
- Does it look right with no data, and with a lot of data?
- If you log out and back in, is the data still there?
- Can you see anyone else's data? (Try. Genuinely try.)
I'm a non-technical founder building an MVP with AI coding tools. Here's my idea:
[paste your description, your users, and what they need to be able to do]
My riskiest assumption is: [the thing that, if false, means this product shouldn't exist]
Break this into vertical slices, where each slice is one complete user action that works end to end and can be demonstrated.
For each slice give me:
1. A one-line description of what the user can do afterwards
2. What has to be built (roughly, in plain English)
3. An honest estimate in evenings, for someone with my level of experience
4. What "done" means — the specific things I should click to verify it
5. What could go wrong or turn out harder than it looks
Order them so that I'm never blocked, and so that the riskiest assumption gets tested as early as possible. Then tell me which slices I could cut entirely and still run a valid experiment.
I'm about to build this slice: [description]
Before any code, write me a short specification. Ask me questions first where you'd otherwise guess.
The spec should cover:
- The user's goal and what happens immediately before and after
- Every screen or state involved, including empty, loading, error and success
- The rules: what's required, what's valid, what's not allowed
- What data this creates or changes, and what else depends on it
- Who's allowed to do this and what happens if someone who isn't tries
- Numbered acceptance criteria I can check off by clicking
Keep it under one page. Save it to docs/ with a sensible filename. Don't write code — I want to read and approve this first.
This is an adversarial review — start it in a fresh chat, so the AI isn't marking its own homework.
I've just finished building [slice]. Before I move on, act as a QA engineer who's been asked to break it.
Look at the actual code and tell me:
1. Ten specific ways a user could break this, with the exact steps for each.
2. What happens with no data at all, and what happens with an unreasonable amount.
3. What happens with awkward input: apostrophes in names, emoji, very long text, leading spaces, pasted formatting.
4. What happens with bad timing: double-click, slow network, refresh mid-action, two tabs open.
5. Whether one user could see or change another user's data. Be specific about how you checked.
6. Which of these actually matter before I put this in front of ten beta users, and which can wait.
Don't fix anything yet. Give me the list, ordered by how likely I am to get burned.
Audit this project honestly. I've been building with AI assistance and I suspect some things look finished but aren't.
Find and list:
1. UI elements — buttons, toggles, links, menus — that aren't wired to anything
2. Functions that are defined but never called
3. Placeholder or hardcoded data pretending to be real
4. Error handling that catches problems and silently does nothing
5. "TODO" or "FIXME" comments and what they're hiding
6. Features that work in one place but not in the equivalent place elsewhere
7. Anything that would only work for my test account
For each, tell me whether it's a must-fix, a should-fix, or a fine-for-now. Be blunt — I'd rather find this out from you than from a beta user.
Use the build plan prompt with your real idea. Then cut the plan in half: delete every slice that isn't needed to test your riskiest assumption. Then look at what's left and cut one more.
You'll know it worked when you have four to seven slices, each an evening or two, and the first one is "deployed and live". Put it in docs/plan.md and commit it.
Do the first slice completely: project set up, deployed to Vercel on a real URL, one page live. Nothing else. Resist every temptation to start on features.
You'll know it worked when you can text the URL to a friend and they can load it on their phone. This is a genuinely big milestone — you now have a deployment pipeline, and every future push goes live automatically.
Take any screen you've built that shows data. Deliberately produce all four states: delete all the data (empty), throttle your network in browser dev tools to see loading, break the connection to force an error, and add fifty records (too much).
You'll know it worked when all four look deliberate rather than broken. Most likely at least two of them look terrible right now — which is exactly the point of doing this before a user does.
Set a timer. Attack your own app: submit empty forms, paste emoji into every field, double-click everything, hit the back button at the worst moment, open it in two tabs and change the same thing in both. Write down everything that breaks.
You'll know it worked when you have a list of at least eight real problems. Fix the top three. Put the rest in GitHub Issues — and notice how differently you now think about "done".