Tutorial

How to deploy a Next.js app on Vercel with a custom domain and SSL (2026)

Deploying a Next.js app on Vercel takes five minutes. Doing it the right way — custom domain, www redirect, SSL that auto-renews, preview deploys configured cleanly — takes thirty. Here's the whole walkthrough.

May 16, 202611 min readCruxBit Team

Vercel is the path of least resistance for Next.js in 2026. The default deploy flow is genuinely a one-click affair, but the difference between "working" and "working cleanly" is a handful of small choices around domains, redirects, environment scoping and preview deploys. This guide walks the whole thing, from a fresh Next.js repo to a live yourdomain.com with auto-renewing SSL, preview URLs for every PR, and the gotchas we've watched teams trip over.

Assumed stack

Next.js 16 (App Router, Turbopack) on Node 20+, pushed to GitHub, deployed to Vercel. The same flow works with GitLab, Bitbucket, and pnpm / npm / yarn / bun.

1. The big picture

What you're wiring up
   Git push                      Build & deploy                    DNS
   ─────────                     ─────────────                    ─────
   git push origin main  ──►   Vercel detects ──►  Production    A / CNAME
                                build & deploy      *.vercel.app   ↓
                                                                Cloudflare /
                                                                Route 53 /
                                                                Namecheap /
                                                                  your DNS

   git push origin feat  ──►   Preview deploy ──►  Preview        (auto SSL
                                per branch          deploy-…       on both)
                                                    .vercel.app)

2. Prerequisites

  • A Next.js project that runs locally (pnpm dev works)
  • A GitHub / GitLab / Bitbucket account with the repo pushed
  • A free Vercel account (Hobby plan is enough for almost every small project)
  • A domain you control (Namecheap, Cloudflare Registrar, GoDaddy, Route 53, etc.)

3. Quick sanity-check your project locally

bash
pnpm install
pnpm build       # Make sure production build succeeds locally first
pnpm start       # Smoke-test the prod bundle on http://localhost:3000

Why bother building locally?

90% of failed Vercel deploys are failures the build would have caught locally. Five minutes here saves a red commit and a Slack message.

4. Push to a Git remote

bash
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin git@github.com:you/your-repo.git
git push -u origin main

5. Import the project on Vercel

  1. 1Go to vercel.com/new
  2. 2Click "Import" next to your repo (you may need to grant access to the GitHub org first)
  3. 3Vercel auto-detects Next.js — leave Framework Preset as "Next.js"
  4. 4Root Directory: leave as ./ unless your app lives in a monorepo subfolder
  5. 5Build Command / Output Directory: leave defaults (Next.js handles these)
  6. 6Add environment variables (see step 6) BEFORE clicking Deploy. Adding them after means re-deploying
  7. 7Click Deploy. First build typically takes 60–120 seconds

6. Environment variables — get the scoping right

Vercel has three environments: Production, Preview, and Development. You can scope each variable to any subset.

  • DATABASE_URL → different value in Production vs Preview (use a staging DB for previews — never let previews write to prod data)
  • NEXT_PUBLIC_* → exposed to the browser. Public keys, analytics IDs, NEVER secrets
  • NEXTAUTH_SECRET / JWT_SECRET → use different secrets per environment
  • Pull them locally with npx vercel env pull .env.local after installing vercel CLI
bash
# Install the Vercel CLI
pnpm add -g vercel

# Link the local repo to the Vercel project
vercel link

# Pull env vars (scoped to the current env, default: development)
vercel env pull .env.local

7. Add your custom domain

  1. 1Project Settings → Domains → Add
  2. 2Type your apex (e.g. cruxbit.in). Vercel will also offer to add the www variant — accept
  3. 3Vercel will show you the DNS records to add at your registrar

DNS — the two records that matter

Recommended DNS
Type    Host    Value                 TTL    Purpose
────    ────    ─────                 ───    ───────
A       @       76.76.21.21           Auto   Apex → Vercel
CNAME   www     cname.vercel-dns.com  Auto   www → Vercel

(Optional: AAAA on @ if you want IPv6 — Vercel publishes the value)

Apex with CNAME (Cloudflare, Route 53)

If your registrar/DNS supports CNAME-flattening or ALIAS records on the apex (Cloudflare, Route 53, DNSimple), use that instead of the A record. It auto-resolves to the freshest Vercel edge IP. On Namecheap/GoDaddy plain DNS, stick with the A record above.

8. SSL — Vercel does this for you

Once DNS propagates (usually 1–15 minutes, sometimes up to 24 hours), Vercel automatically issues a Let's Encrypt certificate for both yourdomain.com and www.yourdomain.com. No copying keys, no Certbot, no renewals to forget. It auto-rotates every 90 days.

