Zero-config Vercel is a myth if you skip the interactive flow
I followed the docs. The build logs were green. Every URL returned 404.
The site is a small Next.js 16 + MDX blog — five static pages, two
posts. Locally, npm run build gave me 10/10 prerendered routes in
under a second. I wanted the project on Vercel before I lost the
afternoon, so I skipped the interactive wizard:
vercel project add eric-walters-site
vercel link --yes --project eric-walters-site
vercel deploy --prod --yes
Three commands, no prompts, perfect for a script. The deploy finished.
Vercel said ● Ready. I curled the URL.
404 https://eric-walters-site-c668...vercel.app/
404 https://eric-walters-site-c668...vercel.app/blog
404 https://eric-walters-site-c668...vercel.app/blog/hello-world
Not the auth page. Not a redirect. Plain 404, x-vercel-error: NOT_FOUND.
The build looked fine
I read the build log line by line. Next.js detected. Turbopack ran. TypeScript passed. Static pages generated. The summary block was identical to my local build:
Route (app)
┌ ○ /
├ ○ /blog
├ ● /blog/[slug]
│ ├ /blog/hello-world
│ └ /blog/shipping-the-simplest-blog-that-works
...
Build Completed in /vercel/output [24s]
Deploying outputs...
Deployment completed
Nothing was wrong. And yet nothing was reachable.
The smoking gun
vercel inspect on a deployment lists its Builds. Mine showed:
Builds
╶ . [0ms]
One build. Zero milliseconds. No artifacts. The Next.js step had clearly run — the log proved it — but Vercel wasn't routing any of the prerendered output to URLs.
That's the giveaway. The build ran. The routing layer never knew it was a Next.js project.
The fix is one line
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "nextjs"
}
Commit vercel.json, redeploy, every route returns 200. Wildcard SSL,
prerendered HTML, the whole picture.
What the wizard does that "automation" doesn't
When you run vercel link interactively in a fresh project, the CLI
detects your framework and writes the preset to your project settings.
You see the prompt. You tap enter. You forget it happened.
When you run vercel project add <name> non-interactively to keep a
script tidy, that step is skipped. The framework field is empty. The
build still runs — Vercel will obediently npm run build anything you
hand it — but the routing layer has no preset, so it serves the upload
as if it were a flat directory of static files. Your /.next/ output
is sitting right there. Nothing knows to ask for it.
The bigger pattern
Framework detection isn't magic. It's a setting. The wizard sets it for you. If you skip the wizard to keep your script clean, you inherit the wizard's defaults as your responsibility.
The thing that hurt was the failure mode. A loud error — "framework not detected, refusing to deploy" — would have cost me sixty seconds. Silent success with empty routing cost me forty minutes of staring at green checkmarks.
Any time a tool's happy path is "we'll figure it out for you," there is a setting underneath. Find the setting. Write it down. Then your script will keep working when the helpers go away.