How to Vibecode
AGENTS · WORKFLOW · SHIPPING
This is for reasonably technical people who aren’t software engineers. “Vibecoding” here means you describe what you want in plain English, an AI agent writes the code, and you stay the person who decides whether it’s any good. It is not no code. You’ll read some. You just won’t type much of it.
The hard part isn’t getting something that kind of works. Getting to “kind of works” is an afternoon now, and it feels like magic. The hard part is week two: changing one thing without breaking the thing that already worked, knowing what state anything is in, getting back to safety when it all goes sideways, and putting it somewhere another human being can actually use it. None of that is a coding problem. It’s a workflow problem, and workflow is what this page is about.
The whole bill is one subscription, about $20 a month. GitHub is free, Cloudflare is free, the rest is free. By the end you’ll have something live on the internet at a URL you can text to someone. This is my setup, not the setup — I arrived at it by doing it wrong first, and it’s roughly the smallest amount of real development practice that pays for itself. Take the parts that help and throw out the rest.
The Shape of the Thing
The Loop
Before you install anything, know what loop you’re being taught. Everything in this guide is machinery wrapped around five steps:
- You describe what you want, in English.
- The agent edits the files.
- You run it and look at it with your own eyes.
- When it works, you save a checkpoint you can come back to.
- You push, and it’s live on the internet.
That’s it. Steps 1 and 2 are the part everyone talks about and the part that’s already solved. Steps 3, 4, and 5 are where projects die, and they’re where most of this page lives.
What you actually need
Four things, one of which costs money.
| Thing | What it’s for | Cost |
|---|---|---|
| A terminal | Where you talk to the agent. Already on your computer. | Free |
| Claude Code | The agent. Reads and edits the files in a folder, runs commands. | ~$20/mo (Pro) |
| GitHub | Save history for your project, and the trigger that deploys it. | Free |
| Cloudflare | Where the thing lives so other people can open it. | Free |
What I’m not going to explain
No computer science. No explanation of what a compiler is, what React is, or how HTTP works. You can be productive for a long time without any of it, and when you do need a piece, you can ask the agent for it right when it matters, which is when it’ll actually stick.
One rule I’m holding myself to on this page: every command shown here is one you type, and every file shown is one you own. I never show you code the agent writes. That code changes with every framework version, and copy-pasting it is how you end up with something you can’t maintain. The commands and the workflow files below have been stable for years.
Setup
Claude Code
This is the one thing you pay for. A Claude Pro subscription (about $20/month) includes Claude Code, which is the agent that runs in your terminal. Sign up at claude.com.
Here’s the single thing beginners misunderstand, so
I’ll be blunt about it: Claude Code works on a
folder. You cd into a directory, you
type claude, and from that moment it can read
and edit every file in there. It is not a chat window you
copy answers out of. It is a coworker sitting at your
computer with your project open. That’s why the rest of
this page is about keeping that folder recoverable.
Install it
npm install -g @anthropic-ai/claude-code
cd ~/Projects/my-first-thing
claude
That needs Node.js installed first. If the install command has moved since I wrote this, the official docs win — and honestly, asking Claude in a browser “how do I install Claude Code on a Mac” is a perfectly good first move.
How to talk to it
You’ll get better results faster if you do these four things from day one:
- Say what “done” looks like. Not “make the table better” but “the table should sort when I click a column header, and stay sorted when I add a row.” The agent is good at building to a spec and bad at guessing your taste.
- One change at a time. A request with four unrelated parts gives you one big pile of edits you can’t evaluate. Four small requests give you four things you can check off.
- When you’re unsure, ask before you edit. “Explain how this currently works and what you’d change, but don’t change anything yet” is a great habit. Read the answer. Then say go.
- Tell it to actually run the thing. The agent can start your app, open it, and check the result. Ask it to. “It should work now” is not the same sentence as “I ran it and here’s what happened.”
GitHub
Git is two things at once, and it’s easier if you take them one at a time. It’s a save history for a folder — every version you ever checkpointed, kept forever, with the ability to go back. And it’s the trigger that puts your work on the internet — you’ll wire it up so that saving to GitHub updates your live site automatically.
Make a free account at github.com, then install GitHub’s command-line tool and log in. It’ll walk you through it with a series of questions; the defaults are fine.
brew install gh # Mac, via Homebrew
gh auth login
We are not learning git yet. You need the account and you need to be logged in, and that’s all for now — the actual workflow comes after your first app is live, when it’ll mean something. If you learn branches and commits before you have anything worth protecting, none of it sticks.
Cloudflare
Make a free account at cloudflare.com. The free tier is genuinely generous — every project on this site runs on it and I’ve never paid for hosting.
You’ll meet two products. Pages hosts plain files: HTML, images, that sort of thing. Point it at a GitHub repository and it publishes what’s in there. Workers runs actual code on their servers, which is what you need once your app has to remember things between visits. Your first app uses Pages. Your third uses Workers.
I’m deliberately not giving you click-by-click instructions for the Cloudflare dashboard anywhere on this page. Those screens get redesigned every few months, and a stale set of directions is worse than none. I’ll tell you what you’re looking for and what it’s called, and you’ll find it — or you’ll paste what you see into Claude and ask which button to press.
Your First App
App 1 · A Page on the Internet
What you’re building
A single web page. A personal homepage, a list of links, a page about your dog. No framework, no build step, no database — one HTML file that a browser opens. Pick something you genuinely want to exist, because the point is that you’ll come back and change it. This site you’re reading right now is exactly this: a folder of HTML files with no build step, and it takes about ten seconds to go from edit to live.
How to do it
Make a folder, make a repository, and start the agent in it.
gh repo create will ask you a few questions
— make it private for now, you can always flip it later.
Then just ask. “Make me a single-page personal site
with my name, a short bio, and links to my GitHub and email.
Plain HTML and CSS, no frameworks. Put it in a folder called
public.” Read what it produces —
genuinely read it, HTML is about as approachable as code
gets — and then look at it in a browser:
cd public
python3 -m http.server 8000
# then open http://localhost:8000
That command is a tiny web server built into your computer. It’s the same one I use to preview this site. Leave it running in one terminal window, edit in another, hit refresh.
When you like it, save it and send it to GitHub:
git add public/index.html
git commit -m "Add the first version of my personal site"
git push
Now go to Cloudflare and connect it. In the dashboard, find
Workers & Pages and create a new Pages project connected
to your GitHub repository. It’ll ask for a
build command — leave it blank, you don’t
have one — and a build output directory, which
is public, the folder your HTML is in. A minute
later you have a real URL.
What this teaches
- A website is just files. The demystification alone is worth the hour.
- The whole deploy loop: edit, commit, push, live. You will use this exact loop forever.
- Local preview. You can always look at it before the world does.
- Your first URL took an afternoon, not a semester.
Why This Is the Whole Game
Stop and appreciate what you have, because it’s more than it looks like. You can change something, see it locally, and have it live for anyone in the world a minute later. Every project in the rest of this guide is that same loop with more machinery in the middle. Not a different loop — the same one.
And this works flawlessly right up until the first time you ask for one more small thing and the agent breaks something that used to work. Which it will. That moment is what the next section exists for.
The Workflow
Branches, Commits, and Pull Requests
Three words that sound like jargon and are actually three very simple ideas.
A branch is a copy of your project you can throw away. You make one, you let the agent tear around in it, and if the result is garbage you delete the branch and it’s like it never happened. Your working version was never in danger. A commit is a save point with a note attached — a moment in time you can return to, and the unit of “this worked.” A pull request is a page on GitHub that shows you every single line that changed, before those changes become part of the real project. That review page is the whole point. It is the difference between an agent that helps you and an agent that quietly redecorates your house.
Here is the loop, and it’s the most important thing on this page:
git checkout -b feature/add-sorting # a copy you can throw away
# ...work with the agent until it actually works...
git add public/index.html public/app.js # only what you changed
git commit -m "Sort the table when a column header is clicked"
git push -u origin feature/add-sorting
gh pr create # opens the review page
gh pr merge # after you have read it
That’s six commands and it will carry you for years. The agent will happily run all of them for you — but do it by hand a few times first, because the muscle memory is what saves you at 11pm when something has gone wrong.
Branch names
Two prefixes cover everything:
feature/short-description for new things and
fix/short-description for repairs. Lowercase,
dashes between words. This matters less than any other rule
here; just be consistent enough that a list of branches
tells you what you were doing.
Commit messages
A plain sentence, in the imperative, saying what changed: “Sort the table when a column header is clicked.” Not “updates” and not “fixed stuff.” The agent will write these for you and it’s good at it — your job is to read the message and check that it matches what you think happened. When it doesn’t, that’s useful information.
Pull requests
Write a paragraph, not just a title. What did you change, and why did it need changing? Have the agent draft it and then edit it. This feels like busywork on a project with one person, and then six weeks later you’re staring at a change you don’t remember making and the paragraph is the only thing that saves you. You’re writing to yourself.
Stage Only What You Changed
You’ll see git add -A and
git add . everywhere on the internet. They mean
“include everything.” Don’t use them. Name
the files, like the example above does. It takes four extra
seconds and it forces you to know what’s in your
change.
Because here’s what actually happens: you ask for a
button and the agent also reorganizes three other files it
decided were untidy. If you typed git add -A,
all of that is now in your commit and you don’t know it.
If you named your files, you see the strays sitting there in
git status. Files you didn’t ask
for are the finding, not the nuisance. Go look at
what it did.
What Not to Commit
A .gitignore file at the top of your project
lists things git should pretend it can’t see.
Everyone’s looks about the same:
node_modules/
dist/
.wrangler/
.dev.vars
*.local
.DS_Store
Those are build output, downloaded libraries, and machine junk — enormous, regenerable, and pointless to keep. The agent will write this file for you; you just need to know it exists and what it’s for.
The part worth doing yourself: if you’re going
to test with real data, add it to .gitignore by
name before the file exists. A folder called
real_data/, a bank export, a spreadsheet with
your actual finances in it. Do it in advance, because the
moment you accidentally commit and push that file, it’s
in the history and getting it out is genuinely difficult.
Passwords and API keys get their own section further down.
Getting Back to Safety
This chapter is the reason for every chapter above it. It is 2am, the agent has been enthusiastic, and nothing works. Four commands:
git status # what changed?
git diff # show me the actual lines
git restore path/to/file # undo my changes to this file
git checkout main # abandon this branch entirely
git restore throws away edits to one file and
puts it back the way it was at your last commit.
git checkout main walks away from the whole
branch and returns you to the last version you merged. Both
of them only work because you committed when things were
good. That’s the actual lesson: commit the
moment something works, before you ask for the next
thing. A save point costs you fifteen seconds and
the absence of one costs you an evening.
The Gate
Before you open a pull request, one check has to pass. On App
1 the gate is “did I open it in a browser and look at
it.” On a bigger project it becomes a command —
on mine it’s npm run check, which
type-checks the code and runs the tests, and I don’t
open a PR until it’s green.
The principle matters more than the command. You need one yes-or-no answer that you trust, and it has to involve actually running the thing. A type-check passing means the code is shaped correctly, not that it does what you wanted. That distinction has bitten me more than once: everything green, everything broken. Open the app. Click the button. Look at the number.
Telling the Agent How You Work
CLAUDE.md
Every conversation with the agent starts from nothing. It
doesn’t remember yesterday’s session, the
decision you made last week, or the reason that one file is
weird. A CLAUDE.md file at the top of your
project is the fix — it gets read automatically at the
start of every session. It’s memory that survives the
conversation ending.
Mine are short. Three headings:
# CLAUDE.md
## What this is
A calculator that replaces my mortgage spreadsheet.
## Commands
npm run dev # start it locally at localhost:5173
npm run check # types + tests; must pass before a PR
## Things that aren't obvious
- The math lives in src/logic.ts and has no interface code in it.
Tests check it against my original spreadsheet numbers. Keep it that way.
- Rates are stored as decimals (0.065), not percentages.
What belongs in it
- What the project is, in one sentence.
- The exact commands to run it and check it.
- The handful of non-obvious decisions that would cost an hour to rediscover — and, ideally, why. “Don’t do X” gets ignored eventually. “Don’t do X because it broke Y” sticks.
- How to verify a change actually worked. If checking your app means starting it and clicking three specific things, write those three things down and the agent will do them.
What doesn’t
- Anything that changes every week — it’ll go stale and start actively misleading.
- Anything the agent could learn by reading one file. It can read the files.
- A list of everything you’ve ever done. That’s the next section.
A Note File for Future You
Separate from that, I keep a STATE.md in every
project — a scratchpad of where things stand, rewritten
whenever I stop working. Four things:
- Status: am I actively on this, or is it parked?
- What I just finished.
- What’s next — concrete enough to start on without thinking.
- What’s broken or half-done, so it doesn’t ambush me.
This is optional and it is very cheap. Twenty seconds when you stop; twenty minutes saved when you come back in three weeks with no idea what you were doing. Ask the agent to update it at the end of a session and you won’t even write it yourself.
A Real App
App 2 · Replace a Spreadsheet
What you’re building
A calculator that runs in a browser. There’s a build step now and the code is a real language, but still no server and no database — it saves in the browser.
Build a spreadsheet you already own and quietly resent:
- A loan payoff or refinance comparison.
- Unit conversion for a hobby — baking, brewing, woodworking, film stock.
- Splitting costs on a group trip.
- A training plan or a fertilizer schedule generator.
How to do it
Start a project from Cloudflare’s template and pick a React app with TypeScript when it asks:
npm create cloudflare@latest my-calculator
It’ll ask a handful of questions, and the exact wording changes over time, so I won’t transcribe them — you want a React app, TypeScript, and yes to deploying. Then hand the whole thing to the agent and describe your spreadsheet: the inputs, the outputs, the rules.
Here’s the one instruction that makes this project
worth doing. Tell it to put the actual math in one
plain file with no interface code in it —
something like src/logic.ts — and to write
tests for that file using real numbers out of your
spreadsheet. You already know what the answers should be.
That’s a genuinely valuable thing to have, and most
people building software don’t.
Your spreadsheet is the test. Ten rows of known-correct inputs and outputs, turned into ten tests, and now every future change is checked against them automatically. That separation — math in one file, buttons in another — is the single most useful structural habit I have, because the math is the part that has to be right and the interface is the part you’ll change forty times.
What this teaches
- A gate that means something.
npm run checknow runs your tests, and it can tell you that you broke the math. - Separating logic from interface, and why anyone bothers.
- Scope creep. A calculator invites endless features and the agent will cheerfully build all of them. This is where you learn to say “good idea, not in this pull request.”
These are the five commands you’ll actually type from here on:
| Command | When | What happens |
|---|---|---|
npm run dev |
While working | Runs the app on your machine, updating as you edit. |
npm run check |
Before every PR | Type-checks and runs the tests. The gate. |
npm run db:migrate:local |
After a database change | Updates the database on your machine (App 3). |
npm run db:migrate:remote |
Before deploying that change | Updates the real database (App 3). |
| Merge the pull request | When it’s ready | This is the deploy. Cloudflare rebuilds and ships it. |
App 3 · Something That Remembers
What you’re building
Something with a database, so it still knows things when you come back tomorrow, on a different device. A home maintenance schedule. A log of things you’ve lent people. A reading list. Books, workouts, plant waterings, whatever. Single user — just you.
The parts
- The page — what runs in the browser. Same as App 2.
- The server — a small program on Cloudflare’s machines that the page talks to.
- The database — where the data actually sits. Cloudflare’s is called D1 and the free tier is plenty.
- Migrations — numbered files describing each change to the database’s shape, applied in order. Once real data exists, these are permanent history. Have the agent write a comment at the top of each one saying why.
The template sets all the plumbing up. There’s a config file with some settings in it that you will not need to understand on day one, and that’s genuinely fine.
Local vs. live
This is the thing that confuses everyone, so brace for it: you now have two databases. One on your laptop for development, one on Cloudflare’s servers for real. They are completely separate. That’s why there are two migrate commands in the table above — a schema change has to be applied to each.
So when you deploy for the first time and your live app is empty while your local one is full of test data: that’s not a bug. That’s the system working. Your test junk stayed on your laptop, which is exactly what you want.
Putting a lock on it
An app with your data in it shouldn’t be open to the world. Cloudflare Access solves this for free: it puts a login in front of your app and only lets your email address through. No password handling, no user accounts, no security code you have to get right.
The ordering is not obvious and getting it wrong costs you a confusing hour. Deploy first — that’s how you learn the address Cloudflare gave you. Then create an Access application for that address, with a policy allowing only your email. It gives you back two values, a team domain and an AUD tag; paste those into your project’s config and deploy again. Now the lock is on. Ask the agent to walk you through it — this is a great thing to have it explain step by step while you click.
Merging is deploying
Once the repository is connected to Cloudflare, merging a
pull request into main builds and ships it
automatically. There is no separate deploy step, and I love
this — the review page is the last thing standing
between an idea and production, which is a good place for
your attention to be.
One caveat that’s invisible once you’re used to it: this only happens if you connected the repository to Cloudflare in the first place. If you merge and nothing changes on the live site, you probably haven’t — and you’ll waste an hour looking for a bug in your code that isn’t there.
Secrets
Sooner or later you’ll have an API key. Three kinds of values, three homes:
| Kind of value | Where it lives | In git? |
|---|---|---|
| Settings that aren’t secret | The project config file | Yes |
| Real secrets, in production | wrangler secret put NAME — typed in, stored by Cloudflare |
No |
| Real secrets, on your laptop | A .dev.vars file, listed in .gitignore |
No |
A nice habit: commit an example version of that local file with the names filled in and the values blank. Future you opens the project on a new machine and immediately knows which four secrets are needed.
And the part people get wrong, so I’ll say it loudly: if you commit and push a key, deleting the line does not help. It’s in the history. Bots scan public repositories for exactly this, within minutes. The only real fix is to go to whoever issued the key and revoke it, then generate a new one. Rotate the key. Don’t negotiate with yourself about it.
Then stop climbing for a while. Three apps in and you can build a genuinely useful amount of software. What I’d avoid next is anything holding other people’s logins, payments, or personal data. That’s a different sport with different consequences, and the gap between “works” and “safe to run” gets very wide very fast. Knowing where the ladder ends is part of using it well.
When It Goes Wrong
The Ways This Actually Fails
None of these are exotic. Every one of them has happened to me, most of them more than once.
- The agent confidently breaks working code. The fix isn’t a cleverer prompt. The fix is that you were on a branch and you committed the version that worked. Commit when it works, before you ask for the next thing.
- You never actually ran it. The agent said “done,” the type-check was green, and nobody opened the app. Open the app.
-
The conversation got too long. Long
sessions drift — the agent loses track of a decision
from an hour ago and quietly re-litigates it. Keep a
session to one change, put durable facts in
CLAUDE.mdrather than in the chat, and start fresh after each merge. -
You asked for a button and got a refactor.
Read the diff before you commit; stage only the files you
meant to touch. On a branch that’s a two-minute
cleanup. On
mainit’s your evening. -
A secret went into git. Pasted into a
file, committed, pushed. Prevention is
.gitignoreandwrangler secret put. Cure is rotating the key — there isn’t another one. - It fixed the symptom. An agent will happily wrap a check around an error while the actual cause sits upstream, untouched, waiting. Make it reproduce the failure and tell you what’s causing it before it changes anything.
- You came back after three weeks with no idea where you were. That’s what the note file is for.
- You built for users who don’t exist. Ship for one user — you — and add the rest when somebody actually asks.
What This Doesn’t Get You
An honest list, because the enthusiasm around this stuff tends to skip it. Free tiers have real limits, and the way you hit one is that your app starts failing in a way that looks exactly like a bug in your code — so when something inexplicable starts happening at scale, check the platform’s limits before you go hunting through your own work.
An agent will build what you describe, which means you still have to know what you want, and being clear about that turns out to be most of the job. And whatever ships has your name on it. “The AI wrote it” is not a thing you get to say about your own software — not to your users and not to yourself. That’s the deal, and it’s a fair one.
If You Want to Build an iPhone App
The Same Loop, Different Machinery
I build iOS apps too, and the surprising thing is how little
the workflow changes. Branches, commits, pull requests,
CLAUDE.md, commit-when-it-works, read-the-diff
— all identical. What swaps out is the machinery around
them:
- Xcode and the simulator replace the dev server. Instead of refreshing a browser tab you press Run and a fake iPhone appears on your screen.
-
A config file replaces
.dev.varsfor secrets — different name, same idea, same.gitignorediscipline, same “commit the example, not the real one.” - Merging is no longer deploying. Releases go through TestFlight and then a human review queue at Apple that takes a day or two. Shipping becomes an event you plan rather than a reflex, which changes the rhythm of the work more than anything else on this list.
- The App Store demands a support URL and a privacy policy URL before it’ll take your app — which is an excellent reason to already own App 1. Two more HTML files on the site you built in an afternoon, and you’ve satisfied Apple.
One honest note: this is where the “free” promise breaks. Building and running on the simulator costs nothing, but putting an app on the App Store requires the Apple Developer Program at $99 a year. Worth knowing before you get attached.
Start Here
Your First Afternoon
Concretely, the next five things:
- Subscribe to Claude Pro and install Claude Code.
- Make a GitHub account and run
gh auth login. - Make a free Cloudflare account. Don’t click anything yet.
- Build App 1 — one page, about something you care about — and get it live.
- Then come back and read The Workflow again. It’ll mean something different once you have a thing to lose.
That’s the whole guide. It’s the setup I actually use, arrived at by doing it wrong first — not a best practice handed down from anywhere. If some part of it feels like ceremony that isn’t earning its keep on your project, drop it. The only two I’d genuinely fight you over are commit when it works and read the diff before you merge. Everything else on this page is in service of those two.