Fix.
How to migrate a vibe-coded app to a standalone codebase
How to safely extract an AI-generated web app from platforms like Lovable or Bolt into an independent codebase and dedicated database you own.
AI app builders like Lovable, Bolt, and Replit are phenomenal for taking an idea from zero to an interactive proof of concept. You describe your interface, test forms, and see working screens in minutes.
The friction begins when your prototype attracts real paying customers. Monthly platform credits escalate quickly, debugging generation regressions becomes a bottleneck, and your database remains locked inside a proprietary cloud instance where you cannot run custom migrations or automated backups.
Migrating your application to an independent repository gives you full ownership of your IP, predictable hosting costs, and the freedom to deploy anywhere.
Here is the exact technical sequence we use to decouple vibe-coded applications and transition them into maintainable production software.
Step 1: Export and audit the raw source code
Most AI platforms offer an export to GitHub feature or a downloadable zip archive. Do not assume the downloaded zip matches what is live in production.
AI platforms frequently run server-side edge functions, inject hidden analytics scripts, and inject authentication cookies directly through platform proxies.
- Export the latest project state from the platform to a clean private Git repository.
- Clone the repository locally and run a dependency audit with
npm audit. - Check
package.jsonfor proprietary platform wrappers, such as custom UI kit bridges or mock database clients. - Compare your local environment variables against the platform dashboard to ensure all API tokens and secret keys are accounted for.
Step 2: Separate frontend components from backend business logic
Vibe-coded projects almost always mix presentation code with database queries inside the same React component.
A typical AI-generated component might contain:
// Fragile: Database queries embedded directly in UI markup
export default function ProjectDashboard() {
const [data, setData] = useState([]);
useEffect(() => {
supabase.from('billing_records').select('*').then(({ data }) => setData(data));
}, []);
return <div>{/* rendering */}</div>;
}
This pattern creates three immediate risks: it exposes your internal table schema to client-side bundles, makes automated testing impossible, and prevents server-side rendering optimizations.
Refactor the architecture:
- Move database interaction into dedicated API routes, server actions, or Supabase edge functions.
- Create explicit TypeScript interfaces for all data models.
- Centralize state management so multiple components do not trigger duplicate database queries.
Step 3: Recreate and migrate the PostgreSQL database
If your project was using the AI platform’s managed database, you need to migrate your schema and data to your own dedicated instance, such as an independent Supabase project, Neon, or RDS.
Never copy tables by hand through a visual interface. Generate verifiable SQL migration scripts:
- Extract table schemas: Generate the complete DDL including foreign keys, check constraints, and default values.
- Review Row-Level Security: AI tools frequently create permissive policies (such as
using (true)) that leave sensitive customer records readable by any visitor. Re-architect policies usingauth.uid()checks andsecurity definerfunctions. - Migrate existing records: Export data to CSV or use
pg_dumpto import existing users and customer records into the new database without ID collision. - Preserve authentication mappings: If you used platform auth, export the
auth.userstable so existing customers can log in without resetting their passwords.
Step 4: Isolate backend secrets and API keys
Inspect your frontend code bundle for leaked credentials. AI generators often place secrets in .env.local files that get bundled into client JavaScript.
- Verify that your Supabase
service_rolekey is never referenced anywhere in client components. - Ensure payment webhook handlers (such as Stripe) verify incoming request signatures using your private endpoint secret.
- Store sensitive third-party tokens (OpenAI, Resend, Twilio) strictly in secure environment variables accessible only by serverless functions.
Step 5: Establish continuous deployment and monitoring
Once the codebase is decoupled, configure automated CI/CD pipelines to your production cloud host:
- Hosting: Deploy frontend applications to platforms like Cloudflare Workers, Vercel, or AWS Amplify.
- Build validation: Add automated GitHub Actions that run TypeScript checks and linters on every pull request. This prevents buggy code from being merged into production.
- Error tracking: Install real-time error logging (such as Sentry) to capture client-side crashes before users report them.
The result: complete technical independence
By moving your vibe-coded application to a standalone codebase, you eliminate platform subscription tiers and regain complete control of your product roadmap. Your team can build new features using whichever AI or human workflows fit best, backed by standard infrastructure you control completely.
If you have a growing prototype and need an expert to execute the move without downtime, review our vibe coded to standalone migration service.
More guides on fix
- Hardening Supabase and Node backends for production8 min read
- Migrate a Lovable app from Vite to Next.js and Supabase8 min read
- How to fix infinite recursion in Supabase RLS6 min read
- The vibe coded MVP audit checklist8 min read
- The production web app penetration testing checklist7 min read
- Taking over a codebase someone else built6 min read
- Lovable Cloud to Supabase migration, what it actually involves7 min read
- What it actually costs to fix a vibe-coded app6 min read
- Is your Lovable app ready for real users? Ten checks8 min read
- Supabase RLS policies that actually work7 min read
- Your Supabase service role key is in your frontend. Do this now5 min read
- Check whether your Supabase data is public in five minutes5 min read
- Why your Lovable app shows a blank page after deploy6 min read