A glowing app icon launching from a futuristic digital cube platform with sparks and fragments
AI, Business, cloud

Migrating from Lovable: Steps to Self-Host Your App

Lovable is a remarkable product.
You describe what you want. It builds it. You ship in hours instead of weeks.
That’s genuinely impressive, and I’ve used it to launch things I would have otherwise shelved for “when I have more time.”

But “when I have more time” eventually arrives.

And when it does, you start asking different questions:

“What happens if they change pricing?”
“Can I run this on my own infrastructure?”
“Where exactly does my data live?”

Those aren’t paranoid questions. They’re the right questions.
This post is about answering them — practically, with actual steps you can follow.

Why Leave Lovable?

Before anything else: you might not need to.

Lovable is a solid platform. If your app is a side project, an internal tool, or an early-stage product with low traffic, staying there is probably the right call. The cost of self-hosting is real — you own the ops now.

But there are situations where moving makes clear sense:

Cost at scale
Lovable’s pricing is per-project and per-usage.
Once you’re past early stage, running your own stack on a VPS or cloud provider is often ~3–5x (or more) cheaper.

Data residency
Some industries (healthcare, finance, defense) require you to control where data lives.
“It’s on Lovable’s servers” isn’t an acceptable answer in those conversations.

Customization ceiling
Lovable generates clean React/Supabase apps, but it has opinions. When you need a specific architecture, edge functions, a custom auth flow, or native mobile builds outside their defaults — you hit the wall.

Ownership
At some point, the code is yours.
You should be able to run it. Anywhere.

What You’re Actually Working With

Lovable generates a specific stack.
Understanding it before you touch anything is important.

A typical Lovable export looks like this:

  • Frontend: React (Vite), TypeScript, Tailwind CSS, shadcn/ui components
  • Backend/DB: Supabase (Postgres, Auth, Storage, Edge Functions)
  • Routing: React Router
  • State/Fetching: TanStack Query, sometimes Zustand
  • Deployment: Previously Lovable’s own hosting; they now push to GitHub and can connect to Netlify/Vercel

The code is real – It’s readable. There’s no magic proprietary runtime you need to reverse-engineer.
That’s the good news.

The less-good news:
Supabase is tightly integrated.
The app talks to a Supabase project by project URL and anon key. If you want to move away from Supabase (or self-host Supabase), that’s a bigger migration than just moving the frontend.

For most people: keep Supabase, move the frontend.
That’s the path of least resistance.

Step 1: Export Your Code

First things first.

Go to your Lovable project → click the GitHub button → connect your GitHub account → push the project.

You now have a real repository with real code. Clone it locally:

git clone https://github.com/your-username/your-lovable-project.git
cd your-lovable-project
npm install

Before you do anything else, make sure it runs locally:

npm run dev

If it opens in your browser and works: great. If it doesn’t: check your .env file (more on that in a moment).

Step 2: Understand Your Environment Variables

This is where most people get stuck.
Lovable injects environment variables automatically. When you run this yourself, you’re responsible for them.

Create a .env file in your project root:

VITE_SUPABASE_URL=https://your-project-ref.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key-here

Find these in your Supabase dashboard → Project Settings → API.

One important thing: never commit your .env to git. Add it to .gitignore immediately if it isn’t already there.

echo ".env" >> .gitignore

For production deployments, you’ll set these as environment variables in your hosting provider’s dashboard — not as files checked into the repo.

Step 3: Build for Production

npm run build

This generates a dist/ folder. Everything in there is static — HTML, CSS, JavaScript bundles. No Node.js server required to serve it.

You can host this on:

  • Vercel (easiest, free tier is generous)
  • Netlify (similar to Vercel, excellent DX)
  • Cloudflare Pages (fastest globally, very generous free tier)
  • A plain VPS with Nginx (most control, most work)

My default recommendation:
1. Cloudflare Pages for public-facing apps
2. VPS + Nginx if you want full control and have ops comfort.

Step 4: Deploy to Cloudflare Pages (Recommended)

If you just want it running fast with zero infrastructure overhead:

  1. Push your repo to GitHub (done in Step 1)
  2. Go to Cloudflare Pages → Create Project → Connect GitHub
  3. Select your repo
  4. Set build settings:
  • Build command: npm run build
  • Build output directory: dist
  1. Add your environment variables (VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY)
  2. Deploy

Done.

Your app is live on a Cloudflare CDN edge network in ~2 minutes, with automatic deployments on every push to main.

Step 5: Deploy to a VPS (The “Real Self-Hosting” Path)

For maximum control, run it on your own server.
I recommend fly.io (so you don’t need to install/maintain anything – just build your webapp in docker) or Hetzner — the value is absurd compared to AWS or GCP for basic hosting needs.

Provision your server, then SSH in:

