NotVibesCoded
Teardowns

Anatomy of a vibe-coded checkout: 14 bugs in 200 lines

A founder sent us the checkout flow their AI built. 200 lines, looked perfect in the demo. We found 14 bugs — including one that charged customers twice. Here's the full teardown.

Published 3 min read

A founder sent us their checkout flow — built entirely by prompting, demoed beautifully, "ready for launch." Two hundred lines of React and a serverless function. It looked perfect.

We read it the way a reviewer reads it: adversarially. Fourteen bugs. Here's the anatomy.

The setup

A standard checkout: cart summary, shipping form, payment via a third-party provider, order confirmation. The AI-generated code was clean-looking — good variable names, tidy components, comments that explained what each block did. This is what makes vibe-coded code dangerous: it reads like it was written by someone competent.

The bugs, by severity

Critical (would cost money or data):

  1. Double-charge race. The "Pay" button didn't disable during submission. Double-click = two charges. The payment provider's idempotency key was never set — the AI didn't know the provider supported one.
  2. Price from the client. The total was computed in the browser and sent to the server, which trusted it. Open devtools, change $129 to $1, check out. The oldest bug in web commerce, regenerated with confidence.
  3. No webhook verification. The payment-success webhook accepted any POST with the right shape. Anyone could forge a "payment succeeded" event and get free orders.
  4. Card data touched the server. The form posted raw card fields to the founder's own endpoint "for validation" before tokenizing. That's PCI scope explosion — a compliance liability hiding behind a helpful comment.

High (would break the business logic):

  1. No inventory check at purchase time. Stock was checked when the page loaded, not when the order was placed. Overselling was guaranteed under any real traffic.
  2. Currency assumed USD. Amounts were formatted with $ hardcoded. The founder planned to launch in three countries.
  3. Tax computed client-side with a flat rate in a constants file. "TODO: make dynamic" — the AI even left the TODO.
  4. Order confirmation emailed before payment settled. The success screen fired on "payment initiated," not "payment captured." Failed payments still got thank-you emails.

Medium (would embarrass you):

  1. No handling for expired sessions — the cart silently emptied after 30 minutes with no message.
  2. Form validation only on submit, with errors that cleared the entire form on re-render.
  3. The loading spinner had no timeout — a hung request meant a permanently spinning page.
  4. Accessibility: zero. No labels on inputs (placeholders only), no focus management, the error summary wasn't announced to screen readers.
  5. No analytics events — the founder would have launched with no idea where checkouts were abandoned.
  6. Secrets in the bundle. The payment provider's secret key — not the publishable one — was in client-side code. We stopped counting severities after this.

Why the demo didn't catch any of it

The demo did the happy path: one item, valid card, fast network, USD, no double-clicks, no adversaries. Every bug on this list lives outside the happy path — in races, in malice, in edge cases, in the boring infrastructure of trust. Demos test whether it works. Review tests whether it's safe. AI is excellent at the first and structurally incapable of caring about the second.

The fix wasn't a rewrite

Here's the part that surprises people: we didn't throw the 200 lines away. The UI code was fine. What it needed was the engineering layer around it — server-side price computation, idempotency, webhook signatures, tokenization-first card handling, inventory transactions. About a day of work by someone who'd been burned before. The AI built a beautiful storefront with no locks on the doors; we installed the locks.

That's the teardown's real lesson. Vibe-coded code isn't worthless — it's unfinished. The gap between "demo" and "done" is exactly the set of things in this list, and it's the same gap every time.


Got code that demos beautifully and scares you slightly? Send it our way — teardowns are what we do, and the first review is an honest one.