Deploy to Vercel
Deploy your Next.js application to Vercel.
Prerequisites#
- GitHub/GitLab/Bitbucket repository
- Vercel account
Quick Deploy#
Via Vercel Dashboard#
- Go to vercel.com/new
- Import your Git repository
- Configure environment variables
- Click Deploy
Via CLI#
1# Install Vercel CLI
2npm install -g vercel
3
4# Login
5vercel login
6
7# Deploy
8vercel
9
10# Deploy to production
11vercel --prodEnvironment Variables#
Required Variables#
1# Database
2DATABASE_URL=postgresql://...
3
4# Authentication (Clerk)
5NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
6CLERK_SECRET_KEY=sk_...
7
8# Payments (Stripe)
9STRIPE_SECRET_KEY=sk_...
10NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_...
11STRIPE_WEBHOOK_SECRET=whsec_...
12
13# App URL
14NEXT_PUBLIC_APP_URL=https://your-app.vercel.appSetting Variables via CLI#
1# Add a variable
2vercel env add DATABASE_URL
3
4# Add for specific environment
5vercel env add STRIPE_SECRET_KEY production
6
7# Pull variables to local .env
8vercel env pull .env.localProject Configuration#
1// vercel.json
2{
3 "framework": "nextjs",
4 "buildCommand": "prisma generate && next build",
5 "installCommand": "npm ci",
6 "regions": ["iad1"],
7 "crons": [
8 {
9 "path": "/api/cron/cleanup",
10 "schedule": "0 0 * * *"
11 }
12 ],
13 "headers": [
14 {
15 "source": "/api/(.*)",
16 "headers": [
17 {
18 "key": "Cache-Control",
19 "value": "no-store"
20 }
21 ]
22 }
23 ]
24}Database Setup (Neon)#
1. Create Neon Project#
1# Install Neon CLI
2npm install -g neonctl
3
4# Login
5neonctl auth
6
7# Create project
8neonctl projects create --name my-project2. Get Connection String#
neonctl connection-string --project-id <project-id>3. Configure Prisma#
1// prisma/schema.prisma
2datasource db {
3 provider = "postgresql"
4 url = env("DATABASE_URL")
5 directUrl = env("DIRECT_URL") // For migrations
6}4. Run Migrations#
# Local development
npx prisma migrate dev
# Production (in CI/CD)
npx prisma migrate deployCI/CD with GitHub Actions#
1# .github/workflows/deploy.yml
2name: Deploy to Vercel
3
4on:
5 push:
6 branches: [main]
7 pull_request:
8 branches: [main]
9
10env:
11 VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
12 VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
13
14jobs:
15 test:
16 runs-on: ubuntu-latest
17 steps:
18 - uses: actions/checkout@v4
19
20 - name: Setup Node.js
21 uses: actions/setup-node@v4
22 with:
23 node-version: '20'
24 cache: 'npm'
25
26 - name: Install dependencies
27 run: npm ci
28
29 - name: Run tests
30 run: npm test
31
32 - name: Run linting
33 run: npm run lint
34
35 deploy-preview:
36 needs: test
37 if: github.event_name == 'pull_request'
38 runs-on: ubuntu-latest
39 steps:
40 - uses: actions/checkout@v4
41
42 - name: Install Vercel CLI
43 run: npm install -g vercel
44
45 - name: Pull Vercel Environment
46 run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
47
48 - name: Build
49 run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
50
51 - name: Deploy Preview
52 id: deploy
53 run: |
54 url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
55 echo "url=$url" >> $GITHUB_OUTPUT
56
57 - name: Comment PR
58 uses: actions/github-script@v7
59 with:
60 script: |
61 github.rest.issues.createComment({
62 issue_number: context.issue.number,
63 owner: context.repo.owner,
64 repo: context.repo.repo,
65 body: '🚀 Preview: ${{ steps.deploy.outputs.url }}'
66 })
67
68 deploy-production:
69 needs: test
70 if: github.event_name == 'push' && github.ref == 'refs/heads/main'
71 runs-on: ubuntu-latest
72 steps:
73 - uses: actions/checkout@v4
74
75 - name: Install Vercel CLI
76 run: npm install -g vercel
77
78 - name: Pull Vercel Environment
79 run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
80
81 - name: Build
82 run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
83
84 - name: Run Migrations
85 env:
86 DATABASE_URL: ${{ secrets.DATABASE_URL }}
87 run: npx prisma migrate deploy
88
89 - name: Deploy Production
90 run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}Domain Configuration#
Add Custom Domain#
# Add domain
vercel domains add yourdomain.com
# Verify
vercel domains verify yourdomain.comDNS Configuration#
Add these records to your DNS provider:
| Type | Name | Value |
|---|---|---|
| A | @ | 76.76.21.21 |
| CNAME | www | cname.vercel-dns.com |
Edge Functions#
1// app/api/edge/route.ts
2export const runtime = 'edge';
3
4export async function GET(request: Request) {
5 return new Response('Hello from the Edge!', {
6 headers: {
7 'x-edge-region': request.headers.get('x-vercel-ip-country') || 'unknown',
8 },
9 });
10}Middleware#
1// middleware.ts
2import { NextResponse } from 'next/server';
3import type { NextRequest } from 'next/server';
4
5export function middleware(request: NextRequest) {
6 // Add geo-location headers
7 const response = NextResponse.next();
8
9 response.headers.set(
10 'x-user-country',
11 request.geo?.country || 'unknown'
12 );
13
14 return response;
15}
16
17export const config = {
18 matcher: '/api/:path*',
19};Monitoring#
Enable Analytics#
1// app/layout.tsx
2import { Analytics } from '@vercel/analytics/react';
3import { SpeedInsights } from '@vercel/speed-insights/next';
4
5export default function RootLayout({ children }) {
6 return (
7 <html>
8 <body>
9 {children}
10 <Analytics />
11 <SpeedInsights />
12 </body>
13 </html>
14 );
15}Error Tracking with Sentry#
npx @sentry/wizard@latest -i nextjsRollback#
# List deployments
vercel ls
# Rollback to specific deployment
vercel rollback <deployment-url>