If the certificate doesn't issue within an hour, check the Domains panel — Vercel will show a yellow warning if it can't validate (usually a missed DNS record or a CAA record blocking Let's Encrypt).

9. Pick a primary — apex or www

Pick one canonical host and redirect the other. Vercel makes this a one-click in the Domains panel: tick "Redirect to" next to whichever you want as the primary. We default to yourdomain.com (apex) as the primary in 2026 — shorter, looks cleaner in social previews.

10. Preview deployments — they're free, set them up properly

Every PR gets a unique preview URL like your-repo-git-feat-x.vercel.app automatically. Three things to wire up:

  1. 1Comment bot — Vercel posts the preview URL on each PR by default. Make sure your repo's GitHub App access is granted (Project Settings → Git)
  2. 2Preview-only env vars — point at staging Postgres, sandbox Stripe, test Razorpay, etc. (step 6)
  3. 3Preview password (Pro plans) — useful for client preview URLs you don't want public

11. next.config.ts — small tweaks worth making

next.config.ts
typescript
import type { NextConfig } from "next";

const config: NextConfig = {
  // Strip console.* in production builds (except errors)
  compiler: {
    removeConsole: process.env.NODE_ENV === "production"
      ? { exclude: ["error", "warn"] }
      : false,
  },

  // If your app serves external images, allowlist their hosts
  images: {
    remotePatterns: [
      { protocol: "https", hostname: "cdn.cruxbit.in" },
    ],
  },

  // Permanent redirects (e.g. old marketing URLs)
  async redirects() {
    return [
      { source: "/services/old-page", destination: "/services",
        permanent: true },
    ];
  },
};

export default config;

12. Vercel-specific files worth knowing

  • .vercelignore — same syntax as .gitignore, excludes files from the deploy upload (rarely needed)
  • vercel.json — for rewrites, redirects, headers and cron jobs not supported by next.config.ts (e.g. setting a max duration on a serverless function)
  • middleware.ts — runs on every request at the edge. Great for redirects, auth gating, A/B tests
vercel.json (optional)
json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functions": {
    "src/app/api/long-job/route.ts": {
      "maxDuration": 60
    }
  },
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Frame-Options", "value": "SAMEORIGIN" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
      ]
    }
  ]
}

13. Common gotchas

  • Adding env vars after deploy — you must redeploy for them to take effect. Use the "Redeploy" button on the latest commit
  • Different env var values for Preview vs Production — easy to miss. Audit Settings → Environment Variables after onboarding
  • API routes hitting Vercel's serverless timeout — Hobby plan caps at 10s, Pro at 60s by default. For long jobs, use a queue or the new Vercel Functions (Fluid Compute) plan
  • Big public/ assets blowing past the 100MB serverless bundle limit — move large media to a CDN or Vercel Blob
  • Caching headaches on dynamic routes — set export const dynamic = "force-dynamic" on routes that must not be cached, and read the Next.js caching docs (they changed meaningfully in Next 15+)
  • Locale-prefixed URLs returning 404 after a rename — preview deploys keep old slugs; force a fresh production deploy after changing routing

14. Once you're live — a 10-minute hardening pass

  1. 1Add a 404 page (app/not-found.tsx) that matches your brand — looks unprofessional with the default
  2. 2Add app/sitemap.ts and app/robots.ts (Next.js generates them at build time)
  3. 3Set metadata with proper Open Graph image (app/opengraph-image.tsx)
  4. 4Wire [[how-to-add-ga4-to-nextjs-2026|Google Analytics 4]] for traffic
  5. 5Add error monitoring (Sentry via @sentry/nextjs) — free tier is generous
  6. 6Submit your sitemap in Google Search Console

TL;DR

  • Push to Git, import on Vercel, set env vars BEFORE first deploy
  • Add custom domain in Settings → Domains; add the A and CNAME records at your registrar
  • Vercel issues + auto-renews Let's Encrypt SSL — you do nothing
  • Pick apex or www as primary; redirect the other
  • Use Preview env vars to point previews at staging data
  • Add 404, sitemap, robots, analytics, error monitoring after going live

Deploying a more complex setup — monorepo, custom build pipeline, multiple environments, multi-region functions — and want a second pair of eyes? Drop us a line and we'll send back a candid take.

#Next.js#Vercel#Deployment#DNS#Tutorial

Have a project?

Building something we've just written about?

Drop us a line. We respond within 24 hours with a candid, no-pressure take on whether we're the right partner.