If you’re exporting your Lovable code for the first time, open the zip and run npm install && npm run build before you do anything else. On a fair number of projects that command fails straight away: a missing environment variable, a Supabase client that was never configured outside Lovable’s preview environment, an import path that only ever resolved inside their sandbox. That’s the first real signal of what moving your app off Bolt or Lovable actually involves. The platform isn’t hiding your code from you, but “you can download a zip” and “you own a working application” are two different claims, and the gap between them is where founders get stuck.
We see this pattern often enough to have a name for it internally: the export looks complete and runs nowhere. Not because the builder did anything underhanded, but because a lot of what makes your app actually work lives in their dashboard, not in your repo.
Signs you’ve outgrown the builder
Vendor lock-in isn’t a crisis, it’s a stage. Most founders who built with Lovable or Bolt hit the same wall eventually, and it’s worth naming the symptoms before you start planning an exit:
- You’re paying for a plan tier mainly to unlock build minutes or seats, not features your users actually need.
- Every small change now breaks something unrelated, because the AI is re-reasoning about a codebase it didn’t design for your current complexity.
- You need backend logic the visual editor can’t express: a scheduled job, a queue, a custom webhook handler, rate limiting that isn’t a toggle.
- A second developer wants to contribute and there’s no real git workflow, just the builder’s own version history.
- A customer or investor asks where your data is hosted and you genuinely don’t know the answer.
- You’ve been told by a platform rep, directly or indirectly, that a feature you need “isn’t on the roadmap.”
None of these mean your app is badly built. They mean the tool that got you to a working product isn’t the tool that will take you past it. If you’re still deciding which builder got you into the best or worst position, our comparison of Cursor, Bolt, and Lovable is worth reading before you commit to a migration plan, because the right next step differs depending on which one you’re leaving.
What you actually get when you export, and what stays behind
When you hit “export” or “download code,” you get your application code. Usually that’s a React or Next.js project, a package.json, and whatever components and pages the builder generated. That part is genuinely yours and it’s the easy part.
Here’s what typically does not come in the zip:
- Environment variables. API keys, database URLs, and auth secrets live in the builder’s hosted environment, not in your exported files. You’ll see
process.env.SOMETHINGreferenced in the code with no value anywhere. - The actual database. Lovable and Bolt both commonly provision a Supabase project behind the scenes. The export gives you the client code that talks to it, not the database itself. You need a separate step, often a transfer of project ownership inside Supabase, to actually take control of your data and schema.
- Auth configuration. OAuth app registrations with Google, GitHub, or others are tied to the builder’s domain and callback URLs, not yours.
- Serverless functions or edge functions, if the app uses any, that run on the builder’s infrastructure and may not be included in a plain code export at all.
- Webhooks and integrations configured through the builder’s own dashboard, like Stripe webhook endpoints pointing at a
*.lovable.appor*.bolt.newsubdomain. - Analytics, custom domains, and DNS records that were set up through the platform rather than through code.
This is the same gap we cover in more detail in our guide to not losing your data as vibe coders: the code export and the data export are two different operations, and skipping the second one is how founders lose their user table on moving day.
The pieces that need rewiring
Assume every one of these needs to be touched, not just copied:
Hosting. You need somewhere new to deploy: Vercel, Netlify, Amplify, Cloudflare, your own server. The exported code usually isn’t pre-wired for any particular host, so you’re setting up a fresh build pipeline from scratch.
Environment variables. Rebuild the .env file by hand, service by service. A useful habit is to keep a plain text inventory as you go:
DATABASE_URL=SUPABASE_URL=SUPABASE_SERVICE_ROLE_KEY=STRIPE_SECRET_KEY=STRIPE_WEBHOOK_SECRET=GOOGLE_OAUTH_CLIENT_ID=GOOGLE_OAUTH_CLIENT_SECRET=NEXTAUTH_URL=Every blank line is a credential you need to track down from a dashboard somewhere, and some of them you’ll need to rotate rather than reuse, because the old ones may still be visible to the platform.
Database. Decide early whether you’re keeping the existing Supabase (or similar) instance under your own account, or migrating the schema and data to a new one. Transferring ownership is usually less risky than a fresh migration, because a migration means dumping, restoring, and re-checking row-level security policies by hand.
Auth callbacks. This is the one that bites people after launch, not before. Every OAuth provider has a registered redirect URL, and it’s almost always hardcoded to the builder’s domain:
https://yourapp.lovable.app/auth/callback → https://yourapp.com/auth/callbackMiss one of these and login works fine in your testing, because you’re testing against the old domain’s session, then breaks for every new user on launch day. Check Google, GitHub, Stripe, and any email provider’s webhook settings, not just the auth provider you remember configuring.
A step by step move plan
- Export the code and build it locally before touching anything else. If
npm run buildfails, fix that first, it tells you exactly what’s missing. - Write down every external service the app touches: database, auth providers, payment processor, email, analytics, file storage. For each one, note where the credentials live right now.
- Stand up the new hosting environment and deploy the exported repo to a staging URL, not your real domain yet.
- Transfer or migrate the database, then point the staging deployment at it and test every read and write path, not just the homepage.
- Update auth callback URLs and webhook endpoints in every provider’s dashboard to the staging URL, confirm login and payments work end to end.
- Only once staging is fully working, repeat step 5 pointing at your real domain, switch DNS, and keep the old builder environment live and read-only for a week or two in case something was missed.
Resist the urge to switch DNS before step 5 is done on staging. That’s the step people skip under deadline pressure, and it’s also the step that causes the quiet failures, a login that works for existing sessions but not new signups, a webhook that silently stops firing because Stripe is still posting to the old URL.
When to bring a developer in for the migration
Do it yourself if the app is small, has one or two integrations, and you’re comfortable reading code even if you can’t write it. Bring someone in when the app touches payments, handles any personal data covered by GDPR or similar rules, or has more than a couple of auth providers. The failure mode for a solo migration isn’t usually “it doesn’t work,” it’s “it works for you and fails silently for ten percent of users,” and that’s expensive to debug after the fact.
If you’re planning to hand this off rather than do it yourself, our piece on handing off a vibe-coded app to a dev team covers how to brief a developer so they’re not starting from zero on day one, which matters even more when the handoff happens mid-migration rather than after it.
Ready to move your app somewhere you control? We’ll plan the move. Get a free assessment.