React Router 7 · SSG Mode

SSG & SSR on Lovable

What works, what doesn't, and the gotchas you'll hit when building statically-rendered apps in Lovable.

Visit /about page

Rendering modes

CSR (default)

Client-side rendering

The Lovable default. Ships an empty HTML shell, hydrates in the browser.

Fully supported

SSG

Static Site Generation

Routes are pre-rendered at build time into static HTML. Best SEO, fastest TTFB.

This project

SSR

Server-Side Rendering

Renders HTML on every request. Requires a Node server runtime.

Not supported on Lovable

Lovable limitations

Lovable's preview & hosting infrastructure serves static assets only. Here's what that means in practice.

No Node.js runtime in production

Lovable hosting serves static files only — there's no server process to handle SSR requests at runtime.

No request-time data fetching

Loaders run at build time only. Per-user or per-request HTML cannot be generated server-side.

No server actions

Form actions and mutations must run client-side or via Lovable Cloud edge functions.

Routes must be enumerable at build

Dynamic routes need an explicit prerender list. You can't lazily generate /post/:slug for unknown slugs.

No middleware on the edge

Auth gates, redirects, and rewrites must happen client-side after hydration.

Environment variables are baked in

All env vars are inlined at build time. Rotating a secret requires a fresh build & deploy.

What works in SSG mode

Fully pre-rendered HTML

Every listed route ships as static HTML — great for SEO and crawlers.

Client-side routing & state

After hydration, the app behaves like a standard SPA with React Router.

Lovable Cloud integrations

Database, auth, storage, and edge functions all work — called from the client.

Build-time data loaders

Fetch from CMSs or APIs during build to embed content in the static output.

Gotchas we hit

Our solution

Deploy SSG output to Cloudflare Pages

Lovable hosting can't serve nested static routes like /about. We bypass that by building, copying build/client into dist, and pushing dist straight to Cloudflare Pages — which serves every index.html natively.

One-time setup

Install Wrangler and authenticate with Cloudflare.

npm install -D wrangler
npx wrangler login
npx wrangler pages project create my-app --production-branch main

Build, copy & deploy

Run after every change you want pushed live. Pulls latest from Lovable, pre-renders all routes, copies them into dist, and uploads.

# 1. Pull latest changes from Lovable (via GitHub sync)
git pull origin main

# 2. Build the static site (outputs to build/client)
npm run build

# 3. Copy build/client → dist (our deployable folder)
node scripts/copy-build.js
# or manually: rm -rf dist && cp -r build/client dist

# 4. Deploy dist to Cloudflare Pages
npx wrangler pages deploy dist --project-name=my-app

Optional: one-line npm script

Add to package.json so a single command rebuilds, copies, and deploys.

"scripts": {
  "deploy": "npm run build && node scripts/copy-build.js && wrangler pages deploy dist --project-name=my-app"
}

Then just run npm run deploy after each Lovable edit. Cloudflare's CDN serves /, /about, and any future pre-rendered routes with proper static HTML — no SPA fallback hacks needed.