Minbook
KO

Lovable to Vercel — Frontend Migration Record

· 10 min read

Background

WICHI is a GEO (Generative Engine Optimization) SaaS. The frontend stack is Vite + React 18 + TypeScript + shadcn/ui. The backend runs on FastAPI, DB and Auth on Supabase, and server hosting on Railway. The initial frontend was built with Lovable, which also handled builds, deployment, and custom domain management.

This post documents the migration of frontend hosting from Lovable to Vercel — the reasons, planning, execution, issues encountered, and retrospective.

Pre-Migration Architecture

LayerTechnologyHosting
FrontendVite + React 18 + TS + shadcn/uiLovable
Backend APIFastAPI + PythonRailway
DB / AuthSupabase (PostgreSQL + Auth + RLS)Supabase Cloud
DNSCloudflare
Domainwichi.appCloudflare-managed

The key point: Lovable’s scope was limited to frontend build + hosting + custom domain. Backend, DB, Auth, and payments all operated independently from Lovable. This kept the migration scope contained and the difficulty low.


Why We Migrated

Lovable was valuable during initial prototyping. Prompt-based UI generation let us iterate fast, and it was instrumental in building WICHI’s first frontend version. Completing the frontend in 3 days during the Jocoding hackathon would not have been possible without Lovable.

The problems surfaced as we moved toward commercialization.

No Git-First Workflow

Lovable uses its own editor where you modify UI via prompts, then pushes changes to GitHub. The reverse direction is not supported — code modified directly on GitHub cannot be pulled into Lovable.

Problems this caused:

ProblemDescription
Branch conflictsLovable works on main, Claude Code works on dev. Merge conflicts were frequent
No PR-based reviewLovable pushes directly to main, bypassing PR-based code review
Opaque change historyLovable’s auto-generated commit messages are prompt summaries; change intent is unclear
One-way syncNo GitHub-to-Lovable sync; externally modified code is not reflected in Lovable’s editor

Even for solo development, PR-based workflows are valuable. Reviewing diffs before merging and verifying in a preview environment are basic safeguards against mistakes.

Limited Deployment Control

Production environments require fine-grained deployment configuration. Items that could not be directly managed on Lovable hosting:

  • Redirect rules: SPA client-side routing fallback rewrite — redirecting deep links like /dashboard/report/123 to index.html
  • Security headers: Customizing X-Frame-Options, Content-Security-Policy, Strict-Transport-Security
  • Cache policies: Static asset cache expiration, Cache-Control header control
  • Environment variable separation: Per-environment (Production, Preview, Development) variable management
  • Build command customization: Pre/post-build scripts, per-environment build flags

SPA rewrite was especially critical. Without redirect rules in a React Router SPA, refreshes and deep link access return 404. On Lovable hosting, this setting was not directly accessible — Lovable handled it internally, making debugging difficult when issues arose.

Dependency Lock-in

Lovable-specific dependencies remained in the codebase:

  • lovable-tagger: A tagging plugin for Lovable’s editor to identify components, registered as a Vite build plugin
  • Configuration code for Lovable editor integration

These dependencies are unnecessary outside Lovable and must be removed when migrating to another host. The deeper the dependencies grow, the higher the migration cost — removing them early was advantageous.

Cost Structure

Lovable subscription costs $25/month ($300/yr). Vercel’s Hobby plan is free, and at WICHI’s traffic level (static site, early stage), there was no chance of exceeding the free tier’s 100GB monthly bandwidth limit.

Cost savings was not the primary migration driver. Git-first workflow and deployment control were the main reasons; cost savings was a side benefit.

Decision Matrix

CriterionKeep LovableMigrate to VercelVerdict
WorkflowHybrid (Lovable + Claude Code)Git-first single toolVercel wins
Deploy controlLimitedFull control (vercel.json)Vercel wins
PR PreviewNot availableAuto-generated per PRVercel wins
RollbackManual restorationInstant rollback to previous deployVercel wins
Visual editorAvailableNot availableLovable wins
Migration riskNoneLow (standard Vite project)Acceptable
DowntimeNone1-5 min during DNS switchAcceptable

