skills/vercel-deployment/SKILL.md
Deploy Next.js applications to Vercel with proper configuration. Use when setting up deployment, configuring environment variables, edge functions, or troubleshooting builds. Activates for deployment issues, environment setup, and Vercel configuration.
npx skillsauth add curiositech/windags-skills vercel-deploymentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Deploy and configure Next.js applications on Vercel with expert-level decision-making for database selection, environment configuration, and production readiness.
DECISION: What database should I use?
├── Development/Prototyping (< 1000 users expected)
│ ├── No external dependencies needed → SQLite (local file)
│ └── Need live data sharing → Turso (SQLite edge)
│
├── Production (> 1000 users, team collaboration)
│ ├── Simple schema, global edge performance → Turso
│ ├── Complex queries, existing Postgres knowledge → Vercel Postgres
│ ├── MySQL ecosystem, PlanetScale branching → PlanetScale
│ └── Self-managed, specific requirements → External Postgres/MySQL
│
└── High Scale (> 100k users)
├── Global read performance critical → Turso + caching
├── Complex analytics, reporting → Vercel Postgres
└── Cost optimization priority → External managed database
DECISION: Where should this environment variable be set?
├── Contains secrets (API keys, database passwords)
│ ├── Used in build process → Build-time env var
│ └── Used at runtime → Runtime env var (Vercel Dashboard only)
│
├── Client-side access needed
│ ├── Public data (API endpoints) → NEXT_PUBLIC_ prefix
│ └── Should be server-only → Regular env var (no prefix)
│
└── Environment-specific values
├── Same across all environments → All scopes (Production + Preview + Development)
├── Different per environment → Separate values per scope
└── Preview testing only → Preview scope only
DECISION: Build failing - what's the root cause?
├── Build timeout (>10min Hobby, >45min Pro)
│ ├── Large bundle size → Analyze bundle, enable splitting
│ ├── Slow dependencies → Cache node_modules, optimize installs
│ └── Complex build step → Split into multiple functions
│
├── Memory errors (OOM)
│ ├── Build process → Reduce concurrent processes
│ └── Runtime → Increase function memory allocation
│
├── Environment variables missing
│ ├── Build-time vars → Set in Vercel project settings
│ └── Runtime vars → Check function logs, verify scope
│
└── Dependency issues
├── Version conflicts → Lock to specific versions
└── Missing peer deps → Install explicitly
| Anti-Pattern | Detection Rule | Symptom | Diagnosis | Fix | |--------------|---------------|---------|-----------|-----| | Env Var Leakage | Client bundle contains server secrets | API keys visible in browser devtools | Used server env var without server-side check | Prefix with NEXT_PUBLIC_ only for public data, verify server-only vars | | Build Timeout Spiral | Build time >15min, getting worse | Builds fail intermittently with timeout | Inefficient build process, growing dependencies | Enable build cache, analyze bundle size, split large operations | | Edge Function Bloat | Edge function >5KB, slow cold starts | Preview deployments slow to respond | Imported server-only libraries in edge runtime | Move to serverless functions, use edge-compatible libraries only | | Database Connection Pool Exhaustion | "too many connections" errors in production | 500 errors during traffic spikes | Each serverless function creates new connection | Implement connection pooling, use database proxy | | Preview Environment Pollution | Production data appears in preview deployments | Test data mixed with real user data | Same database URL for preview and production | Separate DATABASE_URL for preview scope, use staging databases |
Situation: Deploy Next.js chat application with SQLite database to production
Expert Decision Process:
Database Selection (Decision Tree Navigation):
Environment Variable Configuration:
# Production scope
TURSO_DATABASE_URL=libsql://app-prod.turso.io
TURSO_AUTH_TOKEN=eyJ... (production token)
SESSION_SECRET=prod-32-char-secret
# Preview scope
TURSO_DATABASE_URL=libsql://app-staging.turso.io
TURSO_AUTH_TOKEN=eyJ... (staging token)
SESSION_SECRET=preview-32-char-secret
Build Configuration:
// vercel.json
{
"buildCommand": "npm run build && npm run db:push",
"regions": ["iad1", "fra1"], // Multi-region for chat
"functions": {
"src/app/api/chat/route.ts": {
"maxDuration": 30 // Longer timeout for AI responses
}
}
}
Validation Steps Taken:
npm run db:test-connectionNovice would miss: Setting different database URLs for preview vs production, optimizing regions for chat performance, longer timeout for AI endpoints.
Expert catches: Environment separation, performance implications of database location, build optimization for chat features.
Deploy only when ALL conditions are met:
vercel env pull && npm run db:testtime npm run buildANALYZE=true npm run build_next/static/ for API keys.vercel/output/functions/ sizesDO NOT use this skill for:
Delegate to other skills:
tools
Building resilient distributed systems with circuit breakers, retries with full-jitter exponential backoff, retry budgets (per-request 3-attempt + per-client 10% ratio per Google SRE), deadline propagation, and the cascading-failure math (4 layers × 3 retries = 64x amplification). Grounded in Resilience4j, Microsoft Cloud Patterns, AWS Architecture Blog (Marc Brooker), and Google SRE Book.
testing
Designing HTTP cache headers that work correctly across browsers, CDNs, and shared proxies — `Cache-Control` directives per RFC 9111, `stale-while-revalidate` and `stale-if-error` per RFC 5861, the Vary header for varying responses, and surrogate keys for tag-based purging. Grounded in IETF RFCs and Cloudflare/Fastly docs.
development
Use when designing or fixing a Content Security Policy on a real site, choosing between nonce-based and hash-based CSP, adding strict-dynamic, debugging "Refused to execute inline script" errors, deploying CSP in report-only mode first, configuring report-to / report-uri, or auditing an existing policy for unsafe-inline / unsafe-eval / wildcards. Triggers: "CSP blocks legitimate inline script", strict-dynamic, nonce-{RANDOM}, sha256-{HASH}, object-src none, base-uri none, frame-ancestors, Trusted Types, X-Content-Security-Policy obsolete, report-only vs enforced. NOT for general HTTP security headers (HSTS, COOP/COEP), Trusted Types deep dive, CORS configuration, or building a WAF.
tools
Choosing and operating an HTTP API versioning strategy that doesn't break clients — Stripe's date-based pinned versions, the Deprecation/Sunset header pair (RFC 9745 + RFC 8594), URI vs header vs media-type approaches, and the version-transformer pattern. Grounded in Stripe's published architecture and IETF RFCs.