--- name: vercel-deployments description: Deploy frontend and full-stack apps on Vercel with previews, edge functions, environment promotion, and production guardrails. Use when shipping Next.js, SvelteKit, or static sites with zero-config CI/CD. license: MIT metadata: author: devops-skills version: "1.0" --- # Vercel Deployments Ship web apps quickly with preview environments and managed edge infrastructure. ## When to Use This Skill Use this skill when: - Deploying Next.js, SvelteKit, Nuxt, or static sites - Setting up preview environments for every PR - Configuring edge functions and serverless APIs - Managing environment variables across preview/production - Setting up custom domains and redirects ## Prerequisites - Node.js 18+ - Vercel account (free tier works for personal projects) - Git repository (GitHub, GitLab, or Bitbucket) ## Quick Start ```bash # Install CLI npm i -g vercel # Login and link project vercel login vercel link # Deploy to preview vercel # Deploy to production vercel --prod # Pull environment variables locally vercel env pull .env.local ``` ## Project Configuration ```json // vercel.json { "framework": "nextjs", "buildCommand": "npm run build", "outputDirectory": ".next", "installCommand": "npm ci", "regions": ["iad1", "sfo1", "cdg1"], "headers": [ { "source": "/api/(.*)", "headers": [ { "key": "Cache-Control", "value": "no-store" }, { "key": "X-Content-Type-Options", "value": "nosniff" } ] }, { "source": "/(.*)", "headers": [ { "key": "X-Frame-Options", "value": "DENY" }, { "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains" } ] } ], "redirects": [ { "source": "/blog/:slug", "destination": "/posts/:slug", "permanent": true } ], "rewrites": [ { "source": "/api/v1/:path*", "destination": "https://api.example.com/:path*" } ] } ``` ## Environment Variables ```bash # Add environment variables vercel env add DATABASE_URL production vercel env add DATABASE_URL preview vercel env add NEXT_PUBLIC_API_URL production # List all env vars vercel env ls # Pull to local .env.local vercel env pull .env.local # Remove an env var vercel env rm SECRET_KEY production ``` ### Environment Separation Pattern ```bash # Production — real credentials vercel env add DATABASE_URL production <<< "postgresql://prod-host:5432/app" vercel env add STRIPE_SECRET_KEY production # Preview — staging/test credentials vercel env add DATABASE_URL preview <<< "postgresql://staging-host:5432/app" vercel env add STRIPE_SECRET_KEY preview # Use test mode key # Development — local values vercel env add DATABASE_URL development <<< "postgresql://localhost:5432/app" ``` ## Edge Functions ```typescript // app/api/geo/route.ts — Edge API route (Next.js App Router) import { NextRequest } from 'next/server'; export const runtime = 'edge'; export function GET(request: NextRequest) { const country = request.geo?.country || 'US'; const city = request.geo?.city || 'Unknown'; return Response.json({ country, city, region: request.geo?.region, timestamp: new Date().toISOString(), }); } ``` ```typescript // middleware.ts — Edge middleware for auth/redirects import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { // Block non-US traffic from admin if (request.nextUrl.pathname.startsWith('/admin')) { if (request.geo?.country !== 'US') { return NextResponse.redirect(new URL('/blocked', request.url)); } } // Add security headers const response = NextResponse.next(); response.headers.set('X-Request-Id', crypto.randomUUID()); return response; } export const config = { matcher: ['/admin/:path*', '/api/:path*'], }; ``` ## GitHub Actions Integration ```yaml # .github/workflows/preview.yml name: Vercel Preview on: pull_request jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm run lint - run: npm run test - name: Deploy to Vercel Preview id: deploy run: | npm i -g vercel URL=$(vercel --token ${{ secrets.VERCEL_TOKEN }} --yes) echo "url=$URL" >> "$GITHUB_OUTPUT" - name: Comment PR with preview URL uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `Preview deployed: ${{ steps.deploy.outputs.url }}` }); ``` ## CLI Commands Reference ```bash # Deployments vercel # Deploy to preview vercel --prod # Deploy to production vercel rollback # Rollback last production deploy vercel promote # Promote preview to production # Domains vercel domains add example.com vercel domains ls vercel certs ls # Logs vercel logs vercel logs --follow # Project management vercel project ls vercel project rm # Inspect deployment vercel inspect ``` ## Production Guardrails - Require preview checks before merge (GitHub branch protection) - Separate preview and production environment variables — never share API keys - Use branch protection with required deployment status checks - Monitor function duration and cold start behavior in Vercel Analytics - Set spend limits in Vercel dashboard to prevent cost surprises - Enable Vercel Firewall for DDoS and bot protection - Use `vercel.json` headers for security (CSP, HSTS, X-Frame-Options) ## Monitoring & Analytics ```bash # Enable Speed Insights in Next.js npm install @vercel/speed-insights # Enable Web Analytics npm install @vercel/analytics ``` ```typescript // app/layout.tsx import { Analytics } from '@vercel/analytics/react'; import { SpeedInsights } from '@vercel/speed-insights/next'; export default function RootLayout({ children }) { return ( {children} ); } ``` ## Troubleshooting | Issue | Solution | |-------|---------| | Build fails | Check `vercel logs`, verify Node.js version in `engines` field | | Env vars missing | Run `vercel env pull`, check variable scope (preview vs production) | | Edge function timeout | Edge has 30s limit; move heavy work to serverless (no `runtime = 'edge'`) | | Cold starts slow | Use edge runtime where possible, reduce bundle size | | Domain not working | Check DNS propagation, verify `vercel domains` configuration | ## Related Skills - [github-actions](../../../devops/ci-cd/github-actions/) — Automated deployment gates - [cloudflare-pages](../../cloudflare/cloudflare-pages/) — Alternative edge hosting - [ssl-tls-management](../../../security/network/ssl-tls-management/) — Custom certificate setup