5 min readEngineering
When AI starts breaking your own code: a production rescue checklist for Bolt, Cursor and v0 apps
When every prompt breaks something that worked, stop prompting. A checklist for rescuing a Bolt, Cursor or v0 app and getting it ready for real users.
When each prompt fixes one thing and breaks another, the code has outgrown what the AI can keep in view at once. More prompting usually makes it worse. Stop, save a working version you can return to, and fix the app in a set order: security, the main flow, errors, then structure. This is the checklist I use.
Why AI tools start breaking working code
An AI coding tool only sees part of your project at a time. While the app is small, that part is most of it. As files grow, the tool starts rewriting code from a partial view: it repeats logic that already exists somewhere else, changes a function three other screens rely on, or quietly drops a check it didn't know was there. With no tests, nothing tells you until a user finds it.
The signs are easy to spot once you know them:
- A bug you fixed last week is back.
- A change to one screen breaks a different one.
- Files of a thousand lines or more, and three versions of the same function.
- The tool says it fixed the problem, and it didn't.
First, stop the damage
- Save a working versionGet the code into git if it isn’t already: Bolt and v0 can both send a project to GitHub. Tag the last version that worked, so every later change can be compared with it.
- Review every change before it landsIn Cursor, read the diff instead of accepting everything. In Bolt and v0, make one change per prompt and check it before the next. It's slower, and it's what stops the loop.
- Write down what worksSign up, the main action, payment, the admin screens: one line each. That list becomes the test you run by hand after every change, until there are real tests.
The rescue checklist
- Secrets out of the browserAny key in a
NEXT_PUBLIC_orVITE_variable is public. Move secret ones to the server and rotate them. The full how-to. - Checks on every server routeIn Next.js, every Route Handler and every Server Action is a public endpoint anyone can call. Each one should check who is asking and whether they may do this, not trust the screen that called it.
- Database rulesSupabase row-level security or Firebase Security Rules, read against who should see what. My Supabase checklist.
- Payments by webhookAn order is paid when a signed webhook from Stripe says so, and handling the same event twice changes nothing.
- Errors you can seeError tracking on the front end and the server, with the user and the page attached, so failures come to you.
- Types switched onRun
tsc --noEmitand read what it says.anyand@ts-ignorearound money and sign-in are where bugs hide. - Tests where mistakes cost moneyA handful of browser tests (Playwright works well) for sign-up, the main action and payment. Not full coverage, just the paths you can't afford to break.
- One copy of each piece of logicFind the functions that exist three times and keep one. This is the change that stops fixes from undoing each other.
- Packages you choseRemove the ones nothing uses, update the ones with known security holes, and keep the lockfile in git.
- A deploy you can repeatPreview deploys for every change, separate settings for staging and production, and a staging database.
A first health check takes a few minutes. From the project folder:
npx tsc --noEmit # type errors the build may be hiding
npx eslint . # unused code and hook mistakes
npm audit --omit=dev # packages with known security holes
npx knip # files, exports and packages nothing usesRefactoring AI-written React code without breaking it
Don’t clean everything at once. Pick the part that breaks most often, put a test around what it does today, then change it in small steps and run the test after each one. When it passes and the code is simpler, move to the next part.
- Split giant components: data loading in one place, display in another. A 900-line page is usually four components and two hooks.
- Fetch data one way. In a Next.js app from v0, that might mean server components for reads; in a Vite app from Bolt, one query library instead of
useEffectcalls scattered through the screens. - Check where
'use client'sits. At the top of every file, it means nothing renders on the server, which costs speed and search. - Give the AI tool the map. A rules file (
.cursor/rules,AGENTS.mdor similar) that says how the app is organised keeps the next prompt from undoing the clean-up.
Hiring an engineer to finish a Cursor project
Send the repository, the list of what works and what doesn't, the names of the environment variables (not their values, not in a chat), and the date you need it by. Ask for an audit before a quote for the whole job: anyone who prices a rescue without reading the code is guessing.
My audit is $500 – $1,500, with the report in 3 to 5 days, and the fixes are quoted from it, usually $1,500 – $6,000. Here is how a rescue works with me.
Questions people ask
- Can a v0 app go to production?
- Yes. v0 writes ordinary Next.js and React code. It's ready for real users after the same checks as any other code: server-side access checks, secrets on the server, error tracking, tests on the main paths and a repeatable deploy.
- Is it cheaper to fix an AI-built app or rewrite it?
- Usually to fix it, because the app already works for its users. A rewrite pays off when the data model is wrong for the business. This post covers how to tell.
- How long does a rescue take?
- The audit takes 3 to 5 days. The fixes depend on what it finds, and I give you a fixed quote and a timeline from the audit, before any work starts.
- Will you keep working in Cursor or Bolt?
- I use AI coding tools in my own work too. The difference is that every change is reviewed and tested before it ships, and the code is left organised so your tool can keep working on it.