All posts

June 28, 2026 · 9 min read

The Ejection Trap: Surviving the Export from Lovable to Local

Hit Export Project and discover broken env vars, monolithic files, missing pieces, and a build that won't build. Here's the survival path.

By Launched team

You outgrew the platform. You hit Export Project. A zip lands on your desktop. You unzip it, run npm install, run npm run dev, and the screen goes white. Console error: SUPABASE_URL is undefined. You add it to a .env file. New error: a route imports a file that isn't in the export. You fix that. New error: the auth callback redirects to a preview URL that no longer exists. By midnight you're wondering if you should just go back.

The export is not the running app

What runs in the cloud preview is the export plus a stack of platform magic: env injection, route patching, callback rewriting, runtime polyfills. The zip you downloaded is the export. The magic stayed behind.

The failure modes, in order of appearance

  • Missing env vars: the platform injected them; your .env doesn't exist yet.
  • Hardcoded project IDs and URLs: scattered across files, pointing at preview infrastructure.
  • OAuth callbacks pointing at the old preview domain: sign-in works once, never again.
  • Monolithic route or component files: 2,000-line files that no human (or AI) wants to touch.
  • Missing exports / dangling imports: the route tree references files the zip didn't include.
  • Lockfile drift: the preview ran a patched version of a Vite plugin; you don't have it.

The survival path

Step 1: Get it to boot, ugly

Don't refactor yet. Stub the missing env vars with placeholders, comment out the broken imports, get npm run dev to render something. You need a baseline.

Step 2: Stand up your own Supabase project

Don't try to reuse the platform's. Create a new Supabase project, port the schema (a clean migration is easier than reverse-engineering), repoint the env vars, rewrite the OAuth callback URLs.

Step 3: Port feature-by-feature, not file-by-file

The exported file structure is optimized for the platform's runtime, not for human maintenance. Take the business logic, leave the platform glue, rewrite the wiring on a normal React meta-framework (Next.js or TanStack Start).

Step 4: Wire integrations one at a time

Stripe webhook URLs, Resend domains, OAuth providers, storage CORS. Make a checklist. Cross each one off only after a real end-to-end test.

Step 5: Cut over behind a feature flag

Run both deployments in parallel. Diff behavior. Flip the DNS only when nothing is on fire.

Where Launched comes in

We do this migration weekly. Flat fee. Days, not weeks. You keep the code and you keep the database. Book a 20-minute call. Related: Escape vendor lock-in, Own your build.