Lovable’s only advantage was the visual editor. At the commercialization stage, Git-first workflow and deployment control outweighed the visual editor’s value.


Migration Plan

Prerequisites Verified

  1. Code ownership: Full source in GitHub repo (vista-sphere-pro), buildable outside Lovable. Standard Vite project — npm run build confirmed working
  2. Lovable dependency scope: lovable-tagger registered as devDependency only; no Lovable-dependent runtime code
  3. Environment variable inventory: All frontend-referenced env vars cataloged — VITE_API_URL, VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, etc. Fallback values were hardcoded, so Vercel env setup was not strictly required but planned for environment separation
  4. DNS status: Confirmed wichi.app CNAME pointing to Lovable hosting in Cloudflare, checked TTL values

Execution Sequence

flowchart TD
    A["1. Connect repo to Vercel\n(no downtime)"] --> B["2. Configure env variables\n(no downtime)"]
    B --> C["3. Full test on Preview deploy\n(no downtime)"]
    C --> D{"Tests pass?"}
    D -->|Yes| E["4. Switch DNS CNAME\n(1-5 min downtime)"]
    D -->|No| F["Fix issues, retest"]
    F --> C
    E --> G["5. Update CORS settings\n(no downtime)"]
    G --> H["6. Remove Lovable-specific code\n(no downtime)"]
    H --> I["7. Verify and monitor"]

The core principle: limit downtime to the single DNS switch step. Complete staging deployment and full testing on Vercel first, then switch DNS — actual downtime is confined to DNS propagation time.

Downtime Minimization

PreparationDescription
Pre-lower TTLReduced CNAME TTL to 60 seconds the day before, ensuring rapid DNS cache expiration after switch
Staging verificationComplete functional testing on *.vercel.app domain before switching
Rollback planReverting DNS CNAME to Lovable provides instant rollback; delay Lovable subscription cancellation until switch is confirmed
Switch timingExecute during lowest-traffic window

Execution

Step 1: Vercel Project Setup

Connected the GitHub repository to Vercel with default settings:

  • Import Project on Vercel dashboard, select GitHub repo
  • Framework Preset: Vite (auto-detected)
  • Build Command: npm run build (default)
  • Output Directory: dist (default)
  • Root Directory: / (default)

Recognized as a standard Vite project with no special configuration needed.

Step 2: Environment Variables

Configured in Vercel’s Environment Variables section. Vercel separates environment variables across Production / Preview / Development.

VariableProductionPreviewDescription
VITE_API_URLProduction API URLStaging API URLBackend API endpoint
VITE_SUPABASE_URLSupabase URLSameSupabase project URL
VITE_SUPABASE_ANON_KEYAnon KeySameSupabase public key

Hardcoded fallback values meant the app would build and run without env vars set. We configured them explicitly for future environment separation — when a staging backend is added, only the Preview variables need updating.

Step 3: vercel.json Configuration

Set up SPA routing rewrite rules and security headers:

{
  "rewrites": [
    { "source": "/((?!api/).*)", "destination": "/index.html" }
  ],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "X-Content-Type-Options", "value": "nosniff" }
      ]
    }
  ]
}

The rewrites rule is essential. In a React Router SPA, direct navigation or refresh on paths like /dashboard or /report/123 returns 404 if no rewrite rule exists — Vercel cannot find a static file at that path. The rewrite redirects all routes to index.html, letting React Router handle client-side routing.

Step 4: Preview Deploy Testing

Vercel automatically creates a Preview deploy at *.vercel.app. Full functional testing was performed in this staging environment.

