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 (2)

Collapse
 
harjjotsinghh profile image
Harjot Singh

The deploy step is exactly where the "AI built my app" story usually hits its first wall, generation is smooth and then deploy fights you with config, env, and platform quirks no prompt warned you about. Cracking Lovable-to-Vercel is the unglamorous-but-essential part, and it's telling it needed a writeup at all. Generate-then-deploy should be one motion, not two separate fights. That's the gap I closed in Moonshift, the agent deploys it for you and verifies it actually runs, not just builds. What was the real sticking point, build config or env/secrets handling?

Collapse
 
jonathancodes365 profile image
Jonathan Sherpa

Hey Harjot,
It turned out to be a build config issue. During deployment I kept hitting errors and got pretty stuck for a bit . The framework setup wasn’t working properly out of the box. After digging in, I realized it wasn’t the code, just the build configuration causing all the trouble.

Yeah and i guess thanks about the info about Moonshift. I'll happily check it out.
Thanks.