Why Your AI-Generated Next.js App Works Locally but Dies on Vercel
Four hours of vibe coding, perfect local dev, then a Vercel build fails on a case-sensitive import the model "fixed" once. Here is how to catch it before the PR.
You vibe-coded for four hours. The dashboard renders. Auth works. The AI agent closed twelve todos. You push, open the PR, and Vercel replies with a red X: Module not found: Can't resolve './component'. You stare at the file list. The component exists — as Component.tsx. Somewhere in the diff, the model renamed the import to lowercase in one file and left the filename alone. macOS never complained. Linux did.
Local Next.js dev and Vercel production builds are not the same environment. next dev is forgiving, case-insensitive on macOS, and lazy about type-checking. Vercel runs next build on Linux with strict module resolution. AI coding agents amplify the gap because they edit import paths confidently and inconsistently. Run next build locally, verify env vars per Vercel environment, and scan for case drift before you push.
Why `next dev` lies to you
Development mode optimizes for speed, not parity. Hot reload, loose transpilation, and skipped routes mean you can ship a green localhost and still fail the production compiler. TypeScript errors that never block dev can hard-fail next build. Dynamic imports the model added without ssr: false can explode during static analysis. Tree-shaking exposes dead imports the dev server never evaluated.
| Check | `next dev` | Vercel `next build` |
|---|---|---|
| Filesystem | Often case-insensitive (macOS default) | Linux — case-sensitive module resolution |
| TypeScript | Errors may not block the dev server | Compile errors fail the deployment |
| Env vars | Reads .env.local on your machine | Uses Vercel project env per environment |
| AI import edits | Wrong casing may still resolve | Module not found — build stops |
The three failures we see most on AI Next.js repos
Button.tsx → button.tsx in one commit, updates half the imports, or "fixes" a path to ./utils/helpers when the folder is ./Utils/helpers. On macOS both resolve. On Vercel one does not. Grep for filename/import mismatches before push — do not trust the agent's last message saying "all imports updated."DATABASE_URL, NEXT_PUBLIC_* keys, and OAuth redirect URLs often work locally via .env.local but are missing or wrong in Preview. AI agents frequently hardcode fallbacks that mask the gap until build-time or runtime on Vercel."use client" in the wrong file, import server-only modules into client components, or leave unused exports that break under stricter bundling. Only next build exercises the full graph.A 10-minute pre-push ritual
- 1Does production build pass locally?Run
npm run buildorpnpm build. If it fails here, it will fail on Vercel. Fix before opening the PR. - 2Are import paths consistent with filenames?Search for renamed components. On macOS, run
git config core.ignorecase falsein the repo or use a Linux CI job to catch casing regressions early. - 3Are Preview env vars set?Open Vercel → Settings → Environment Variables. Confirm Preview has every key your feature reads, not just Production.
- 4Did TypeScript run in strict mode?Run
tsc --noEmitif your build script skips full type-check. AI-generated props andanycasts love to hide here.
Commands that mirror Vercel
# Match what Vercel runs
pnpm install --frozen-lockfile
pnpm build
# Optional: type-check explicitly
pnpm exec tsc --noEmitCatch failures before merge
Manual rituals help, but the durable fix is verifying the PR in an environment that behaves like Vercel — not re-running the same local dev command and hoping. Our guide on Vercel build failures on pull requests walks through running builds in ephemeral sandboxes, catching TypeScript and circular-import errors on the branch, and treating Preview deploys as a merge gate rather than a surprise. Read it at /vercel-build-failed-on-pull-request if you want the full playbook.
Critique can run sandbox verification against your PR: install, build, and test in an isolated Linux environment so case sensitivity and compile failures surface as review evidence before your reviewer ever opens the diff. That is especially useful when the author is an agent that does not remember yesterday's import path.