Test checklist:

  • Main page rendering
  • Login / signup flow
  • Dashboard access and data loading
  • Analysis execution (backend API calls)
  • Report viewing
  • Payment page access
  • Deep link direct access (SPA rewrite verification)
  • No 404 on page refresh
  • OG image loading
  • Mobile layout

An OG image issue was discovered at this stage — detailed in the Troubleshooting section.

Step 5: Remove lovable-tagger

npm uninstall lovable-tagger

Then removed the lovable-tagger plugin registration from vite.config.ts. Since it was a devDependency used only for component identification in Lovable’s editor, removal had no runtime impact.

Confirmed npm run build completed successfully after removal.

Step 6: DNS Switch

The most carefully managed step. Changed wichi.app’s CNAME record in Cloudflare from Lovable hosting to Vercel.

sequenceDiagram
    participant User as User
    participant CF as Cloudflare DNS
    participant L as Lovable Hosting
    participant V as Vercel

    Note over CF: Before: CNAME → Lovable
    User->>CF: wichi.app request
    CF->>L: CNAME resolves → Lovable
    L->>User: Response

    Note over CF: Execute CNAME change
    CF->>CF: CNAME → Vercel

    Note over CF: After: CNAME → Vercel
    User->>CF: wichi.app request
    CF->>V: CNAME resolves → Vercel
    V->>User: Response

    Note over CF: DNS propagation: ~1 min with 60s TTL

Execution steps:

  1. Add custom domain (wichi.app) in Vercel dashboard
  2. Note the CNAME target address Vercel provides
  3. Update wichi.app CNAME record to Vercel target in Cloudflare DNS
  4. Confirm domain verification and automatic SSL certificate issuance in Vercel dashboard
  5. Verify with curl -I https://wichi.app (confirm Vercel server headers)

Thanks to pre-lowered TTL (60 seconds), DNS propagation completed in approximately 2 minutes.

Step 7: CORS Update

After DNS switch, update the backend (FastAPI) CORS settings:

ChangeBeforeAfter
Add allowed domain*.vercel.app (for Preview deploys)
Keep allowed domainwichi.appwichi.app (unchanged — domain itself did not change)
Remove allowed domainLovable domain

Since the wichi.app domain itself did not change, production CORS remained unaffected. The only addition needed was *.vercel.app for Vercel Preview deploy URLs, enabling staging API calls from PR-generated preview URLs.

Step 8: Verification

Post-migration verification:

  • https://wichi.app accessible
  • SSL certificate valid (Let’s Encrypt, Vercel auto-issued)
  • All major pages and features functional
  • OG images loading correctly
  • Backend API calls working (no CORS issues)
  • Google Search Console site access confirmed
  • GA4 event collection confirmed

Troubleshooting

OG Image Dependency

Symptom: OG images broken on Preview deploy. URLs shared on social media showed no image preview.

Cause: OG image was hosted on Lovable’s GCP Storage. The HTML <meta property="og:image"> tag referenced a Lovable GCP bucket URL directly.

# Before: Lovable GCP Storage URL
<meta property="og:image" content="https://storage.googleapis.com/lovable-uploads/..." />

Canceling Lovable’s subscription could invalidate this URL. External service dependency for OG images means vulnerability to that service’s outages or policy changes.

Fix: Moved the OG image to the project’s public/ directory.

# After: Self-hosted
<meta property="og:image" content="https://wichi.app/og-image.webp" />

Placing the image in public/og-image.webp makes Vercel serve it as a static asset automatically — no external dependency.

This was missed during pre-migration analysis. Lovable’s GCP Storage dependency is invisible at the code level — it only surfaces by inspecting HTML meta tag URLs one by one.

SPA Rewrite Missing

Symptom: 404 errors on direct URL access or page refresh after Vercel deployment.

Cause: No rewrite rules in vercel.json. Lovable handled SPA hosting rewrites internally, so no explicit configuration existed in the codebase.

