Article
How to rescue a vibe-coded app: the order that works
Published on
The app got to 80% in a week. The last 20% has taken a month and is not done. Every prompt that fixes one screen breaks another, the credits go on loops over the same error, and you no longer deploy on a Friday, or at all, without holding your breath. That is the moment an AI-built app needs a rescue rather than another prompt.
A rescue is not a rewrite. Whether to rebuild is a separate decision, made with numbers, and covered in rebuild or fix your vibe-coded app. This post is about the other path, which is the usual one: keeping what works and making the rest safe to change. What matters most is the order. Each step makes the next one cheaper, and skipping ahead is how rescues turn into a second round of the same mess.
Signs you are past "one more prompt"
- A fix in one place breaks something unrelated, and you only find out from a user.
- You cannot say where the data lives, who can read it, or whether there is a backup.
- The app works in the preview and fails on the real domain.
- Nobody, including the AI, can explain why a part works the way it does.
- You are afraid to touch payments or login.
One of these is a bug. Three of them mean the app no longer has a structure you can steer.
0. Stop adding features
Every feature added during a rescue is built on ground that is about to move. Freeze the scope for the duration: bugs that hurt users get fixed, new ideas go on a list. This is the hardest step for a founder and the one that makes the rest affordable.
1. Get custody of everything
Before any code changes, make sure you own what you are rescuing:
- The code in a Git repository you control. Lovable and Bolt can both connect to GitHub; apps built with Cursor, Claude Code or Codex usually live in a folder on someone's laptop, which is not the same thing. One repository, one main branch, and the deployed version traceable to a commit.
- The backend in your accounts. The Supabase project, the Stripe account, the domain and the hosting should be under your company's login, not the freelancer's or the tool's.
- A list of every service the app touches, with who pays for it and where its keys are set. AI-built apps quietly accumulate these: an email provider, an AI API, a storage bucket, a second Supabase project for testing that production still points at.
This is not paperwork. A "mysterious" production bug in these apps often turns out to be a setting in an account nobody remembered.
2. Close the holes that expose data or money
Security comes before bugs because it is the one problem that gets worse while you wait. In AI-built apps the same few holes appear again and again:
-
Secret keys in the browser. Build the app and search the output for key prefixes that must never be public. Stripe's secret and restricted live keys start with
sk_live_andrk_live_; Supabase's secret keys start withsb_secret_:grep -rlE 'sk_live_|rk_live_|sb_secret_' dist/dist/is Vite's default build folder, which Lovable apps created before 13 May 2026 use; newer Lovable apps run on TanStack Start. In a Next.js app, search.next/static/instead: it holds the JavaScript and CSS served to the browser under/_next/static/. For any other setup, search the folder the build writes the browser files to. Add the first characters of every other secret the app uses, such as an AI provider's key, copied from that provider's dashboard. Each hit is a lead, not proof: check whether it is a real key that reaches the browser. If it is, move the call that uses it to a server function and rotate the key, because removing it from the code does not remove it from versions already published. If the project still uses Supabase's legacy JWT keys, check in the API settings which one the frontend uses: theanonkey is meant to be public, theservice_rolekey never is. -
Tables without row-level security, or with policies that allow everything. A policy of
USING (true)filters no rows: fine for data that is meant to be public, no protection at all for data that belongs to one user. The RLS error guide shows the policies that are actually safe. -
Permissions enforced only in the interface. Hiding the admin button is not access control. Every check has to happen again on the server or in the database.
-
Payment webhooks that are not verified, so anyone can mark an order as paid.
The full list is in the security checklist. Go through it before anything else in this post.
3. Make sure you can go back
Changing an app safely needs two things it probably does not have:
-
A backup you have restored at least once. Check what your database plan actually keeps, then take a copy you control. Supabase's backup and restore guide uses three dumps, with the connection string you get from Connect on the project dashboard:
supabase db dump --db-url "$DB_URL" -f roles.sql --role-only supabase db dump --db-url "$DB_URL" -f schema.sql supabase db dump --db-url "$DB_URL" -f data.sql --use-copy --data-only \ -x "storage.buckets_vectors" -x "storage.vector_indexes"Then restore them into an empty project with
psql, as the same guide shows, to prove they work. Uploaded files are not in these dumps; the guide moves them with a separate script. An untested backup is a hope. -
A place to break things that is not production. A second Supabase project and a staging deploy of the same code. If the AI tool can write to the production database, one bad prompt can delete real data.
And deploys should come from the repository, so that undoing a bad one is a revert and not an afternoon of reconstruction.
4. Pin down what the app does today
Before fixing anything, write down the journeys that must keep working: signing up, logging in, paying, and the two or three actions the app exists for. Then turn each one into an automated end-to-end test (Playwright is the usual choice) that runs before every deploy.
Include the quirks. Users build habits around the app as it is, bugs included, and a rescue that "fixes" a behaviour someone relies on is a regression from where they sit. A test that pins the current behaviour lets you change it deliberately rather than by accident.
These tests are also what make AI coding safe again afterwards: an agent that has to keep them green cannot silently break checkout while fixing a margin.
5. Fix what blocks launch, then what blocks growth
Now the bugs, in this order:
- Launch blockers. Login that redirects to
localhost, payments that work in test mode only, emails that never arrive, a custom domain that will not verify. These are usually configuration rather than code; the common ones are in why an app works in preview but not in production. - Anything touching data or money. Duplicate charges, orders without a user, records that two users can overwrite.
- What blocks the next feature. The part of the structure that the roadmap keeps fighting: a second user role, a team account, an integration.
Fix in small slices that each ship on their own, with the tests from step 4 green every time. A rescue that disappears for six weeks and comes back as one giant change has the same risk as the rewrite it was meant to avoid.
6. Tidy the structure last, and only where you will work
AI-generated code is full of duplication: three ways to call the database, two date formats, a 600-line component. It is tempting to clean it all. Don't. Clean the areas the next months of work will touch, consolidate one pattern at a time, and leave stable, ugly code that nobody needs to change alone. Tidiness has a cost, and it only pays back where change happens.
7. Hand it back so you can keep building
The goal is not an app you can never touch again. It is one you, a developer or an AI agent can keep changing without fear:
- A README that says how to run it, test it and deploy it.
- Every environment variable listed, with where its value lives.
- A rules file for the AI tools (
AGENTS.md, Cursor rules, Lovable's knowledge settings) that names the patterns to follow and the tests to keep green. - Someone who knows what to do when something breaks at night.
What not to do
- Ask the AI to "fix everything". Without tests and a way back, a large prompt is a large, unreviewable change. It is how most of these apps got here.
- Start with the redesign. A new interface on top of an open database is a nicer-looking incident.
- Skip custody because the freelancer is nice. People move on; accounts stay with whoever created them.
Doing it yourself, or with us
Everything above can be done in-house if someone on the team is comfortable with databases, deploys and tests. The hard part is usually the first look: knowing which of the hundred things wrong are the five that matter.
That first look is our vibe code rescue audit: 450 EUR, 48 working hours, and a written report of what works, what is broken, what is a real security risk and what each fix costs, in the order above. You can take the report and do the work yourself. If you continue with us, the fee is deducted and the rescue runs as a fixed-scope quote, typically 1,500-6,000 EUR. We finish your app; we do not rebuild it unless the numbers say so, in writing.