labs · ai-assisted programming
Build the same application three times without writing much code, then find out what you actually shipped — and build it once more the other way, so you have felt both sides of the argument rather than just heard it.
Nothing to install — every tool in this lab runs in a browser. You need a free account on each of three prompt-first builders:
Each free plan has a daily limit, so build all three in one sitting. If a limit stops you, use Build mode in Google AI Studio instead, which needs a Google account.
Create a REFLECTION.md in this folder now; you will write into it
throughout.
DIY 2 and DIY 4 use the Copilot chat in your Codespace. Open the chat panel
with Ctrl+Alt+I (Ctrl+Cmd+I on a Mac). Every step that talks to the
assistant names a mode: Plan reads and thinks but changes nothing;
Interactive reads your files and asks before it runs a command or
changes a file. This lab never needs Autopilot. Fresh conversation
means press the + at the top of the chat panel first.
Tool names change. The three used here are examples of a category, not a prescription. If one has changed name, pricing or shut down, pick another prompt-first builder and note which you used. The exercise is about the category.
One brief, three tools. The repetition is the point: it separates what is true of the approach from what is true of one product.
The brief. A to-do application. Add a task, mark it done, delete it, and the list survives a page refresh.
REFLECTION.md. Use the same prompt for all three.What you should have
Three working to-do apps, one shared prompt, and a table in
REFLECTION.md recording time, number of follow-ups, and for each tool
the first mistake, or the first decision it made that your prompt did not.
Using the same prompt for all three is what makes this a comparison rather than three anecdotes. Resist improving the prompt between tools — if you must, record that you did and why.
"Survives a page refresh" is the requirement that separates a demo from an app. Check it explicitly in all three. If one fails, that is your first mistake. If all three pass, look at what each one chose without being asked: what an empty task does, whether the same task can go in twice. The brief says nothing about either, so every tool answered for you.
You now own three applications you did not write. This section is the whole reason the lab exists.
Pick one of the three and spend fifteen minutes in its source.
Open its code view — the Code tab in Lovable, v0 and Google AI
Studio, the <> icon in Bolt.new — and find the file that handles
user input or data storage.
Answer in REFLECTION.md:
Find one line you genuinely cannot explain. Paste it.
Fresh conversation, Plan, in the Copilot chat: paste the line and ask what it does. Did the explanation match what you had assumed?
Fresh conversation, Plan: paste the whole file and ask directly:
Review this code for security vulnerabilities as a security engineer would.
Record what it finds.
What you should have
At least one concrete thing you would not ship, the line you could not explain, and the security review's findings.
Around 45% of AI-generated samples carry a common vulnerability class, so
the base rate is on your side. Unvalidated input is the usual suspect —
look for anything that goes from a form straight into storage: is there a
limit on how long a task can be, or a check for an empty one? In plain
JavaScript, also look for text that goes straight back onto the page
through innerHTML. React escapes text by default, so in a React app that
one is less likely.
Step 4 is the real exercise. The gap between what you assumed a line did and what it does is comprehension debt, measured directly, on code you created an hour ago.
Lovable shows its code read-only on the free plan. Reading is all this step needs.
What you should have
An estimate with reasoning, and an honest comparison against building it by hand.
There is no correct answer and the honest one is often "shorter" — these tools genuinely save time. The exercise is to make the trade visible rather than to conclude it is bad.
If your answer is "I would just ask the tool to add it", that is a legitimate strategy. Note what it depends on: that the tool still understands a codebase it wrote and you did not read.
Now the other side of the argument, so your opinion is based on having done both.
In spec.md, before touching any tool, write one page:
Open spec.md. Fresh conversation, Plan, in the Copilot chat:
Here is spec.md. Give me a plan: which files you will create and what each one does. Do not write code yet.
Read the plan against your spec. Correct it where it drifted, in the same conversation.
Only now switch the mode to Interactive, stay in the same
conversation, and ask it to build the plan in a new folder called
todo-spec next to this README. Allow the changes it asks for.
Check the result against your three acceptance criteria.
What you should have
spec.md, the plan you reviewed and corrected, a working app, and a note
of where the plan drifted from your spec.
Step 3 is the step everyone skips, and skipping it turns spec-driven development into vibe coding with extra paperwork. The plan is the cheapest place to catch a misunderstanding — cheaper than the code and far cheaper than the deployed app.
If your spec has no "does not do" section, it is not finished. Bounding the work is most of the value.
Record in REFLECTION.md:
## Vibe vs spec-driven
Time, vibe coding: ......... [minutes]
Time, spec-driven: ......... [minutes]
Which produced code you would defend? ....... [which, and why]
Which for a throwaway prototype? ............ [which]
Which for something assessed and demonstrated? [which]
Where did writing the spec change what you built? [be specific]
What you should have
A completed comparison with a stated preference and a reason that is not "it is the responsible choice".
Spec-driven being slower is not a criticism — it is the cost, and the question is what the cost buys. If it bought nothing on a to-do app, say so. That is a real finding, and it is the argument for vibe coding on small disposable work.
The last line is the one worth thinking about: what did writing it down change about what you built? Usually something.
Complete this table in REFLECTION.md with your own examples:
| Task | Mode I'd choose | Why |
|---|---|---|
| A weekend prototype | ||
| A feature in assessed work | ||
| Something a stranger maintains | ||
| Code handling other people's data |
Add one row for a task you would give no assistant.
Write two sentences on what would have to change for you to move a task from one mode to the other.
What you should have
A completed table with concrete tasks, including one you would not delegate, and a stated condition for switching modes.
Useful axes for the last question: how reversible is it, how well can you test it, how long will it live, and who pays if it is wrong.
If every row says the same mode, you have not found your boundary. Push until you do — the boundary is the actual output of this lab.