ssh root@your-server-ip

Install Nginx:

apt update && apt install nginx -y

Create your site directory and copy the build:

mkdir -p /var/www/myapp
# From your local machine:
scp -r dist/* root@your-server-ip:/var/www/myapp/

Or better: set up a CI/CD pipeline that does this automatically on push.

Configure Nginx:

server {
listen 80;
server_name yourdomain.com;
root /var/www/myapp;
index index.html;
# This is critical for React Router — all paths serve index.html
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets aggressively
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}

Save to /etc/nginx/sites-available/myapp, symlink it:

ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

Add HTTPS with Let’s Encrypt:

apt install certbot python3-certbot-nginx -y
certbot --nginx -d yourdomain.com

Certbot auto-renews.
You’re done.

Step 6: The Native App Situation

If your Lovable app has a native mobile wrapper — this is where things get interesting.

Lovable has been expanding into native capabilities using Capacitor under the hood. If your project has native bindings, you’ll find a capacitor.config.ts in the project root.

The good news:
Capacitor is open-source and you own the workflow entirely.

For iOS:

npm run build
npx cap sync ios
npx cap open ios

This opens Xcode with your project. From there, you archive and submit to the App Store exactly like any other iOS app. You need an Apple Developer account ($99/year).

For Android:

npm run build
npx cap sync android
npx cap open android

This opens Android Studio. Build → Generate Signed Bundle/APK → distribute via Play Store or sideload directly.

The webview URL matters.

In development, Capacitor talks to localhost. In production, you need to point it at your live web app. Edit capacitor.config.ts:

import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.yourcompany.yourapp',
appName: 'Your App',
webDir: 'dist',
server: {
// Remove this for production — use bundled assets instead
// url: 'http://localhost:5173',
androidScheme: 'https'
}
};
export default config;

For most native apps, you want the webDir approach — the built assets are bundled directly into the native app binary. This means offline support works and you don’t depend on your web server being up for the app to function.

Run npx cap sync after every build to keep the native project in sync with your web build.

Step 7: Handling Supabase at Scale

You moved the frontend. Supabase is still doing the backend work.

For most apps: that’s fine. Supabase is genuinely good infrastructure.

But if you want to self-host Supabase too (for compliance, cost, or curiosity), they publish an official Docker Compose setup:

git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .env
# Edit .env with your secrets
docker compose up -d

This runs the full Supabase stack — Postgres, GoTrue (auth), PostgREST, Realtime, Storage, and Studio — on your own hardware.

It’s more maintenance burden. But it’s also complete ownership.

My honest take: use Supabase managed unless you have a specific reason not to.
Their managed infrastructure is well-run and the pricing is reasonable until you’re at serious scale.

Step 8: Setting Up CI/CD So You Don’t Do This Manually Again

Manually copying files to a server is how you get paged at 2am because you forgot a step.

Here’s a minimal GitHub Actions workflow that builds and deploys on every push to main:

# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'npm'
- name: Install & Build
run: |
npm ci
npm run build
env:
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
- name: Deploy to Server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "dist/*"
target: "/var/www/myapp"
strip_components: 1

Add your secrets in GitHub → Settings → Secrets and variables → Actions.

Push to main. It deploys automatically.
That’s the whole loop.

The Checklist Before You Pull the Plug on Lovable

Don’t cancel your Lovable plan until you’ve verified all of this:

  • [ ] App runs locally with npm run dev
  • [ ] Production build succeeds with npm run build
  • [ ] All environment variables are set correctly in production
  • [ ] Supabase Row Level Security policies are configured (don’t rely on Lovable having set these correctly)
  • [ ] Auth flows work end-to-end (sign up, sign in, sign out, password reset)
  • [ ] Any storage/file uploads work against your Supabase bucket policies
  • [ ] Edge functions (if any) are deployed to Supabase
  • [ ] Custom domain is pointing to your new hosting
  • [ ] HTTPS is working
  • [ ] Native builds open and run correctly (iOS Simulator + Android Emulator at minimum)
  • [ ] CI/CD pipeline deploys successfully from a test push

Run through this list twice.
Yep… On the second time you’ll catch something you missed.

What I’ve Learned From Doing This

Lovable is excellent for getting to a working product quickly.
Self-hosting is excellent for owning what you built.

These aren’t in conflict — they’re a sequence.

Build fast on Lovable.
Validate the idea.
Get real users.
Then, when the infrastructure costs start mattering or the compliance questions start arriving, migrate.

The migration is maybe 4–6 hours of focused work for a typical app.
That’s worth doing on a quiet Sunday, not during a crisis.

Do it before you need to.

Questions? Find me on GitHub


Discover more from Ido Green

Subscribe to get the latest posts sent to your email.

Standard

Leave a comment