D
Dev SOPKnowledge Base
Search
← All topics

GitHub + Vercel Deployment: Automated CI/CD for Next.js SaaS

Automated Next.js deployment via GitHub + Vercel — repo setup, Vercel project linking, GitHub Actions CI pipeline, environment variable management, preview deployments, and production rollback procedures.

deploymentgithubvercelcicdnextjsautomation
Agent trigger phrases: deploy to Vercel · GitHub Vercel deployment · Vercel CI/CD · Vercel GitHub Actions · preview deployment · Vercel rollback · production deploy

Overview

The standard deployment pipeline for Next.js SaaS: GitHub as source of truth, Vercel as host, GitHub Actions for CI gates. Preview deployments automatically on every PR.

Initial Setup

1. Create GitHub Repository

# Via GitHub CLI
gh repo create my-app --private --source=. --remote=origin --push

# Or manual
git init && git add -A && git commit -m "init"
git remote add origin https://github.com/username/my-app.git
git push -u origin main

2. Link Vercel Project

npm i -g vercel
vercel link     # follow prompts to connect to Vercel account and project

This creates .vercel/project.json with your project ID and org ID — needed for CI.

3. Connect GitHub to Vercel

In Vercel Dashboard → Project → Settings → Git:

  • Connect GitHub repository
  • Set production branch: main
  • Enable preview deployments for all branches

GitHub Actions CI Pipeline

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: "20"

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"
      - run: npm ci
      - run: npm run lint
      - run: npm run type-check
      - run: npm run build

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"
      - run: npm ci
      - name: Deploy to Vercel
        env:
          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
        run: |
          npx vercel pull --yes --environment=production --token=$VERCEL_TOKEN
          npx vercel build --prod --token=$VERCEL_TOKEN
          npx vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN

Required GitHub Secrets

In GitHub repo → Settings → Secrets and Variables → Actions:

| Secret | Where to get it | |--------|----------------| | VERCEL_TOKEN | vercel.com/account/tokens | | VERCEL_ORG_ID | .vercel/project.jsonorgId | | VERCEL_PROJECT_ID | .vercel/project.jsonprojectId |

Preview Deployments

Every PR automatically gets a preview URL from Vercel:

  • Format: https://my-app-git-branch-username.vercel.app
  • Shares production env vars (unless you configure separate preview vars)
  • Deleted automatically when PR is merged or closed

To set preview-specific env vars:

vercel env add DATABASE_URL preview
# or in Dashboard → Settings → Environment Variables → set Target: Preview

Branch-Based Environments

For staging vs production:

# In Vercel Dashboard → Settings → Git
# Add custom build settings per branch:
# Branch: staging → Build command: npm run build:staging
# Branch: main → Build command: npm run build

Or set branch-specific env vars:

vercel env add API_URL preview    # staging API
vercel env add API_URL production # production API

Environment Variable Sync

# Pull current production env to local
vercel env pull .env.local

# Add new var to specific targets
vercel env add NEW_SECRET production
vercel env add NEW_SECRET preview

# List all vars
vercel env ls

# Remove a var
vercel env rm OLD_SECRET production

Rollback

# List recent deployments
vercel ls

# Rollback to specific deployment
vercel rollback <deployment-url>

# Or via Dashboard: Deployments → find previous → Promote to Production

Custom Domain Setup

# Add domain
vercel domains add yourdomain.com

# Check DNS requirements
vercel domains inspect yourdomain.com

DNS records (add in your registrar):

  • Root: A 76.76.21.21
  • www: CNAME cname.vercel-dns.com

SSL certificate auto-provisioned after DNS propagates (usually < 5 min).

Monorepo Setup

For monorepos (multiple apps in one repo):

// vercel.json (in app subfolder)
{
  "buildCommand": "cd ../.. && npm run build --workspace=apps/web",
  "outputDirectory": "apps/web/.next",
  "installCommand": "npm install"
}

In Vercel Dashboard, set Root Directory to apps/web.

Build Cache

Vercel caches .next/cache between deployments. To invalidate:

vercel deploy --force   # bypasses cache

Health Check Endpoint

Add to src/app/api/health/route.ts:

export const dynamic = "force-dynamic";

export async function GET() {
  return Response.json({
    status: "ok",
    timestamp: new Date().toISOString(),
    version: process.env.VERCEL_GIT_COMMIT_SHA?.slice(0, 7) ?? "local",
  });
}

Vercel exposes VERCEL_GIT_COMMIT_SHA, VERCEL_URL, VERCEL_ENV automatically.