Fix: Added SPA rewrite rules to vercel.json — all requests except API paths redirect to index.html.

Environment Variable Fallbacks

Discovery: Hardcoded fallback values existed for environment variables:

const API_URL = import.meta.env.VITE_API_URL || "https://api.wichi.app"

This means Vercel works without explicit env var configuration in production. But it is also a problem: Preview environments call the production API too, breaking staging/production isolation.

Not an immediate issue since no separate staging backend exists yet, but when staging is added, these fallback values must be removed to enforce Vercel environment variable usage.


Before and After Comparison

Deployment Pipeline

flowchart LR
    subgraph Before["Before: Lovable"]
        direction TB
        L1["Edit via prompts in Lovable editor"] --> L2["Lovable builds"]
        L2 --> L3["Auto-deploy"]
        L4["Edit code via Claude Code"] --> L5["git push"]
        L5 --> L6["Not recognized by Lovable"]
        L6 --> L7["Manual sync required"]
    end

    subgraph After["After: Vercel"]
        direction TB
        V1["Edit code"] --> V2["git push / Create PR"]
        V2 --> V3["Vercel auto-build"]
        V3 --> V4["Preview Deploy created"]
        V4 --> V5["Review then merge"]
        V5 --> V6["Production auto-deploy"]
    end

During the Lovable era, two tools (Lovable editor + Claude Code) modified code through separate paths with incomplete synchronization. After the Vercel migration, all code changes flow through a single Git-based pipeline.

Feature Comparison

FeatureLovableVercel
Deploy triggerManual from Lovable editorgit push = auto-deploy
PR PreviewNot availableAuto-generated per PR with unique URL
Deploy historyLimited visibility in LovablePer-commit tracking in dashboard, build log access
RollbackManual restoration (difficult)One-click rollback to previous deploy version
Env var managementLimitedProduction / Preview / Development separation
Build configInternal to Lovable, limited customizationFull control via vercel.json
Security headersNot configurableConfigurable via vercel.json headers
CDNLovable’s ownVercel Edge Network (global)
Domain SSLLovable-managedLet’s Encrypt auto-issued and renewed
Build logsHard to accessReal-time build log streaming

Workflow Comparison

ScenarioLovableVercel
UI component editPrompt in Lovable editor → manual pushEdit code → PR → Preview verify → merge
Deploy error foundManual fix in Lovable editor, redeployInstant rollback in Vercel, then fix
New feature developmentHybrid Lovable(main) + Claude Code(dev)Single tool (Claude Code) on feature branch
Env var changeLovable settings page (limited)Vercel dashboard, independent per environment
Build failure debugLovable internal error (limited info)Full error stack in Vercel build logs

The most impactful change: PR = Preview Deploy. Verifying code changes in a real deployment environment before merging is a safety net that prevents mistakes even in solo development. Vercel’s Preview Deploy runs in an environment identical to production, catching environment-related issues before they reach users.


Migration Checklist

A comprehensive checklist generalized for similar migrations.

Pre-Migration

  • Full source code in GitHub, buildable externally
  • Platform-specific dependency list identified (lovable-tagger, etc.)
  • Environment variable inventory complete
  • Current DNS configuration verified (CNAME target, TTL)
  • Rollback plan established

Execution

  • Connect repo to Vercel, configure basics
  • Set environment variables (per-environment separation)
  • Write vercel.json (rewrites, headers)
  • Full test on Preview deploy
  • Remove platform-specific dependencies (lovable-tagger)
  • Migrate OG image to local hosting
  • Pre-lower DNS TTL (60 seconds)
  • Switch DNS CNAME (Cloudflare → Vercel)
  • Confirm SSL certificate issuance

Post-Migration

  • Update backend CORS settings
  • Full production test
  • Verify GA4 event collection
  • Verify Search Console access
  • Update README deployment docs
  • Cancel previous platform subscription

Issue Log

