Deploy fixes for AI-built apps
The works-locally-breaks-in-production class of failure is where AI-built apps spend the most post-deploy hours. Lovable, Bolt, v0, Cursor, and Claude Code each ship apps whose localhost path is smooth and whose production path is not — env vars set only in Development scope, edge runtime directives added silently, case-sensitive imports that pass on macOS and fail on Linux, Tailwind content globs that miss the /app directory, hydration mismatches from Date.now() on the server. Per the 2025 Stack Overflow Developer Survey, 66% of developers say AI tools increase deploy frequency — and post-deploy incident rate is up commensurately. This hub groups every deploy-time fix on the site into one navigable index.
By Hyder ShahFounder · Afterbuild LabsLast updated 2026-04-18
- 9
- Indexed deploy fixes
- 95%
- Map to 5 root causes
- 20m
- Typical 500 diagnosis
- 100%
- Root-cause fix
What this hub covers
This hub covers any failure that appears at or after deploy to Vercel and is not specific to auth, payments, or the database layer. Vercel 500 errors, white screens, build failures with empty logs, env-var scoping, hydration mismatches in production, edge runtime incompatibilities, missing Tailwind styles, broken next/image, and CORS errors that only show up on the production domain. The primary surface is Next.js App Router 16 on Vercel, but most failure modes apply to any Node-runtime deploy.
What this hub does notcover: Stripe webhook failures that happen to surface after deploy (see the payments hub), OAuth redirect URI misconfigurations (auth hub), or Supabase RLS drift (database hub). The boundary is: if the same failure would happen on a staging domain with correct config, it belongs here; if the failure is specific to a third-party integration, it belongs in that category's hub.
The most common failures
Six deploy-category failure modes appear in every rescue intake for AI-built apps. Each is a predictable consequence of the gap between the generator's localhost assumptions and Vercel's production environment.
- Env var undefined in production. The most common single cause of post-deploy 500s and white screens. Missing
NEXT_PUBLIC_prefix on client-side values, wrong Vercel environment scope, or a stale cached build. See env variables not loading Vercel, 500 error after deploy, and white screen after Vercel deploy. - Edge runtime on a Node-dependent route.
export const runtime = "edge"added by Bolt or v0 templates. The route imports Stripe, node:crypto, a Postgres driver, or Buffer — edge runtime strips each. Remove the directive; stay on the default Node runtime. - Hydration mismatch. Server-rendered HTML does not match client-rendered output.
Date.now(),Math.random(),window, orlocalStorageaccess during render. Production swallows the diff and sometimes blanks the page. See Next.js hydration error in production. - Case-sensitive import failure on Linux. macOS and Windows are case-insensitive; Linux build servers are not.
import Button from "./button"resolves fine locally, fails on Vercel with a module-not-found that the build log sometimes reports without a stack. See App works locally, not in production. - Tailwind JIT purging production classes. Dynamic class strings (
bg-${color}-500) are invisible to the static scanner. Missing content paths intailwind.config. See Tailwind styles not applying in production. - Build exits with no error. Non-zero exit, empty log. TypeScript strict mode, missing
generateStaticParams, or a package-lock version mismatch. See Vercel build failed with no error.
Indexed deploy fixes
Each link is a root-cause walkthrough: exact error string, the commit shape that produced it, the fix, and the regression test.
- § FX-01→ READ
500 error after deploy
Vercel returns 500 on routes that worked in preview. Env var scope, runtime flag, or a missing build dependency.
- § FX-02→ READ
White screen after Vercel deploy
Build passes, page loads blank. NEXT_PUBLIC_ env var undefined in the bundle or a hydration error swallowed by the production build.
- § FX-03→ READ
Vercel build failed with no error
Build exits non-zero, logs show nothing. TypeScript strict, missing prerender param, or a silent package-lock mismatch.
- § FX-04→ READ
App works locally, not in production
Localhost perfect, production broken. Case-sensitive imports, missing env vars, or an edge runtime directive added silently.
- § FX-05→ READ
env variables not loading Vercel
process.env.X is undefined after deploy. Missing NEXT_PUBLIC_ prefix, wrong environment scope, or a stale cached build.
- § FX-06→ READ
Next.js hydration error in production
Text content did not match. SSR mismatch from Date.now, window access, or a localStorage read on first paint.
- § FX-21→ READ
Next.js Image not loading
next/image returns 400 or 404 on production. Missing remotePatterns, wrong loader, or a blob URL the optimizer cannot fetch.
- § FX-22→ READ
Tailwind styles not applying in production
Styles work in dev, missing in prod. Content path misses a template, JIT purged a dynamic class, or a nested config mismatch.
- § FX-15→ READ
CORS error in production only
Access-Control-Allow-Origin missing on live domain. Add the origin to Supabase/Clerk allow-list or return it from Next.js middleware.
Shared root causes
Deploy-category symptoms differ, but their root causes cluster into four patterns. Rule each out before diving into the stack trace.
- Localhost vs production environment drift. Env vars scoped only to Development, case-insensitive filesystem, Node version mismatch, or a
.env.localthat was never moved to Vercel. - Runtime directive added silently.
export const runtime = "edge"from a Bolt template,export const dynamic = "force-static"from a v0 refactor, or an inherited config that changes the execution environment without a visible diff. - SSR/CSR boundary assumptions. Browser-only code (
window,localStorage,Date.now) called during server render. The AI tool tested the page client-side where the globals exist; the server never has them. - Build-time assumptions about source paths. Tailwind content globs, Next.js
images.remotePatterns, TypeScript path aliases — each one has to match the actual source tree on the build server, not the developer's local machine.
Prevention checklist
Merge these before the next production deploy. Each one replaces a silent production failure with a loud build failure.
- Validate
process.envat module load with a zod schema. A missing required var should fail the build, not the first production request. - Set every env var in Vercel → Settings → Environment Variables in all three scopes (Development, Preview, Production) unless there is a specific reason to differ.
- Remove every
export const runtime = "edge"directive unless the route has been verified to use only edge-compatible APIs. - Lock Node version in
package.json"engines" and match Vercel's project setting. - Run a case-sensitive filesystem check in CI (
git config core.ignorecase falselocally;eslintpluginimport/no-unresolved). - Write every browser-only global access inside a
useEffector a component guarded by"use client"with a typeof window check. - Audit
tailwind.config.tscontent paths and add dynamic class strings to the safelist or rewrite them as full literal names. - Add every remote image host to
next.config.jsimages.remotePatternsbefore first use. - Add a smoke test that hits
/,/api/health, and one auth-protected route on every preview deploy. - Review the Vercel function log after every deploy for 5 minutes; a caught early 500 is a 20-minute fix, an uncaught one is a support ticket.
When to bring in a developer
Most deploy fixes are 20-minute patches once the root cause is identified from the function log. Bring in a developer when: the build fails with no log output and no reproduction on the local machine, the deploy succeeds but the site intermittently returns 500 under no observable pattern, a revert to a known-good commit also fails, or the build is reaching memory or time limits on Vercel's infrastructure.
Escalate immediately if the site has been broken for more than six hours and the founder is burning credit or losing signups. Book the Emergency Triage for a single deploy-blocking incident, or the Break the Fix Loop service if the app has been in a cycle of revert-and-redeploy for more than 48 hours.
Related clusters
For the stack-wide walkthrough of Vercel deploy failures, read the Vercel deploy fix stack hub. For platform-specific deploy failures, see the per-builder problem pages: Lovable preview works, prod broken, Bolt deployment failing, Bolt preview works, prod broken, Cursor deploy failing, Cursor local works, prod broken, v0 deploy to Vercel, and Replit deployment not sticking. When the deploy symptom chains into another category, continue at the payment fix hub, the auth fix hub, or the database fix hub.
Production down right now?
Book the 48-hour emergency triage for one deploy-blocking fix, fixed price, refund if we miss. Or the free diagnostic for a written rescue-vs-rewrite recommendation.