Skip to content

AI-Assisted Software Development: Coding Agents in Practice · From vibe coding to shipping: capstone · lesson 16 of 17 · 12 min

Vibe coding vs engineering discipline

What "vibe coding" means

In early 2025 Andrej Karpathy popularized the phrase vibe coding: describing what you want, accepting whatever the AI produces without reading the diffs, pasting errors back until it works, and "forgetting that the code even exists". He framed it as fun for throwaway weekend projects. The phrase spread far beyond that framing, and today it describes a spectrum from harmless prototyping to shipping unreviewed code to customers.

The point of this lesson is not to sneer at vibe coding. It is genuinely useful. The point is to know which side of the line you are on, and to cross it deliberately.

Prototype mode versus production mode

| Dimension | Prototype mode (vibe coding is fine) | Production mode (engineering discipline) | |---|---|---| | Purpose | Explore an idea, demo, learn | Serve real users, handle real data | | Lifetime | Days, disposable | Months or years, maintained | | Data | Fake or public | Real, possibly personal or financial | | Review | Optional | Required, with tests | | Security | Isolated, no secrets | Threat-modeled, least privilege | | Who pays for bugs | You, briefly | Customers, your reputation, your on-call rota |

A useful rule: anything that touches real users, real money, real personal data, or credentials is production, no matter how small.

Where vibe coding shines

  • Throwaway prototypes to test an idea with users before investing.
  • Internal one-off scripts with no sensitive access (reformat a CSV, generate test fixtures).
  • Learning a new framework by building something small.
  • UI exploration: trying five layouts in an afternoon.
  • Non-developers building personal tools: a creator's content calendar, a shop owner's price calculator, running locally.

Where it bites

Common failure patterns when vibe-coded apps reach production:

  • Authentication and authorization gaps: pages that check login in the UI but not on the server; database rules left open.
  • Secrets in the front end: API keys shipped to the browser.
  • No input validation: injection, oversized uploads, abuse of paid APIs.
  • No tests: every change risks breaking something else, and nobody knows.
  • Unmaintainable structure: duplicated logic, dead code, inconsistent patterns that no one, including the AI, can reason about later.
  • Cost blow-ups: unbounded API calls from public endpoints.

Crossing the line deliberately: the hardening checklist

When a prototype earns its way to production, harden it before real users arrive:

  1. Read the code. All of it, or have someone who can. If no one can explain it, it is not ready.
  2. Threat model in one page: what data, who can access what, what could an attacker do.
  3. Move secrets server-side; rotate any that were ever exposed.
  4. Enforce authorization on the server for every data access; review database security rules.
  5. Add tests for core flows and for the bugs you already found.
  6. Validate inputs and add rate limits, especially on anything that calls paid APIs.
  7. Add an instruction file and CI so future agent work follows the rules.
  8. Refactor duplicated or dead code with the migration playbook if needed.
  9. Set up logging, monitoring and backups.

Worked example: from weekend demo to paying customers

A fitness creator in Riyadh vibe-coded a booking app for her online classes over a weekend using an AI app builder and a coding agent. Followers loved it; she wanted to take payments. A freelance developer ran the hardening checklist: found the admin page protected only by a hidden link, a payment provider secret key in the browser bundle, and no server-side check that a booking belonged to the logged-in user. Two days of hardening (with an agent doing much of the work under the plan-implement-verify loop) made it safe to launch. The prototype was not wasted; it validated demand cheaply.

Hands-on: a prototype-to-production gate

Add this to your project README or AGENTS.md so the transition is explicit:

## Status: PROTOTYPE  (change to PRODUCTION only when all boxes are checked)
- [ ] Code read and explainable by a named owner: ______
- [ ] One-page threat model in docs/threat-model.md
- [ ] No secrets in client code; exposed secrets rotated
- [ ] Server-side authorization on every data access; DB rules reviewed
- [ ] Tests for core flows run in CI
- [ ] Input validation + rate limits on public and paid-API endpoints
- [ ] AGENTS.md, permission baseline, secret scanning, branch protection
- [ ] Logging, monitoring, backups

Ask your agent to audit against the gate:

Audit this repository against the checklist in README.md "Status" section. For each item,
report pass/fail with file:line evidence. Do not fix anything yet; produce a prioritized plan.

Pitfalls

  • "It's just an MVP" used to justify skipping auth.
  • Assuming the platform handles security. App builders and hosted databases provide tools, not guarantees; you must configure them.
  • Rewriting from scratch by default. Often hardening is faster; decide with evidence.

How to measure success

Every project has an explicit status (prototype or production), and nothing reaches real users without passing the gate.

Video lecture: Vibe coding vs engineering discipline

Lecture coming soon · 14 chapters · about 9 minutes. Read the full transcript below.

  1. Vibe coding vs engineering discipline
  2. Analogy: midnight cooking vs a restaurant
  3. Two modes
  4. The rule
  5. Where it shines
  6. Where it bites
  7. Hardening checklist
  8. Case: Riyadh booking app
  9. Mindset
  10. Example: the market-stall calculator
  11. Scenario: the dashboard that escaped (illustrative)
  12. Deeper: 'signed in' isn't authorization
  13. Watch me do it: the production gate
  14. Recap

Lecture transcript

Vibe coding vs engineering discipline

In early twenty twenty-five, Andrej Karpathy coined a phrase that took over developer culture: vibe coding. You describe what you want, accept whatever the AI produces without reading it, paste errors back until it works, and forget the code even exists. He framed it as fun for throwaway weekend projects. In this lecture you will learn when vibe coding is exactly the right tool, when it becomes dangerous, and how to cross from prototype to production deliberately.

Analogy: midnight cooking vs a restaurant