TimingIssueSeverityResolutionTime Spent
Preview testOG image brokenMediumMoved image to local public/15 min
Preview testDeep link 404HighAdded vercel.json rewrite rules10 min
Post-DNS switchSSL certificate pendingLowVercel auto-issued, ~1 min wait1 min
Post-migrationCORS error on Preview deploysMediumAdded *.vercel.app to backend5 min

Time Spent

The entire migration took roughly half a day.

TaskDuration
Vercel project setup + env vars15 min
vercel.json configuration10 min
Preview deploy testing30 min
lovable-tagger removal + build verification10 min
OG image migration15 min
DNS switch + propagation wait15 min
CORS update5 min
Production verification30 min
Documentation update20 min
Total~2.5 hours

Testing and verification consumed the most time. Actual code changes were minimal — mostly configuration file edits and external service updates (DNS, CORS). DNS propagation was fast thanks to the pre-lowered TTL.


Retrospective

When Lovable Is Still the Right Tool

Leaving Lovable does not mean Lovable is a bad tool. Tools serve their intended purposes.

ScenarioLovable FitReason
Hackathon / PrototypingHighPrompt-to-UI speed is unmatched. Optimal for building a working frontend in 3 days
Design explorationHighRapidly try and compare multiple UI variations
Non-developer MVP creationHighBuild a deployable frontend without writing code
Production hostingLowLimitations in deploy control, env separation, rollback, PR Preview
Long-term maintenanceLowNo Git-first workflow, platform-specific dependencies

For WICHI, Lovable provided clear value in the “0 to 1” phase. Building the first frontend version during a 3-day hackathon would have been much harder without it.

When to Graduate from No-Code/Low-Code Platforms

General criteria for transitioning from no-code/low-code platforms to traditional hosting — not Lovable-specific:

If 3 or more of the following apply, it is time to evaluate migration:

  • PR-based code review is needed — team of 2+ or solo developer who needs change history tracking
  • Direct deployment configuration control is needed — redirects, security headers, cache policies, env var separation
  • Rollback capability is needed — ability to instantly revert to a previous version when post-deploy issues arise
  • Platform cost is unreasonable compared to alternatives — free or low-cost hosting provides equivalent functionality
  • Platform-specific dependencies are accumulating — proprietary SDKs, plugins, and config code growing in the codebase
  • Integration with other tools is needed — CI/CD, monitoring, A/B testing, external service connectivity

Lessons Learned

Acknowledge the limits of pre-migration analysis. The OG image’s Lovable GCP dependency was missed during planning. Code-level dependencies are findable by searching package.json and import statements, but implicit dependencies like external URLs embedded in HTML meta tags or CDN paths are easily overlooked.

Zero downtime is unrealistic, but minimization is achievable. True zero downtime is virtually impossible in DNS-involving migrations. But pre-lowering TTL, pre-validating staging, and having a rollback plan can reduce downtime to minutes.

Platform transitions are cheaper when done early. Platform-specific dependencies accumulate over time. When migration becomes necessary, acting quickly minimizes cost. WICHI’s Lovable dependencies were limited to lovable-tagger and an OG image URL — enabling completion in half a day. Had dependencies deepened further, it would have taken much longer.


How Daily Work Changed After Migration

TaskBeforeAfter
Component editLovable editor → prompt → pushEdit code → PR → Preview verify → merge
DeployManual trigger in Lovable editorgit push = automatic. No extra steps
Deploy failureCheck Lovable error message (limited info)Full error stack in Vercel build logs
Emergency rollbackManual restoration (time-consuming)Select previous deploy in Vercel dashboard → instant rollback
New feature verificationLocal testing onlyPreview URL on PR creation for real-environment verification

PR Preview is valuable even for solo development. It catches “works locally but breaks in deployment” issues before merge. Vercel’s Preview Deploy runs in a production-identical environment, surfacing environment-related problems early.

Share

Related Posts

Comments