Deploying Next.js on Vercel: A Practical Guide
A hands-on walkthrough for shipping a Next.js app to Vercel — connecting Git, configuring environment variables, understanding preview deployments, and avoiding the usual production gotchas.
What you'll learn
- ✓How Vercel maps Git branches to deployment environments
- ✓Where to put environment variables and which scope to pick
- ✓How preview URLs and production aliases work together
- ✓Common build failures and how to debug them quickly
Prerequisites
- •A Next.js project pushed to GitHub, GitLab, or Bitbucket
What and Why
Vercel is the platform built by the same team that builds Next.js, and it treats every Next.js feature as a first-class citizen. You get serverless functions, edge runtime, image optimization, ISR caching, and a CDN without writing infrastructure code. The trade-off is convention: Vercel decides where your code runs, and if you fight it, you will lose. Knowing the conventions up front means you spend more time shipping and less time debugging the dashboard.
Mental Model
Think of a Vercel project as three layers stacked on a Git repo. The bottom layer is the build — Vercel clones your branch, runs next build, and captures the output. The middle layer is the deployment, an immutable snapshot of that build at a unique URL like my-app-7x82h.vercel.app. The top layer is the alias, a friendly URL such as my-app.vercel.app or your custom domain that points at one specific deployment. Promoting to production is just retargeting the alias; rolling back is the same operation in reverse.
Hands-on Example
Start by importing your repo from the Vercel dashboard. Pick the framework preset (Next.js is auto-detected), set the root directory if your app lives in a monorepo subfolder, and add environment variables. For a typical app you might add DATABASE_URL (scoped to Production), NEXT_PUBLIC_API_URL (all environments), and STRIPE_SECRET_KEY (Production + Preview).
Push a commit to your main branch. Vercel builds it, produces a deployment URL, and aliases your production domain to that deployment. Now open a pull request from a feature branch — Vercel automatically builds a preview deployment and posts the URL as a PR comment. Each push to that branch creates a new immutable preview.
git push origin main
|
v
[Vercel webhook] -> clone repo
|
v
[Build] next build -> .next/ output (functions + static)
|
v
[Deployment] my-app-abc123.vercel.app (immutable)
|
v
[Promote] alias my-app.com -> abc123
^
|
feature branch push -> preview deployment
my-app-feat-xyz.vercel.app
(does NOT touch production alias) Locally, install the CLI with npm i -g vercel, run vercel link to connect the folder, and use vercel env pull .env.local to download the dev environment variables. Now next dev runs against the same config as production.
Common Pitfalls
The first trap is environment variable scope. A variable added only to Production will be missing in Preview, and your PR previews will crash with cryptic undefined errors. When in doubt, add the variable to all three scopes (Production, Preview, Development) and override per-scope only when values truly differ.
Second, server-only secrets prefixed with NEXT_PUBLIC_ get bundled into the client. If you accidentally name a secret NEXT_PUBLIC_STRIPE_SECRET_KEY, it ships to every browser. Audit prefixes before deploying.
Third, build caching can mask issues. Vercel caches node_modules and .next/cache between builds. If a dependency change does not seem to take effect, redeploy with the “Clear build cache” toggle in the dashboard.
Fourth, function size limits. The default Node serverless function has a 50 MB compressed size limit. Large dependencies (puppeteer, ffmpeg binaries) will fail at deploy time. Move heavy work to a separate worker or use the Edge runtime where possible.
Best Practices
Pin your Node version in package.json with an engines field so the build environment matches local. Add a vercel.json only when you need to override defaults — headers, redirects, or per-function configuration — and keep it minimal. Use the Vercel GitHub integration to require a successful Preview before merging; this gives you a real environment per PR. Set up the Vercel Analytics package for real-user performance data once traffic warrants it. Finally, treat the production alias as a switch: keep at least one known-good deployment in history so a rollback is a single click.
Wrap-up
Vercel rewards teams that lean into the conventions. Push to a branch, get a preview; merge to main, get production; promote or roll back by retargeting an alias. Once the environment-variable scoping and the build-cache behavior click, the platform mostly gets out of your way and lets you ship Next.js features as fast as you can write them.
Related articles
- Next.js Next.js Middleware and the Edge Runtime
What Next.js middleware actually is, how it runs on the Edge, what you can and cannot do there, and the patterns that work in production.
- Next.js Error Boundaries in the Next.js App Router
How error.tsx, global-error.tsx, and not-found.tsx work in the Next.js App Router — when each one fires, how segments isolate failures, and patterns for recovery and observability.
- Next.js Next.js Edge Config Tutorial: Ultra-Low-Latency Reads
Use Vercel Edge Config to serve feature flags, redirects, and small config blobs from the edge with single-digit-millisecond reads — when to use it, how it differs from KV, and a working example.
- Next.js Next.js Environment Variables and Secrets
Learn how Next.js loads environment variables, when they are exposed to the browser, and how to keep secrets out of your client bundle.