How to migrate from Lovable to your own hosting
GitHub sync, Vite frontend on Vercel, decide whether to keep or move the Supabase project, replace auth redirects, OAuth callbacks and Edge Functions. Includes a flag for the newer TanStack Start stack.
Lovable is one of the cleanest exits in the AI-builder market. Lovable's documentation states that "you own your code," that projects can be continuously synced to GitHub, and that exported applications are "standard Vite + React projects" deployable on any major cloud provider or self-hosted infrastructure (source).
Stack note for newer projects. Around April 20, 2026, Lovable silently switched new projects to TanStack Start with SSR instead of Vite. Lovable's own SEO docs confirm it: "New apps are built on TanStack Start, which supports full server-side rendering (SSR)" (source). Old projects were not migrated. Check
package.jsonbefore following any deploy step — if you seevinxior anapp.config.tsin the root, you are on the new stack and the Vite-specific deploy details below (output directory, SPA-fallback rewrites) do not apply. The GitHub sync, env-var, auth-redirect and Supabase parts of this guide still work either way.
The frontend portion of a Lovable project is genuinely portable. The backend is where most of the migration work lives — and the path depends on whether you stay on Supabase or move off it entirely.
What a Lovable project actually contains
A typical Lovable build is structured like this:
| Layer | Default in Lovable | What you migrate |
|---|---|---|
| Frontend | Vite + React (TanStack Start + SSR for projects created from April 20, 2026) | GitHub repo → Vercel, Netlify, Cloudflare Pages, Railway, or any static host |
| Database | Supabase (managed by Lovable Cloud, or your own Supabase project) | Either keep the existing Supabase or move to a separate Supabase project |
| Auth | Supabase Auth | Redirect URLs, OAuth providers, sessions |
| Storage | Supabase Storage | Buckets, policies, files |
| Edge Functions | Supabase Edge Functions | Functions and their secrets |
| Env vars | .env with VITE_* keys | Same keys on the new host |
| Custom domain | Lovable Cloud or external | DNS + SSL on the new host |
The Lovable platform itself — the editor and the AI agent — cannot be self-hosted. Only the applications it generates are portable. If you depend on Lovable's AI to keep editing the project, syncing back to GitHub keeps both ends in step. If you are leaving for good, the AI agent goes with the platform.
Decide what you are actually migrating
Lovable migrations split into three scenarios with very different scopes:
Scenario A: Move only the frontend. The application stays on Supabase (whichever Supabase project Lovable provisioned), and the migration is a frontend deploy. This is the lowest-risk path and what most projects should start with.
Scenario B: Move frontend and Supabase project. A new Supabase project under your own account, with the database, auth users, storage and edge functions migrated over. Lovable documents that database, storage and configuration are portable, with managed Supabase or self-hosted Supabase as the supported targets (source).
Scenario C: Move off Supabase entirely. A separate Postgres host, plus a replacement for Supabase Auth, Storage, Realtime and Edge Functions. Lovable's docs note that migrating to plain Postgres "is not supported out of the box" because the app code relies on Supabase-specific features. This is a rewrite, not a migration.
Most teams should run A first, get the frontend stable on a new host for a week or two, then consider B if there is a real reason to leave Supabase. C is rarely worth the effort.
Step 1 — Sync the project to GitHub
In the Lovable editor, open project settings and connect to GitHub. Lovable creates the repository if one does not exist, and applies two-way sync between the editor and the repo. Edits in Lovable push commits to GitHub; commits pushed to the active branch sync back into Lovable.
Once the repo exists, clone it locally:
git clone <your-github-repo-url>
cd <project-name>
git tag pre-migration
git push --tags
The tag is the rollback point if the migration goes wrong.
Step 2 — Inventory the stack
cat package.json
ls supabase 2>/dev/null
cat vite.config.* 2>/dev/null
cat .env 2>/dev/null
A standard Lovable project has:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
Build command npm run build, output directory dist, Node 22. If there is a supabase/ folder, the project has its own Supabase migrations and possibly Edge Functions; if there is no supabase/ folder, the project is calling a Supabase project managed by Lovable Cloud.
If package.json lists vinxi instead of vite, the project is on Lovable's newer TanStack Start stack — the deploy steps below assume Vite; treat the TanStack Start variant as a server-rendered Node.js app and let Vercel or Railway auto-detect it.
The environment variables to look for in .env:
VITE_SUPABASE_URL=
VITE_SUPABASE_PUBLISHABLE_KEY=
VITE_SUPABASE_PROJECT_ID=
These are the keys the frontend uses to reach Supabase. They are safe to expose to the browser (the publishable key is the anon key), so they belong on the host's environment-variables panel.
Where Lovable stores secrets
The .env file in the repo holds the browser-safe VITE_* keys. Anything that should not be public — third-party API keys, secrets used by Edge Functions — lives in Lovable's Cloud tab → Secrets section (click the + button next to Preview in the editor, then Secrets). Lovable encrypts these and injects them into Edge Functions automatically.
There is no export button. Open the Secrets panel, list every key, and copy each pair into the new host's environment-variables panel manually. If the project uses Edge Functions, the same secrets need to be set on the destination Supabase project (supabase secrets set KEY=VALUE via the Supabase CLI). See the hub guide's secrets-moving principles for what to rotate vs migrate.
Step 3 — Build locally
npm ci
npm run build
npm run preview
If npm run build fails, the production deploy will fail the same way. Resolve build errors before continuing — typically missing env vars or a TypeScript regression.
Step 4 — Deploy the frontend
Vercel
The path of least resistance for a Vite + React project.
- Import the GitHub repo at vercel.com/new.
- Framework preset: Vite (Vercel auto-detects).
- Build command:
npm run build. Output directory:dist. - Add the three
VITE_*environment variables under "Environment Variables." - Deploy.
If direct URL navigation to client-side routes (/dashboard, /settings) returns 404, add vercel.json to the repo root:
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}
Netlify or Cloudflare Pages
Same Vite settings — build npm run build, publish directory dist, same env vars. For SPA fallback, add public/_redirects:
/* /index.html 200
Railway
Useful if you want the frontend and other Railway services in one project. Either deploy from GitHub with the same Vite settings, or use a Dockerfile if Railway's auto-detection picks the wrong defaults.
Step 5 — Update auth redirect URLs
This is where most Lovable migrations break in production. The new domain — both the host-provided one (my-app.vercel.app) and any custom domain — has to be added everywhere the old Lovable domain was registered:
- Supabase Authentication → URL Configuration → Site URL + Additional Redirect URLs.
- Any OAuth provider (Google, GitHub, etc.) → authorized redirect URIs.
- Magic-link email templates if they hardcode a domain.
Users on the old domain will still have valid sessions, but new logins from the new domain will fail until the redirect list is updated.
Step 6 — Optional: move to your own Supabase project
Skip this if Scenario A is enough. If you want full ownership of the database, Lovable's official guide for this scenario uses your repo's existing supabase/migrations/ files rather than a generic pg_dump — that path is the one documented below (source).
Working with a coding agent. If you would rather not run these steps by hand, Claude Code, Codex, or another agent with repo access can do the mechanical work. Open the cloned repo in the agent, point it at this guide, and let it handle the migration files, env-var updates and the
supabase/config.tomledit. CLI commands (supabase link,supabase db push, deploy commands) run inside the agent session in your local terminal with your approval. This is the realistic option if you came to Lovable from the no-code side and the database side feels unfamiliar.
Manual path (Supabase dashboard)
- Create a new Supabase project. supabase.com → New project. Pick your organization, set a database password (save it), choose the region closest to your users. Wait ~2 minutes for provisioning.
- Save the new credentials. From the new project's settings, copy Project ID, anon (publishable) key, and the project URL
https://[project-id].supabase.co. - Update
.envin the cloned repo:
VITE_SUPABASE_URL=https://[new-project-id].supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=[new-anon-key]
VITE_SUPABASE_PROJECT_ID=[new-project-id]
- Update
supabase/config.toml— changeproject_idto the new project ID. This file ships with every Lovable project that uses Lovable Cloud. - Run the SQL migrations. Every Lovable Cloud project has SQL files in
supabase/migrations/, named with timestamps so they sort chronologically. Open the SQL Editor in the new Supabase project, paste each migration file's contents in order, and run them one by one. This carries over tables, RLS policies, functions and triggers. - Move the data. In the old project: Database → Table → Export CSV for each table. In the new project: Table Editor → Insert → Import data from CSV. Map columns when prompted.
- Reconfigure authentication providers. Authentication → Sign In / Providers on the new project. Enable the same providers, and update OAuth redirect URLs in Google Console / GitHub / etc. to point at the new Supabase project URL.
- Migrate storage files. Download buckets from the old project (Cloud → Storage), upload to the matching buckets in the new project (Storage tab).
- Re-create Edge Function secrets. Edge Functions → Manage Secrets on the new project. Re-add anything the functions need (Stripe keys, third-party API tokens, etc.).
- Update env vars on the deployment host to the new
VITE_*values, and redeploy — Vercel and Railway only apply env changes to new deployments.
CLI path (Supabase CLI)
For comfort with the terminal:
npm install -g @supabase/cli # or: brew install supabase/tap/supabase
supabase login
supabase link --project-ref [new-project-id]
supabase db push # runs every migration in supabase/migrations/
supabase db diff # verify schema matches
The CLI path replaces steps 4-5 of the manual path. Data migration (step 6), auth providers (7), storage (8) and secrets (9) still need to be handled separately.
One thing that does not migrate: user passwords. Supabase's auth system stores password hashes that cannot be exported. Users will need to reset their passwords on the new project. Plan around this — ideally migrate before the project has many real users, or build a password-reset flow into the cutover.
What you have to replace yourself
Lovable Cloud bundles production hosting, custom domains, automatic SSL, managed authentication with row-level security, database and file storage, preview environments, managed AI provider access, OAuth configuration with token refresh, and compliance infrastructure (source). The migration replaces these one by one:
- CI/CD — handled automatically once GitHub is connected to Vercel or Railway.
- SSL — Vercel and Railway issue Let's Encrypt certificates on the custom domain automatically.
- Auth + RLS — stays on Supabase. Configuration moves to your Supabase project if you ran Scenario B.
- AI provider keys — open accounts directly with OpenAI / Anthropic / whoever Lovable was proxying. Add the keys as server-only env vars (never
VITE_*). - Email — replace Lovable's email service with Resend, Postmark or SendGrid. Configure SPF, DKIM and DMARC on the sending domain.
Common gotchas
Client-side routing 404s. Already covered above — vercel.json rewrites or Netlify _redirects fix it. Not an issue on Lovable's newer TanStack Start stack, which renders pages on the server.
Build fails on the host but passes locally. Almost always a missing or differently-named env var. Check that every VITE_* key on the host matches the local .env exactly.
OAuth callback URL mismatch. Symptom: "redirect_uri_mismatch" after login. Add the new domain to the OAuth provider's authorized redirect URIs.
Edge Functions stop working. They do not migrate with pg_dump. Deploy them separately to the new Supabase project using the Supabase CLI, and copy any secrets the functions need.
Stripe webhooks fail silently. The endpoint URL has to be updated in the Stripe dashboard. Don't forget the webhook signing secret if you generate a new endpoint.
Where to go next
The next guide in this pillar, "Your first real deploy: Supabase + Vercel from scratch," walks through Scenario A end to end — from connected GitHub repo to a public domain. It also covers the connection-pooling gotcha (port 6543 transaction-mode pooler) that bites serverless apps the moment they get real traffic.
Next in this pillar
How to migrate from Replit to your own hostingGet the next guide when it lands
One email on Sunday with new /learn guides, tool updates, and a couple of links worth reading.