Vercel Essentials
Complete guide to deploying production-ready applications with custom domains on Vercel.
What is Vercel?
Vercel is a cloud platform for static sites and serverless functions that enables developers to deploy instantly and scale automatically.
Key Features:
Best For:
Prerequisites
Requirements
Before starting, ensure you have:
Installation
Install Vercel CLI
# ========== Install Globally ==========
npm install -g vercel
# ========== Verify Installation ==========
vercel --version
# ========== Login to Vercel ==========
vercel login
# Follow the prompts:
# 1. Choose authentication method (GitHub, GitLab, Email)
# 2. Verify in browser
# 3. Return to terminal
Expected Output:
> Success! GitHub authentication complete.
> Email: your.email@example.com
> Connected to: YourName
Quick Start
Deploy Your First Project
Step 1: Navigate to Your Project
# Go to your project directory
cd /path/to/your/project
# Example project structure:
# myapp/
# ├── package.json
# ├── next.config.js
# └── src/
# └── ...
Step 2: Deploy
# ========== One-Command Deploy ==========
vercel
# This will:
# 1. Detect your framework (Next.js, React, etc.)
# 2. Configure build settings automatically
# 3. Upload and build your project
# 4. Provide preview URL
Interactive Setup:
Vercel CLI 33.0.0
? Set up and deploy "~/myapp"? [Y/n] y
? Which scope do you want to deploy to? YourName
? Link to existing project? [y/N] n
? What's your project's name? myapp
? In which directory is your code located? ./
Auto-detected Project Settings (Next.js):
- Build Command: next build
- Output Directory: .next
- Development Command: next dev
? Want to override the settings? [y/N] n
🔗 Linked to yourname/myapp
🔍 Inspect: https://vercel.com/yourname/myapp/inspect
✅ Production: https://myapp.vercel.app [copied to clipboard]
Step 3: Visit Your Site
# Your app is now live at:
# https://myapp.vercel.app
# Preview the deployment
vercel open
Git Integration
Connect Repository
Via Vercel Dashboard:
Framework Preset: Next.js (auto-detected)
Root Directory: ./
Build Command: npm run build (auto-filled)
Output Directory: .next (auto-filled)
Install Command: npm install (auto-filled)
Automatic Deployments
Production Deployment:# Every push to main/master branch triggers production deployment
git add .
git commit -m "Update homepage"
git push origin main
# Vercel automatically:
# ✓ Detects push
# ✓ Builds project
# ✓ Deploys to production
# ✓ Updates https://myapp.vercel.app
Preview Deployments:
# Every push to other branches creates preview deployment
git checkout -b feature/new-header
git add .
git commit -m "Add new header"
git push origin feature/new-header
# Vercel creates unique preview URL:
# https://myapp-git-feature-new-header.vercel.app
# Also comments on PR with preview link
Environment Variables
Managing Environment Variables
Via Vercel Dashboard:
Via CLI:
# ========== Add Environment Variable ==========
vercel env add DATABASE_URL
# Interactive prompts:
? What's the value of DATABASE_URL? postgres://...
? Add to Development, Preview, and Production? Production
# ========== Add Multiple Variables ==========
vercel env add API_KEY
vercel env add STRIPE_SECRET_KEY
vercel env add REDIS_URL
# ========== Pull Environment Variables ==========
# Download env vars to local .env file
vercel env pull .env.local
# ========== List Environment Variables ==========
vercel env ls
Environment-Specific Variables
# ========== Development Only ==========
vercel env add DEV_API_URL
? Add to which environment? Development
# ========== Preview Only ==========
vercel env add STAGING_DATABASE
? Add to which environment? Preview
# ========== Production Only ==========
vercel env add PROD_API_KEY
? Add to which environment? Production
# ========== All Environments ==========
vercel env add ANALYTICS_ID
? Add to which environment? Development, Preview, Production
Using in Code
Next.js Example:
// ========== Server-side (API Routes, getServerSideProps) ==========
// Access with process.env
export default function handler(req, res) {
const apiKey = process.env.API_KEY;
const dbUrl = process.env.DATABASE_URL;
// Use variables...
}
// ========== Client-side ==========
// Must be prefixed with NEXT_PUBLIC_
export default function Component() {
const publicKey = process.env.NEXT_PUBLIC_STRIPE_KEY;
return <div>{/* Use public key */}</div>;
}
Environment Variables File Structure:
# .env.local (development)
DATABASE_URL=localhost:5432
API_KEY=dev_key_123
NEXT_PUBLIC_API_URL=http://localhost:3000
# .env.production (production - set in Vercel dashboard)
DATABASE_URL=production-db-url
API_KEY=prod_key_xyz
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
Custom Domain Setup
Add Custom Domain
Method 1: Via Dashboard
yourdomain.com
- Click "Add"
Method 2: Via CLI
# ========== Add Domain ==========
vercel domains add yourdomain.com
# ========== Add with Alias ==========
vercel alias set myapp.vercel.app yourdomain.com
DNS Configuration
Option A: Vercel Nameservers (Recommended)
Set these nameservers at your domain registrar:ns1.vercel-dns.com
ns2.vercel-dns.com
Benefits:
Option B: Custom DNS (A/CNAME Records)
For Root Domain (yourdomain.com):Type: A
Name: @
Value: 76.76.21.21
TTL: 3600
For Subdomain (www.yourdomain.com):
Type: CNAME
Name: www
Value: cname.vercel-dns.com
TTL: 3600
For Both (Root + www):
# Root domain
Type: A
Name: @
Value: 76.76.21.21
# WWW subdomain
Type: CNAME
Name: www
Value: cname.vercel-dns.com
SSL Certificate
Automatic SSL:
# Check certificate status
vercel certs ls
# View certificate details
vercel certs inspect yourdomain.com
Multiple Domains
# ========== Add Multiple Domains ==========
vercel domains add yourdomain.com
vercel domains add www.yourdomain.com
vercel domains add app.yourdomain.com
# ========== Set Production Domain ==========
vercel alias set myapp.vercel.app yourdomain.com --prod
# ========== Redirect www to non-www ==========
# Add redirect in vercel.json:
vercel.json:
{
"redirects": [
{
"source": "www.yourdomain.com/:path*",
"destination": "https://yourdomain.com/:path*",
"permanent": true
}
]
}
Configuration
vercel.json
Basic Configuration:
{
"version": 2,
"name": "myapp",
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
]
}
Build Settings
Custom Build Configuration:
{
"buildCommand": "npm run build",
"devCommand": "npm run dev",
"installCommand": "npm install",
"framework": "nextjs",
"outputDirectory": ".next"
}
Redirects and Rewrites
Redirects (301/302):
{
"redirects": [
{
"source": "/old-page",
"destination": "/new-page",
"permanent": true
},
{
"source": "/blog/:slug",
"destination": "/news/:slug",
"permanent": false
},
{
"source": "/old-site/:path*",
"destination": "https://newsitedomain.com/:path*",
"permanent": true
}
]
}
Rewrites (Proxying):
{
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://api.external.com/:path*"
},
{
"source": "/blog",
"destination": "https://blog.yourdomain.com"
}
]
}
Headers
Custom Headers:
{
"headers": [
{
"source": "/api/(.*)",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "*"
},
{
"key": "Access-Control-Allow-Methods",
"value": "GET, POST, PUT, DELETE, OPTIONS"
}
]
},
{
"source": "/(.*)",
"headers": [
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
}
]
}
]
}
Caching
Cache-Control Headers:
{
"headers": [
{
"source": "/static/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "/_next/static/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}
Serverless Functions
Creating API Routes
Next.js API Routes (Automatic):
// pages/api/hello.js
export default function handler(req, res) {
// Automatically deployed as serverless function
res.status(200).json({ message: 'Hello from Vercel!' });
}
// Available at: https://yourdomain.com/api/hello
Standalone Serverless Function:
// api/user.js
module.exports = (req, res) => {
const { userId } = req.query;
// Database query...
res.status(200).json({
userId,
name: 'John Doe'
});
}
// Available at: https://yourdomain.com/api/user?userId=123
Function Configuration
Timeout and Memory:
{
"functions": {
"api/heavy-computation.js": {
"memory": 3008,
"maxDuration": 60
},
"api/*.js": {
"memory": 1024,
"maxDuration": 10
}
}
}
Memory Options: 128, 256, 512, 1024, 3008 MB Max Duration: 10s (Hobby), 60s (Pro), 900s (Enterprise)
Performance Optimization
Image Optimization
Next.js Image Component:
import Image from 'next/image';
export default function Component() {
return (
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // Load immediately
quality={90} // Image quality (1-100)
/>
);
}
// Vercel automatically:
// ✓ Optimizes image format (WebP, AVIF)
// ✓ Resizes for device
// ✓ Lazy loads by default
// ✓ Serves from Edge CDN
Image Optimization Config:
// next.config.js
module.exports = {
images: {
domains: ['cdn.example.com', 'images.unsplash.com'],
formats: ['image/webp', 'image/avif'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
}
};
Edge Functions
Use Edge Runtime for Ultra-Low Latency:
// pages/api/edge.js
export const config = {
runtime: 'edge', // Run on Edge (not serverless)
};
export default async function handler(req) {
return new Response(
JSON.stringify({ message: 'Hello from the Edge!' }),
{
status: 200,
headers: {
'Content-Type': 'application/json',
},
}
);
}
// Benefits:
// ✓ <10ms cold start
// ✓ Runs globally at the edge
// ✓ Lower cost
Static Generation
Optimize Build with ISR (Incremental Static Regeneration):
// pages/blog/[slug].js
export async function getStaticProps({ params }) {
const post = await getPost(params.slug);
return {
props: { post },
revalidate: 60, // Regenerate page every 60 seconds
};
}
export async function getStaticPaths() {
return {
paths: [],
fallback: 'blocking', // Generate on first request
};
}
// Benefits:
// ✓ Fast page loads (pre-rendered)
// ✓ Automatic updates
// ✓ Reduced serverless costs
Deployment Workflows
Production Deployment
Manual Production Deploy:
# ========== Deploy to Production ==========
vercel --prod
# ========== Deploy with Custom Domain ==========
vercel --prod --target production
# ========== View Deployment Logs ==========
vercel logs myapp.vercel.app
# ========== Inspect Deployment ==========
vercel inspect https://myapp-abc123.vercel.app
Preview Deployments
Create Preview from Branch:
# ========== Deploy Current Branch as Preview ==========
vercel
# Gets unique URL like:
# https://myapp-git-feature-branch-username.vercel.app
# ========== Deploy Specific Branch ==========
git checkout feature/new-design
vercel
# ========== Share Preview ==========
vercel ls # List deployments
vercel open # Open latest in browser
Rollback
Rollback to Previous Deployment:
# ========== List Recent Deployments ==========
vercel ls
# Output:
# Age Deployment Status Duration
# 2m myapp-abc123.vercel.app Ready 1m 23s
# 1h myapp-def456.vercel.app Ready 1m 15s
# 2h myapp-ghi789.vercel.app Ready 1m 30s
# ========== Promote Previous Deployment ==========
vercel alias set myapp-def456.vercel.app yourdomain.com --prod
# ========== Instant Rollback ==========
vercel rollback https://myapp-def456.vercel.app
CI/CD Integration
GitHub Actions
Deploy on Push:
# .github/workflows/deploy.yml
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Vercel CLI
run: npm install -g vercel
- name: Pull Vercel Environment
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy to Vercel
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
Required Secrets:
VERCEL_TOKEN - Get from Vercel Dashboard → Settings → TokensVERCEL_ORG_ID - Found in .vercel/project.jsonVERCEL_PROJECT_ID - Found in .vercel/project.jsonGitLab CI
# .gitlab-ci.yml
deploy:
stage: deploy
image: node:18
script:
- npm install -g vercel
- vercel pull --yes --environment=production --token=$VERCEL_TOKEN
- vercel build --prod --token=$VERCEL_TOKEN
- vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN
only:
- main
Monitoring and Analytics
Vercel Analytics
Enable Analytics:
# Install package
npm install @vercel/analytics
# Add to your app
// pages/_app.js
import { Analytics } from '@vercel/analytics/react';
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<Analytics />
</>
);
}
View Analytics:
Metrics Available:
Speed Insights
# Install Speed Insights
npm install @vercel/speed-insights
# Add to your app
// pages/_app.js
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<SpeedInsights />
</>
);
}
Real User Metrics (RUM):
Log Drains
Stream Logs to External Service:
# ========== Add Log Drain ==========
vercel log-drain add https://logs.example.com
# Supported services:
# - Datadog
# - LogDNA
# - Logtail
# - Splunk
# - Custom HTTP endpoint
Security
Environment Protection
Password Protection:
# Via Dashboard:
# 1. Go to Project Settings
# 2. Click "Deployment Protection"
# 3. Enable "Vercel Authentication"
# 4. Or set password for deployment
Restrict Preview Deployments:
{
"github": {
"silent": true,
"autoJobCancelation": true
}
}
Security Headers
Production-Ready Security Headers:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
},
{
"key": "Permissions-Policy",
"value": "geolocation=(), microphone=(), camera=()"
},
{
"key": "Strict-Transport-Security",
"value": "max-age=31536000; includeSubDomains"
},
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
}
]
}
]
}
Troubleshooting
Common Issues
Build Failures:
# ========== View Build Logs ==========
vercel logs https://myapp-abc123.vercel.app
# ========== Check Build Settings ==========
vercel inspect https://myapp-abc123.vercel.app
# Common fixes:
# 1. Verify Node version in package.json
{
"engines": {
"node": ">=18.0.0"
}
}
# 2. Clear build cache
vercel --force
# 3. Check environment variables
vercel env ls
Domain Not Working:
# ========== Verify DNS Configuration ==========
nslookup yourdomain.com
# ========== Check Domain Status ==========
vercel domains ls
# ========== Remove and Re-add Domain ==========
vercel domains rm yourdomain.com
vercel domains add yourdomain.com
# ========== Wait for DNS Propagation ==========
# Can take up to 48 hours (usually <1 hour)
# Check status: https://www.whatsmydns.net/
Function Timeout:
# Increase timeout in vercel.json
{
"functions": {
"api/slow-function.js": {
"maxDuration": 30 // Increase to 30s
}
}
}
# Or upgrade plan for longer timeouts:
# Hobby: 10s
# Pro: 60s
# Enterprise: 900s
Large Bundle Size:
# Analyze bundle
npm install -g @next/bundle-analyzer
# In next.config.js:
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// config
});
# Run analysis
ANALYZE=true npm run build
# Common fixes:
# 1. Use dynamic imports
const Component = dynamic(() => import('./Component'));
# 2. Remove unused dependencies
npm uninstall unused-package
# 3. Use tree-shaking
# Import only what you need
import { specific } from 'library'; // Good
import * as library from 'library'; // Bad
Best Practices
Production Checklist
Before Going Live:
vercel env ls
# Verify all production secrets are set
vercel domains ls
# Ensure SSL is active
Performance Tips
1. Use Edge Functions for APIsexport const config = { runtime: 'edge' };
2. Optimize Images
import Image from 'next/image';
// Always use Next.js Image component
3. Enable ISR
export async function getStaticProps() {
return {
props: {},
revalidate: 60, // Regenerate every 60s
};
}
4. Configure Caching
{
"headers": [
{
"source": "/static/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
}
]
}
5. Use Compression
// next.config.js
module.exports = {
compress: true, // Enable gzip compression
};
Resources
Quick Reference Card
# ========== Deployment ==========
vercel # Deploy to preview
vercel --prod # Deploy to production
vercel --force # Force rebuild
# ========== Domains ==========
vercel domains add example.com # Add custom domain
vercel domains ls # List domains
vercel alias set old.vercel.app example.com
# ========== Environment Variables ==========
vercel env add VAR_NAME # Add env variable
vercel env ls # List variables
vercel env pull # Download to .env.local
# ========== Logs & Monitoring ==========
vercel logs # View logs
vercel inspect URL # Inspect deployment
vercel ls # List deployments
# ========== Management ==========
vercel rollback URL # Rollback deployment
vercel rm DEPLOYMENT # Remove deployment
vercel projects ls # List all projects
Next Steps
vercel---
Last Updated: 2026-04-20 Vercel CLI Version: 33+ Difficulty: Intermediate