DEV Community

Cover image for Deploying Lovable to Vercel — Cracked"
Jonathan Sherpa
Jonathan Sherpa

Posted on

Deploying Lovable to Vercel — Cracked"

🚀 Live demo: urljourney.vercel.app

Deploying Lovable + TanStack Start to Vercel kept throwing 404s and "No Output Directory" errors no matter what I tried. After hours of debugging, here's exactly what was wrong and the 2-file fix.

What Lovable Generates:
Lovable scaffolds projects using TanStack Start with Nitro as the server engine. This is a full-stack SSR framework, not a static site.
That's the root cause of every Vercel deployment problem.

Why It Fails Out of the Box
Problem 1: Vercel expects public/ but gets nothing
Vercel assumes a static site. TanStack Start + Nitro outputs a server bundle.
So you get:
No Output Directory named "public" found after the Build completed.

Problem 2: Setting outputDirectory: "dist/client" gives 404
Even after pointing Vercel to dist/client, every route returns 404. TanStack Start uses SSR — every route needs the Nitro server to handle it.
Without the server running, nothing works.

Problem 3: The rewrite trick doesn't work
Adding this to vercel.json:
json{ "source": "/(.*)", "destination": "/dist/server/server.js" }
...fails because dist/server/server.js is just an error logger, not the actual server entry.

Problem 4: Vercel functions runtime syntax is wrong
Trying "runtime": "nodejs20.x" throws:
Function Runtimes must have a valid version, for example now-php@1.0.0

Problem 5: Default Nitro preset is Cloudflare, not Vercel
The @lovable.dev/vite-tanstack-config comment in vite.config.ts says:

"nitro (build-only using cloudflare as a default target)"

A Vercel preset exists in Nitro but it's never used unless you explicitly set it. That's the real fix.

The Fix (2 Files)
Step 1: Update vite.config.ts
tsimport { defineConfig } from "@lovable.dev/vite-tanstack-config";

export default defineConfig({
tanstackStart: {
server: { entry: "server" },
},
nitro: {
preset: "vercel",
output: {
dir: ".vercel/output",
serverDir: ".vercel/output/functions/__server.func",
publicDir: ".vercel/output/static",
},
},
});
Step 2: Create vercel.json
json{
"buildCommand": "npm run build",
"outputDirectory": ".vercel/output",
"framework": null
}
Step 3: Build and verify locally
bashnpm run build
ls .vercel/output/

Should show: config.json functions/ static/ nitro.json

Step 4: Commit and push
bashgit add vite.config.ts vercel.json
git commit -m "fix: use nitro vercel preset with prebuilt output"
git push

Why This Works
Nitro's Vercel preset generates .vercel/output in Vercel's Build Output API v3 format:
.vercel/output/
config.json ← routing rules
static/ ← static assets served by CDN
functions/
__server.func/
index.mjs ← serverless function handling all SSR routes
.vc-config.json ← tells Vercel this is a Node.js function
Vercel natively understands this format and correctly wires up static asset serving + the serverless function. No manual rewrites needed.

Starting Fresh on Lovable?
Make these two changes before your first push and skip all of this pain.

Common Mistakes to Avoid

❌ Don't set outputDirectory: "dist" or "dist/client"
❌ Don't add manual rewrites in vercel.json
❌ Don't set framework: "vite" or any other framework
❌ Don't skip the output.dir override in vite.config.ts
✅ Always run npm run build locally first and verify .vercel/output/ exists before pushing

Top comments (0)