Fixing vibe-coded apps
What breaks in apps built with Lovable, Bolt, v0, Cursor and Replit, and how to fix it properly.
The complete guide to fixing a vibe-coded appFix a vibe-coded app in order of risk. Stop prompting, then check exposed keys and access rules, then the data model and payments, then error states, speed, mobile and SEO. Most apps need targeted fixes rather than a rewrite, but get the code into GitHub and out of the fix loop first.10 security holes in vibe-coded apps (and how to close them)The holes that matter most are tables without Row Level Security, policies that let everyone in, secret keys shipped to the browser, roles stored where users can edit them, server endpoints that check login but not ownership, and unverified payment webhooks. Each has a specific fix you can test in minutes.Adding the error handling AI tools skipAI tools build the path where everything works, so failed requests, bad input and crashes get a blank screen or nothing at all. Add an error boundary (error.tsx in Next.js) for crashes, check every fetch and Supabase result, return expected errors as values, show a toast for failed actions, and log errors somewhere you will see them.Bolt app slow: is it the preview, the published site or the database?First work out which part is slow. The Bolt preview runs a development server inside your browser using WebContainers, so it depends on your computer and is slower than the published build. If the published site is slow, look at image weight, database queries and row level security policies, and check the Logs page within the hour.Bolt auth not working: fixing sign-in, Google login and reset emailsMost Bolt login problems trace back to four things: the Site URL and URI allow list in the database's Authentication settings, testing Google sign-in inside the preview instead of the published site, the default limit of 2 auth emails per hour, and table policies that never check who is signed in. Fix them in that order.Bolt database issues: permission errors, paused databases and missing dataMost Bolt database issues come from how Bolt Cloud behaves, not broken code. New tables are private by default since 30 October 2026, unpublished projects pause after six days of low use, restoring a version rolls back code but not the database, and duplicates start with an empty copy. Find which one you hit, then fix permissions, restart, or realign the schema.Bolt mobile layout broken: fixing a Bolt web app on phones, and when you need ExpoCheck the layout in Bolt's Responsive mode and on a real phone using the published site, then fix overflow, fixed widths, viewport height and tap targets in the code. If you need an app-store app rather than a website, Bolt's docs say web projects don't easily switch to mobile, so start an Expo project with the words mobile app in the first prompt.Bolt SEO: why your Bolt site isn't showing up in Google and how to fix itIf your Bolt project is a client-rendered Vite app, crawlers that don't run JavaScript see one near-empty HTML file with the same title on every URL. Publish publicly on a custom domain, use real paths instead of #/ URLs, give each route its own title and description, add robots.txt and a sitemap in public/, and prerender the pages that need to rank.Cursor auth not working: fixing login code the agent wired across filesCursor's agent writes auth code it cannot fully see: .env files are on its default ignore list, so it guesses variable names, and it adds checks wherever the prompt pointed rather than everywhere data is read. Map every auth touchpoint, put the session check in one server-only helper, describe your env and Next.js version in a scoped rule, then review the diff with a deep review.Cursor codebase messy: cleaning up after the agent, and keeping it cleanA Cursor codebase gets messy when the agent makes wide edits with nothing checking them: rules saved in the wrong format are ignored, long chats lose earlier conventions to summarisation, and no test or type check runs before it says it is done. Split the work, rewrite rules as small .mdc files, add a stop hook that runs checks, and review every diff.Exposed API keys in AI-generated code: how to check and fixSearch your built JavaScript and git history for the first characters of each secret key. If one is there, rotate it first, then move the call into server code, such as a Next.js route handler or a Supabase Edge Function, and drop the NEXT_PUBLIC_ or VITE_ prefix. Deleting the key from the code is not enough.Fixing authentication in an AI-built appBroken auth in AI-built apps usually comes down to five things: Supabase's default email sender, a Site URL still set to localhost, a session refresh file with the wrong name for your Next.js version, server code trusting getSession(), and pages that check login but not permissions. Each is a setting or a few lines of code.Fixing broken mobile layouts in AI-generated UIsAI builders usually design in a wide desktop preview, so the base classes describe the desktop layout and phones get whatever is left. Fix it mobile-first: make the unprefixed Tailwind classes the phone layout, add sm: and md: for wider screens, let wide content scroll inside its own box, and swap h-screen for min-h-dvh.How to hand a vibe-coded app to a developerPut the code in a Git repository you own, keep every service account (hosting, database, Stripe, domain) in your name and invite the developer rather than sharing logins, list every environment variable without values, back up the database, and write down how the app works and what is broken. That turns a week of detective work into a day.Lovable app slow: finding the real bottleneck and fixing itIn most slow Lovable apps the database is the bottleneck: queries without indexes, row level security policies that call functions per row, or a small instance under load. Check the pressure cards under More, then Database, then Manage, then Settings, ask Lovable for the slowest queries, fix those, and only then pay for a bigger instance.Lovable auth not working: redirects, email confirmation and lost sessions fixedMost Lovable auth failures come from four places: your live or custom domain missing from the Redirect URLs list, users stuck unconfirmed, a page guard that runs before the saved session loads, or row level security returning nothing. Check More, then Users, then Settings first, then your auth code and table policies.Lovable mobile layout broken: why it looks fine in preview and how to fix itLovable's Mobile view shrinks the preview inside your desktop browser, so it misses phone toolbars, the keyboard and touch. Most breakage comes from fixed widths, full-height screens built on 100vh, wide tables and classes written desktop first. Find the overflowing element, fix it in code or with a targeted prompt, then test the published app on a real phone.Lovable SEO not working: client-rendered vs server-rendered projectsIt depends on when the project was created. Lovable apps from 13 May 2026 use TanStack Start and render every page on the server. Older React and Vite apps render in the browser, and only verified crawlers get pre-rendered copies, which can miss late-loading content. Run the SEO and AI search review, fix metadata per page, and consider upgrading older projects.Lovable Supabase issues: empty data, paused databases and schema drift fixedMost Lovable Supabase problems come from row level security returning nothing, a paused database, schema changes made outside Lovable's migrations, or two Lovable projects sharing one Supabase project. Work out which backend you are on first, because Lovable's built-in backend and your own Supabase project are fixed in different places.Replit Agent code messy: how to clean up an Agent-built codebase without breaking itAgent edits what each prompt asks for, so after weeks of chat a Replit app collects duplicate components, dead routes and a database schema out of step with the code. Clean it in small reviewed steps: write real rules into replit.md, plan each refactor in Plan mode, commit to GitHub before every change, and read the migration SQL before it reaches production.Replit auth not working: how to fix sign-in on a published appMost Replit sign-in failures come from treating development and production as one. Clerk Auth on Replit runs separate Development and Production environments, with separate keys, users and sign-in settings. Find out which auth system Agent installed, then check the production keys, the published domain and the server-side check on every API route.Replit SEO not working: why Google can't see your Replit app and how to fix itReplit's SEO rating and SEO Agent fix the technical basics, such as titles, meta descriptions, sitemap.xml and robots.txt. They can't fix an app that is private or serves the same empty HTML for every URL. Make the app public, put it on a custom domain, and make each page that should rank return its own title, description and content.The vibe-code rescue checklistCheck the things that lose money, data or trust first: secret keys in the browser, missing access rules, payments that rely on the success page, and errors nobody sees. Then check mobile layout, accessibility, speed and whether you own the code and accounts. Most items can be tested without reading code.v0 auth not working: why login breaks between preview and productionMost v0 auth failures are environment problems, not form problems. The v0 preview only reads Development variables, Supabase does not know your preview or production URLs, Vercel protection sits in front of your login, or the session refresh file never runs. Fix those four, then check the session on the server in every protected page and action.v0 code messy: how to untangle a v0 project and keep it tidyv0 code gets messy when UI and data logic are generated in the same prompts, database queries are written inline without an ORM, and several chats change the same project on separate branches. Connect GitHub, move data access into one folder, split server and client components, add type checks and tests to CI, and save your structure as a v0 Instruction.v0 mobile layout broken: fixing a v0 app that only works on desktopv0 builds with Tailwind and shadcn/ui, which are mobile-first, but layouts prompted and previewed on a desktop often only add classes for wide screens. Rewrite the base classes for a 375px screen, add larger breakpoints on top, contain overflow, and stop layout-critical parts from waiting on JavaScript to detect a phone.What a vibe-code rescue costs in the UKIt depends on how many problems there are and whether the data model is sound. UK contract developers advertised with React or Next.js skills had a median of about £520 to £525 a day in the six months to November 2026, so a week of fixes at the median is roughly £2,600. Fixed-price rescues are priced after an audit instead.When to refactor vs rebuild a vibe-coded appRefactor when the data model is sound and the problems are local, like missing error handling, messy components or a broken mobile layout. Rebuild when the data model is wrong, security is broken at the foundations, or you can't get the code out. Most often the answer is in between: keep what works and replace the rest piece by piece.Why AI-built apps break after the first 100 usersThey break because real users hit limits a one-person preview never touches: the default email sender, unindexed queries on growing tables, the 1,000-row API cap, database connections from serverless functions, two people acting at once, and third-party rate limits. None of these show up when you test alone with ten rows of data.Why your AI-built app is slow, and what fixes itAI-built apps are usually slow for a few specific reasons: data fetched in a chain of requests after the page loads, queries without indexes, access policies that re-run for every row, a server region far from the database, and too much JavaScript and image weight. Measure first, then fix the slowest step, which is usually the data.Your AI app's database is a mess: how to fix the data modelWrite down what each table is for, then fix the schema in small migrations: replace copied text with foreign keys, merge duplicates and add unique constraints, store money as integer pence, use timestamptz for times and index what you filter on. Clean the existing data before each constraint, and make every change through a migration file, not the dashboard.
See if BlackFig fits your idea (it probably does)
A quick 30 minute call. No slides, no hard sell. You leave with a clear next step either way.