Full Stack Vibe Coding for Dummies
*A plain-language guide to building a complete working app by talking to an AI, without pretending you're a software engineer.*
---
Part 1: What we're actually talking about
Vibe coding
The term comes from Andrej Karpathy, an AI researcher, who used it in early 2025 to describe a way of working where you describe what you want in ordinary English, an AI writes the code, and you mostly don't read the code. You look at the result, say "the button is too small" or "it broke," and go again.
That's it. That's the whole idea. You are steering, not typing.
The important word in that description is *mostly*. Vibe coding in its pure form means accepting code you don't understand. That is fine for a weekend toy. It is dangerous the moment real people, real money, or real personal data are involved. This guide assumes you want to end up somewhere between the two: fast and loose while you're figuring out what you're building, careful in the specific places where carelessness costs you.
Full stack
"Stack" is just the pile of software layers that make up an app. "Full stack" means all of them, front to back.
Here is the whole thing as a restaurant:
| Layer | Restaurant equivalent | What it actually is |
|---|---|---|
| **Frontend** | The dining room | What the user sees and clicks. Runs inside their web browser or phone. |
| **Backend** | The kitchen | Code running on a computer you rent. Applies the rules, holds the secrets, does the work customers never see. |
| **Database** | The walk-in fridge and pantry | Where information is stored so it's still there tomorrow. Users, orders, posts, settings. |
| **Auth** | The host at the door | Short for authentication and authorisation. Who are you, and what are you allowed to touch? |
| **Hosting / deployment** | The building and the lease | The service that runs all of the above on the public internet and gives you a web address. |
A "full stack app" is one that has all five. A landing page has only the first. A to-do list that forgets everything when you close the tab has only the first. The moment you want people to log in and have their stuff still be there next week, you need the whole restaurant.
What you can realistically build this way
Very achievable: internal tools, dashboards, booking forms, directories, calculators, simple marketplaces, content sites, prototypes to show an investor or a boss, personal apps for you and twelve friends.
Achievable with real care: a small paid product with a few hundred users.
Not realistically achievable by vibes alone: anything handling medical records, anything where a bug loses someone's money, anything that needs to survive a determined attacker, anything at large scale.
---
Part 2: The eight words you need before you start
Do not skip this. Almost every disaster in this guide happens to people who didn't know one of these eight things.
**API.** A way for one piece of software to ask another piece of software for something. When your app "calls the Stripe API," it's sending a message to Stripe saying "charge this card" and getting an answer back.
**API key.** A password that proves your app is allowed to make those calls. It usually looks like a long string of random characters. Anyone who has it can spend your money. Treat it exactly like a credit card number.
**Client vs server.** Client means code running on the user's device. Server means code running on your rented computer. **Anything on the client can be read by anyone.** There is no such thing as hiding a secret in the frontend. This single sentence prevents most of the expensive mistakes in Part 6.
**Environment variable.** A setting stored outside your code, usually in a hidden file called `.env` or in your hosting provider's settings panel. This is where API keys are supposed to live, so they never end up in the code itself.
**Repository (repo).** The folder holding your project's code, tracked by a tool called Git. GitHub is the popular website for storing repos. Repos can be public or private. A public repo containing a `.env` file is a very bad day.
**Commit.** A saved checkpoint of your code. Git keeps every commit forever, which means you can always go back. This is your undo button and your safety net.
**Dependency (or package).** Someone else's code that your app uses so you don't have to write it yourself. A typical app has hundreds. Every one is a small act of trust.
**Deploy.** Pushing your code out to the live internet so other people can use it.
---
Part 3: Picking your tools
The tools split into two families. Pick based on who you are, not on which one is trendiest.
Family one: the browser builders
You type in a chat box on a website and watch an app appear in a preview pane next to it. Lovable, Bolt, Replit, and a growing crowd of others work like this. Many now include a built-in database, login system, and hosting, so you never touch a terminal.
**Good for:** people who have never installed a code editor, ideas you want on screen within the hour, showing something to someone tomorrow.
**The catch:** you're inside their walls. When you outgrow the tool or it does something strange, getting out and understanding what you have can be painful. And the convenience of "it handles the database for you" is exactly where several of the well-known security failures came from.
Family two: the agents
These work on real files on your own computer. Cursor and Windsurf are code editors with an AI agent built in. Claude Code and Codex are agents you run from the terminal or an app, which read your whole project, make changes across many files, and can run commands. (Anthropic's docs for Claude Code are at docs.claude.com/en/docs/claude-code/overview.)
**Good for:** anything you intend to keep, anything with more than a handful of screens, anyone willing to spend one afternoon learning the basics of a terminal and Git.
**The catch:** a slightly steeper first day. You will see a terminal. It's fine.
The honest recommendation
Start in family one if the words "terminal" and "repository" make you tense. Move to family two the moment your project is something you actually care about. Plenty of people prototype in a browser builder, export the code to GitHub, and continue in Cursor or Claude Code. That's a good path.
Pick a boring stack and stick to it
The single biggest quality improvement available to you is telling the AI what to build with, every time, instead of letting it pick fresh technologies at random. Mixing three approaches in one project is how projects die.
A default that works, is widely documented, and that every AI model knows well:
- **Frontend:** React with Next.js
- **Database, auth and file storage:** Supabase (this is Postgres, a serious database, wrapped in a friendly interface)
- **Hosting:** Vercel
- **Payments:** Stripe
- **Code storage:** GitHub, private repo
You don't need to understand these deeply. You need to name them consistently.
---
Part 4: The build
Step 0: Write the paragraph
Before you open any tool, write one paragraph in plain English:
> *What it is. Who uses it. The three things they can do. What gets stored.*
Example: "A booking page for a small dental clinic. Patients pick a doctor, see available slots, and book one. Staff log in to see the day's list and cancel bookings. It stores patients' names, phone numbers, and appointments."
This paragraph is the most valuable thing you will produce all day. Every AI tool gets dramatically better output when it knows the destination. Keep it in a file at the top of your project. In Cursor that's a rules file; with Claude Code it's a `CLAUDE.md`. Add your stack choices and any rules ("never put secrets in frontend code," "always use Supabase Row Level Security") to the same file. The AI reads it every session so you don't have to repeat yourself.
Step 1: Ask for a plan, not for code
Paste your paragraph and say: *"Before writing any code, give me a plan. What screens does this need, what tables go in the database, and what's the order to build them in? Ask me anything that's unclear."*
Read the plan. Argue with it. A bad plan turns into a thousand lines of bad code in about ninety seconds, and it is far cheaper to fix in the plan.
Step 2: Get something ugly on screen
Build the shell first. One page, a title, a fake list of items typed in by hand. No database, no login. Confirm you can see it in a browser and change the title. You have now proven the whole pipeline works, which means every problem after this is a small problem.
Step 3: Set up Git before you have anything to lose
Make a private GitHub repo. Commit. Then commit after every single change that works. Ask your tool to do it: *"Commit this with a clear message."*
Why this matters so much: when the AI wrecks your project in twenty minutes of confident thrashing, the fix is not a heroic debugging session. The fix is going back to the last commit that worked and describing what you want differently.
Step 4: The database
Say what you're storing, in nouns. *"I need tables for patients, doctors, and appointments. A patient has a name and phone. An appointment belongs to one patient and one doctor and has a time."*
Then, before you go one step further, read Part 6 on Row Level Security. This is the layer where the worst public failures happened.
Step 5: Logins
Don't build login yourself and don't let the AI build it from scratch. Use the ready-made one that comes with Supabase, or Clerk, or Auth0. Password handling, password resets, session expiry, and email verification are a swamp full of subtle mistakes, and these services have already crossed it.
Step 6: Deploy on day one, not on launch day
Push it live while it's still ugly and empty. Deployment breaks in its own special ways, and you want to discover those on a day when nothing is at stake. After that, every change goes live in a minute and you're never facing a scary launch.
Step 7: One feature at a time, forever
The rhythm is: describe one small thing, look at it, commit, next thing.
The failure mode is describing five things at once, getting a wall of changes, finding that two of them broke something, and having no idea which. Resist. Small steps are faster overall even though each one feels slower.
Prompting patterns that measurably help
- **Give context, not just commands.** "The booking form should reject times in the past" beats "fix the date thing."
- **Paste errors whole.** The entire red text, not your summary of it. The details you'd trim are the useful ones.
- **Say what you expected and what happened.** "I clicked Book and expected a confirmation, but nothing happened and the page went blank."
- **Ask for the smallest change.** "What's the smallest change that fixes this without touching anything else?"
- **Ask before you accept.** "Explain what this code does as if I've never programmed. What could go wrong with it?"
- **Ask it to critique itself.** "Review what you just wrote. What's the weakest part?" This works surprisingly well.
---
Part 5: When it breaks
It will break. Not because the tool is bad, but because software breaks, and this is now your software.
**The doom loop.** You report an error, it changes something, a new error appears, you report that, it changes something back, the original error returns. You can burn an entire evening here.
How to break out:
1. **Stop after three failed attempts.** The fourth won't work either. The model is now confused about its own earlier changes.
2. **Revert to your last good commit.** Yes, throwing away an hour's work. It's faster.
3. **Start a fresh conversation.** Long, tangled chats degrade. A clean one with a clean description of the problem often solves it immediately.
4. **Ask for diagnosis, not repair.** "Don't fix anything. Explain what's actually happening and give me three possible causes."
5. **Ask for logging.** "Add print statements so I can see what value this has when it fails." Then paste what you see.
6. **Ask a different model.** They fail differently. A second opinion is one paste away.
**A note on being lied to.** These tools are confident when they're wrong. "I've fixed the issue" sometimes means "I've changed something." Always check the actual behaviour in the browser yourself. Trust the app, not the summary.
---
Part 6: The stuff that will genuinely hurt you
This is the part where "for dummies" stops being cute. AI-generated code is fast, and it is careless in predictable ways. A scan by security firm Escape.tech of 5,600 apps built with these tools turned up over 2,000 vulnerabilities, more than 400 exposed secrets, and 175 cases of exposed personal data. These are not hypotheticals.
1. Secrets in the frontend
**The mistake:** the API key ends up in code that runs in the user's browser, where anyone can read it by pressing F12. Or a `.env` file gets committed to a public GitHub repo. Bots scan GitHub for exactly this, continuously.
**What it costs:** someone else spending against your account. Bills in the thousands arrive quickly.
**What to do:** keys live in environment variables on the server only. `.env` goes in `.gitignore`. The frontend never calls a paid third-party service directly; it calls *your* backend, and your backend calls the service. Turn on GitHub's secret scanning. If a key is ever exposed even for a minute, rotate it. Git remembers deleted files, so deleting it is not enough.
2. Row Level Security
This is the one that has caused the most public damage, so read it twice.
Modern backend services let your frontend talk to the database more or less directly. That's convenient and it's fine, *but only if the database itself enforces who can see what*. Row Level Security (RLS) is that enforcement: a rule on each table saying "a user can only read rows where the user ID matches their own."
**If RLS is off, every user can read every row.** Not just their own bookings. Everyone's. A social app called Moltbook exposed around 1.5 million API keys this exact way.
The AI will often not turn it on unless you insist. So insist: *"Enable Row Level Security on every table and write policies so users can only access their own rows. Then show me how to verify it's working."*
Then verify it. Log in as a second test user and try to read the first user's data.
3. Access control that only exists in the interface
**The mistake:** the AI hides the "Delete" button from non-admins and calls it done. But the underlying request still works if someone sends it directly. Hiding a button is decoration, not security.
This isn't a hypothetical either: a documented flaw in apps built with Lovable inverted access control logic across roughly 170 live applications, blocking legitimate users while letting others through.
**What to do:** ask explicitly, "is this permission checked on the server, or only hidden in the UI?" The check must live where the user can't reach it.
4. Packages that don't exist
AI models invent library names with total confidence. A study presented at USENIX Security in 2025 examined 2.23 million generated code samples and found nearly one in five referenced a package that doesn't exist, with 43% of the invented names showing up again on repeat runs.
Attackers noticed. They register the commonly hallucinated names and put malicious code in them, a practice now called **slopsquatting**. Your AI suggests it, you install it, and you've handed a stranger access to your machine.
**What to do:** before installing anything unfamiliar, search for the package name. Check it exists on npm or PyPI, check when it was published, check that it has real downloads and a real repository. A package created three weeks ago with forty downloads is a red flag.
5. No brakes on spending
Every paid service you connect can be called an unlimited number of times. If a key leaks, or your code accidentally loops, the meter runs.
**What to do, today:** set a hard spending cap on every paid API account. Set billing alerts. Add rate limiting on your login page and any expensive operation. Do this before launch, not after the invoice.
6. Agents with too much power
Coding agents can run commands. They can also run the wrong command. Replit's agent famously deleted a production database during an explicit code freeze.
**What to do:** the AI never gets credentials to your live database. Keep a separate development database with fake data. Take backups. When an agent proposes running something destructive, read it before approving.
The pre-launch checklist
Before a single real person uses your app:
- [ ] No API keys anywhere in frontend code
- [ ] `.env` is in `.gitignore`, repo is private
- [ ] Row Level Security enabled on every table, and tested with two accounts
- [ ] Every permission check happens on the server
- [ ] Spending caps and billing alerts on every paid service
- [ ] Rate limiting on login
- [ ] Errors shown to users say "something went wrong," not the full technical trace
- [ ] Every dependency verified as a real, maintained package
- [ ] Database backups turned on
- [ ] Someone else has tried to break it
A useful last step: paste your code into a fresh AI conversation and ask, *"You are a security researcher. Find every way to abuse this application."* A fresh model with an adversarial brief catches things the model that wrote the code will not.
---
Part 7: The literacy that makes you dangerous
You don't need to be able to write code. You do need to be able to tell when you're being handed nonsense. The gap between "can't code at all" and "can't be fooled" is about a week of casual attention.
Learn to:
- **Read an error message.** They're less cryptic than they look. The file name and line number are right there.
- **Use browser dev tools.** F12. The Console tab shows errors. The Network tab shows every request your app makes, including the ones carrying data you thought was hidden.
- **Read a database schema.** Tables, columns, and which table points at which. If you can read yours out loud, you understand your app.
- **Use Git.** Commit, revert, branch. Three commands.
- **Tell client from server.** Look at a piece of code and know where it runs.
- **Read a diff.** The red and green lines showing what changed. Skim every one before accepting.
That last habit is the whole game. Vibe coding without ever glancing at diffs is how people end up with an app they cannot fix, cannot explain, and cannot safely hand to anyone.
---
Part 8: When to stop and get a human
Not as failure. As arithmetic. Get a professional involved when:
- You're handling payments in a way that touches card details directly
- You're storing health, financial, or children's data
- You're subject to any regulation at all
- You have more than a few hundred real users
- You're storing anything you'd hate to see in a news story
- You cannot explain what your app does with a user's password
A good pattern: build it yourself, prove people want it, then pay someone for two days to review it before it matters. Two days of review is cheap. A breach is not.
---
Glossary
**Auth** — Authentication (who are you) and authorisation (what may you do).
**Backend** — Code on your server. Users never see it.
**CORS** — A browser rule about which websites may call your backend. Set too loosely by default in a lot of generated code.
**Commit** — A saved checkpoint in Git.
**Dependency** — Someone else's code your app relies on.
**Deploy** — Put your code on the live internet.
**Diff** — A view of exactly what changed in a file.
**Endpoint** — A single address on your backend that does one job.
**Environment variable** — A setting kept outside your code, where secrets belong.
**Frontend** — What runs in the user's browser. Fully visible to them.
**Git / GitHub** — The system that tracks versions of your code, and the website that stores it.
**Migration** — A recorded change to the database's structure.
**Postgres** — A widely used, reliable database.
**Rate limiting** — Capping how often someone can hit part of your app.
**Repo** — Your project folder, tracked by Git.
**RLS (Row Level Security)** — Database rules controlling which rows each user may see. Turn it on.
**Slopsquatting** — Attackers registering package names that AI models commonly hallucinate.
**Staging** — A private copy of your live app for testing.
**Stack** — The set of technologies your app is built from.
**Token** — A string proving identity or permission. A secret.
---
The short version
1. Write the paragraph describing what you're building.
2. Pick one boring stack and never deviate.
3. Ask for a plan before any code.
4. Commit constantly. Deploy on day one.
5. One small feature at a time.
6. After three failed fixes, revert and start fresh.
7. Keys on the server. Row Level Security on. Permission checks on the server. Spending caps set.
8. Read the diffs, even when you barely understand them.
9. Get a real review before real people arrive.
Everything else is details you can look up.