Here is an analogy. Vibe coding is like cooking for yourself at midnight. You throw things in a pan, taste as you go, and if it is a bit odd, nobody gets hurt. Running a restaurant is different. You follow recipes, you check fridge temperatures, you label allergens, and an inspector can walk in at any time. Both are cooking. Both are valuable. The mistake is serving your midnight experiment to paying customers without switching into restaurant mode first.

Two modes

This is not a lecture that sneers at vibe coding. It is genuinely useful. The skill is knowing which side of the line you are on. Prototype mode is for exploring, demoing and learning, with fake data and a lifetime of days. Production mode is for real users and real data, maintained for months or years, with review, tests and a threat model. The difference is not the size of the app. It is who pays when something breaks.

The rule

Here is the rule to remember. Anything that touches real users, real money, real personal data or credentials is production, no matter how small it looks. A booking form with ten customers is production. A script that reformats a public CSV on your laptop is not.

Where it shines

Where does vibe coding shine? Throwaway prototypes to test an idea with users before investing. One-off internal scripts with no sensitive access. Learning a new framework by building something small. Exploring five UI layouts in an afternoon. And non-developers building personal tools that run locally, like a creator's content calendar or a shop owner's price calculator. In all of these, speed matters more than durability, and mistakes are cheap.

Where it bites

And where does it bite? When vibe-coded apps reach real users, the same failures show up again and again. Login checked in the interface but not on the server. Database rules left open. Secret API keys shipped to the browser. No input validation or rate limits, so a public endpoint can run up a huge bill on a paid API. No tests, so every change breaks something. And tangled, duplicated code that no one, including the AI, can reason about later.

Hardening checklist

So cross the line deliberately, with a hardening checklist. Read the code, or have someone who can. Write a one-page threat model. Move secrets to the server and rotate anything that was ever exposed. Enforce authorization on the server for every data access. Add tests for core flows. Validate inputs and add rate limits. Add an instruction file and CI. Clean up duplication. And set up logging, monitoring and backups.

Case: Riyadh booking app

A story from Riyadh. A fitness creator vibe-coded a booking app for her online classes over a weekend. Followers loved it, and she wanted to take payments. A freelance developer ran the checklist and found three serious problems: the admin page was protected only by a hidden link, a payment secret key sat in the browser bundle, and the server never checked that a booking belonged to the logged-in user. Two days of hardening, much of it done by an agent inside the plan, implement, verify loop, made it safe to launch.

Mindset

Notice what did not happen. Nobody threw the prototype away in disgust. It validated demand cheaply, which is exactly its job. Rewriting from scratch is sometimes right, but often hardening is faster, so decide with evidence. Also beware two excuses. It's just an MVP, used to justify skipping authentication. And the platform handles security. App builders and hosted databases give you tools, not guarantees. You still have to configure them correctly.

Example: the market-stall calculator

A simple example. You vibe-code a price calculator for your market stall in an afternoon. It runs on your laptop, uses no customer data, and helps you quote faster. Perfect: stay in prototype mode. Now your cousin wants to put it online so customers can place orders and pay. The moment it takes orders and payments, it becomes production. Same code, very different obligations: authentication, server-side checks, secret handling, tests and backups. The code did not change. The stakes did.

Scenario: the dashboard that escaped (illustrative)

Now a realistic scenario with illustrative numbers. A startup in Karachi vibe-codes an internal dashboard for its sales team, then quietly shares the link with two big clients. Three months later, a security review finds the dashboard's database rules allow any logged-in user to read every client's records, and an API key for a paid mapping service is visible in the browser, with a bill several times higher than expected. Nobody did anything malicious; the prototype simply crossed the line without a gate. Common mistake: sharing a prototype link with outsiders and calling it a demo.

Deeper: 'signed in' isn't authorization

One level deeper on the Karachi dashboard. The database rules said: allow read if the user is signed in. That sounds safe, until you remember that anyone can sign up. The fix was a rule tying each record to the client organization in the user's verified profile, plus a test that signs in as client A and tries to read client B's records.

Watch me do it: the production gate

Watch me do it. I'm running the prototype-to-production audit on the Riyadh booking app. First, I paste the status gate into the README, with every box unchecked. Then I paste the audit prompt: check each item, report pass or fail with file and line evidence, and do not fix anything yet. The agent reports. Code read and explainable by a named owner: fail, no owner listed, so I add the freelancer's name after we read the code together. Threat model: fail, missing, so we write one page: customer names, phone numbers and payments; attackers could book in someone else's name or reach the admin page. Secrets in client code: fail. The payment provider's secret key is in the front-end bundle, found in the built JavaScript file. We move it to a server function and rotate it immediately, because it was already public. Server-side authorization: fail. The booking cancel endpoint accepts any booking ID. We add an ownership check and a test. Database rules: the admin collection is readable by any logged-in user, so we restrict it. Tests in CI: fail, so we add tests for booking, cancel and payment. Rate limits: we add them to the booking endpoint. Instruction file, secret scanning and branch protection: added. Logging and backups: turned on. Two days later every box is checked, and the status line changes to production.

Recap

Recap. Vibe coding is a great prototype tool and a poor production practice. Anything touching real users, money, personal data or credentials is production. Cross the line deliberately with the hardening checklist. Your next step: add the prototype-to-production status gate from the lesson to one of your projects, and run the audit prompt so your agent reports pass or fail with evidence for each item.

Key takeaways

  • Vibe coding is useful for prototypes, learning and safe one-off tools.
  • Anything touching real users, money, personal data or credentials is production.
  • Common vibe-coded failures: UI-only auth, secrets in the browser, no validation or rate limits, no tests.
  • Cross into production deliberately with a hardening checklist and an explicit status gate.

Try it

Add the prototype-to-production status gate to one project and run the audit prompt, recording pass or fail with evidence per item.