toolchains/javascript/frameworks/nextjs/SKILL.md
Next.js environment variable management with file precedence, variable types, and deployment configurations. Use when configuring Next.js applications, managing environment-specific settings, or deploying to Vercel/Railway/Heroku.
npx skillsauth add bobmatnyc/claude-mpm-skills nextjs-env-variablesInstall 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.
Complete guide to Next.js environment variable management.
my-nextjs-app/
├── .env # Shared defaults (committed)
├── .env.local # Local secrets (gitignored)
├── .env.development # Development defaults (committed)
├── .env.development.local # Local dev overrides (gitignored)
├── .env.production # Production defaults (committed)
├── .env.production.local # Production secrets (gitignored)
├── .env.test # Test environment (committed)
└── .env.example # Documentation (committed)
Next.js loads files in this order (higher = higher precedence):
.env.$(NODE_ENV).local (e.g., .env.production.local).env.local (not loaded in test environment).env.$(NODE_ENV) (e.g., .env.production).envExample: In production, if DATABASE_URL is defined in both .env and .env.production.local, the value from .env.production.local wins.
Exposed to the browser. Must prefix with NEXT_PUBLIC_.
# .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_ANALYTICS_ID=UA-123456789
NEXT_PUBLIC_SITE_NAME=My Awesome Site
NEXT_PUBLIC_ENABLE_FEATURE_X=true
Access in code:
// Works in both client and server
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
// Usage in components
export default function MyComponent() {
return <div>API: {process.env.NEXT_PUBLIC_API_URL}</div>;
}
⚠️ Security Warning: NEVER put secrets in NEXT_PUBLIC_* variables!
# ❌ WRONG - Secret exposed to browser
NEXT_PUBLIC_API_SECRET=sk_live_abc123
# ✅ CORRECT - Secret only on server
API_SECRET=sk_live_abc123
Only available in server-side code (API routes, getServerSideProps, etc.).
# .env.local
DATABASE_URL=postgres://localhost:5432/mydb
JWT_SECRET=super-secret-jwt-key-do-not-expose
STRIPE_SECRET_KEY=sk_live_abc123
SMTP_PASSWORD=email-password-here
Access in code:
// ✅ Works in API routes
export default async function handler(req, res) {
const dbUrl = process.env.DATABASE_URL;
// Use dbUrl...
}
// ✅ Works in getServerSideProps
export async function getServerSideProps() {
const secret = process.env.JWT_SECRET;
// Use secret...
}
// ❌ Does NOT work in components (browser)
export default function MyComponent() {
const dbUrl = process.env.DATABASE_URL; // undefined!
}
# Shared defaults for all environments
NEXT_PUBLIC_APP_NAME=My Next.js App
NEXT_PUBLIC_DEFAULT_LOCALE=en
# Database (overridden in .env.local)
DATABASE_URL=postgres://localhost:5432/dev
# External services (no secrets)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_abc123
# Local development secrets
DATABASE_URL=postgres://localhost:5432/mylocal
JWT_SECRET=dev-jwt-secret-change-in-production
STRIPE_SECRET_KEY=sk_test_local_key
# Local overrides
NEXT_PUBLIC_API_URL=http://localhost:4000/api
# Production environment defaults
NEXT_PUBLIC_API_URL=https://api.production.com
NEXT_PUBLIC_ANALYTICS_ID=UA-PROD-123456
# These will be overridden by platform env vars
DATABASE_URL=set-this-in-vercel
JWT_SECRET=set-this-in-vercel
# Copy this to .env.local and fill in actual values
# Client-side (browser accessible)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_ANALYTICS_ID=your-analytics-id
NEXT_PUBLIC_SITE_NAME=Your Site Name
# Server-side (secrets)
DATABASE_URL=postgres://user:password@host:5432/database # pragma: allowlist secret
JWT_SECRET=your-jwt-secret-32-chars-minimum
STRIPE_SECRET_KEY=sk_live_your_stripe_key
SMTP_HOST=smtp.example.com
SMTP_PORT=587
[email protected]
SMTP_PASSWORD=your-smtp-password
# Development (.env.local)
DATABASE_URL=postgres://localhost:5432/myapp_dev
# Production (Vercel Environment Variables)
DATABASE_URL=postgres://user:pass@prod-host:5432/myapp_prod # pragma: allowlist secret
# Public keys (client-side)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123
# Secret keys (server-side only)
STRIPE_SECRET_KEY=sk_live_xyz789
# Toggle features
NEXT_PUBLIC_ENABLE_DARK_MODE=true
NEXT_PUBLIC_ENABLE_BETA_FEATURES=false
DATABASE_URLpostgres://...Vercel automatically exposes NEXT_PUBLIC_* variables at build time.
# Vercel automatically handles:
NEXT_PUBLIC_API_URL=https://api.example.com # ✅ Exposed to browser
# Server-only:
DATABASE_URL=postgres://... # ✅ Not exposed to browser
⚠️ Important: NEXT_PUBLIC_* variables are baked into the build at build time.
If changing them in Vercel, redeploy is required:
vercel --prod
# Check structure
python scripts/validate_env.py .env.local --framework nextjs
# Compare with .env.example
python scripts/validate_env.py .env.local --compare-with .env.example
# Check for security issues
python scripts/scan_exposed.py --check-gitignore
# List all .env files
ls -la .env*
# Validate each
for file in .env*; do
echo "=== $file ==="
python scripts/validate_env.py $file --framework nextjs
done
# Compare local vs Vercel
python scripts/sync_secrets.py --platform vercel --compare
# Sync (dry-run first)
python scripts/sync_secrets.py --platform vercel --sync --dry-run
# Actually sync
python scripts/sync_secrets.py --platform vercel --sync --confirm
Symptom: process.env.MY_VAR is undefined in component.
Solution: Add NEXT_PUBLIC_ prefix:
# ❌ Wrong
API_URL=https://api.example.com
# ✅ Correct
NEXT_PUBLIC_API_URL=https://api.example.com
Symptom: Changed NEXT_PUBLIC_* variable in Vercel, but app still uses old value.
Solution: Redeploy (variables are baked into build):
vercel --prod
Symptom: App works with .env.local, fails in production.
Solution: Ensure all variables from .env.local are set in Vercel:
# Compare
python scripts/sync_secrets.py --platform vercel --compare
# Find missing vars and add them in Vercel UI
.env.local in .gitignore.env.*.local in .gitignoreNEXT_PUBLIC_* variables.env files committed with real secrets.env.example has structure, not actual valuesRelated: validation.md | security.md | frameworks.md
When using Nextjs, these skills enhance your workflow:
[Full documentation available in these skills if deployed in your bundle]
development
Optimize web performance using Core Web Vitals, modern patterns (View Transitions, Speculation Rules), and framework-specific techniques
development
Best practices for documenting APIs and code interfaces, eliminating redundant documentation guidance per agent.
development
Comprehensive API design patterns covering REST, GraphQL, gRPC, versioning, authentication, and modern API best practices
development
Visual verification workflow for UI changes to accelerate code review and catch ...