
Nextjs
- 82 installs
- 63 repo stars
- Updated July 18, 2026
- bobmatnyc/claude-mpm-skills
nextjs is a reference skill for Next.js environment variable management, covering .env file precedence, NEXT_PUBLIC vs server-only variables, and platform deployment config.
About
This skill is a reference for managing environment variables in Next.js applications. It covers the .env file precedence order, the difference between NEXT_PUBLIC client variables and server-only secrets, and setting variables when deploying to Vercel, Railway, or Heroku. A developer uses it when configuring per-environment settings for a Next.js app.
- Next.js .env file precedence and per-environment defaults
- NEXT_PUBLIC client variables vs server-only secrets
- Setting env vars for Vercel, Railway, and Heroku deploys
Nextjs by the numbers
- 82 all-time installs (skills.sh)
- Ranked #1,104 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
nextjs capabilities & compatibility
- Capabilities
- env configuration · secrets management · deployment config
- Works with
- vercel
- Use cases
- frontend · devops
- Runs
- Runs locally
- Pricing
- Free
What nextjs says it does
Next.js environment variable management with file precedence, variable types, and deployment configurations.
Exposed to the browser. Must prefix with `NEXT_PUBLIC_`.
**⚠️ Security Warning**: NEVER put secrets in `NEXT_PUBLIC_*` variables!
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill nextjsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 82 |
|---|---|
| repo stars | ★ 63 |
| Last updated | July 18, 2026 |
| Repository | bobmatnyc/claude-mpm-skills ↗ |
What it does
Reference for Next.js environment variable file precedence, NEXT_PUBLIC vs server-only variables, and platform deployment config.
Who is it for?
Developers configuring per-environment settings and secrets in a Next.js app.
Skip if: Developers needing full Next.js routing, rendering, or App Router guidance.
When should I use this skill?
Configuring Next.js applications, managing environment-specific settings, or deploying to Vercel/Railway/Heroku.
What you get
Correctly scoped Next.js env files with secrets kept off the client.
By the numbers
- Documents a 4-level env file precedence order
Files
Next.js Environment Variable Structure
Complete guide to Next.js environment variable management.
File Structure
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)File Precedence
Next.js loads files in this order (higher = higher precedence):
1. .env.$(NODE_ENV).local (e.g., .env.production.local) 2. .env.local (not loaded in test environment) 3. .env.$(NODE_ENV) (e.g., .env.production) 4. .env
Example: In production, if DATABASE_URL is defined in both .env and .env.production.local, the value from .env.production.local wins.
Variable Types
Client-Side Variables (NEXT_PUBLIC_*)
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=trueAccess 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_abc123Server-Side Variables
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-hereAccess 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!
}Example Files
.env (Committed - Shared Defaults)
# 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.env.local (Gitignored - Local Secrets)
# 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.env.production (Committed - Production Defaults)
# 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.env.example (Committed - Documentation)
# 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
SMTP_USER=your-email@example.com
SMTP_PASSWORD=your-smtp-passwordCommon Patterns
Database Configuration
# 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 secretAPI Keys
# Public keys (client-side)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123
# Secret keys (server-side only)
STRIPE_SECRET_KEY=sk_live_xyz789Feature Flags
# Toggle features
NEXT_PUBLIC_ENABLE_DARK_MODE=true
NEXT_PUBLIC_ENABLE_BETA_FEATURES=falseDeployment to Vercel
Step 1: Add Environment Variables in Vercel
1. Go to Project Settings → Environment Variables 2. Add each variable:
- Key:
DATABASE_URL - Value:
postgres://... - Environments: Production, Preview, Development
Step 2: Separate Client vs Server Variables
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 browserStep 3: Rebuild After Changing NEXT_PUBLIC_ Variables
⚠️ Important: NEXT_PUBLIC_* variables are baked into the build at build time.
If changing them in Vercel, redeploy is required:
vercel --prodValidation Workflow
1. Validate Local Environment
# 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-gitignore2. Check File Precedence
# List all .env files
ls -la .env*
# Validate each
for file in .env*; do
echo "=== $file ==="
python scripts/validate_env.py $file --framework nextjs
done3. Sync to Vercel
# 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 --confirmCommon Issues
Issue: Variable Undefined in Browser
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.comIssue: Changed Variable Not Reflected
Symptom: Changed NEXT_PUBLIC_* variable in Vercel, but app still uses old value.
Solution: Redeploy (variables are baked into build):
vercel --prodIssue: Works Locally, Not in Production
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 UISecurity Checklist
- [ ]
.env.localin.gitignore - [ ]
.env.*.localin.gitignore - [ ] No secrets in
NEXT_PUBLIC_*variables - [ ] No
.envfiles committed with real secrets - [ ]
.env.examplehas structure, not actual values - [ ] Secrets set directly in Vercel (not in committed files)
References
---
Related: validation.md | security.md | frameworks.md
Related Skills
When using Nextjs, these skills enhance your workflow:
- react: Core React patterns and hooks for Next.js components
- tanstack-query: Server-state management with App Router and Server Components
- drizzle: Type-safe ORM for Next.js server actions and API routes
- prisma: Alternative ORM with excellent Next.js integration
- test-driven-development: Testing Next.js App Router, Server Components, and API routes
[Full documentation available in these skills if deployed in your bundle]
{
"name": "nextjs",
"version": "1.0.0",
"category": "toolchain",
"toolchain": "javascript",
"framework": "nextjs",
"tags": [
"async",
"database",
"api",
"security",
"testing"
],
"entry_point_tokens": 64,
"full_tokens": 2123,
"author": "bobmatnyc",
"license": "MIT",
"requires": [],
"updated": "2025-11-21",
"source_path": "infrastructure/env-manager/examples/nextjs-env-structure.md",
"source": "https://github.com/bobmatnyc/claude-mpm",
"created": "2025-11-21",
"modified": "2025-11-21",
"maintainer": "Claude MPM Team",
"attribution_required": true,
"repository": "https://github.com/bobmatnyc/claude-mpm-skills"
}
Related skills
FAQ
What is the Next.js env file precedence?
.env.$(NODE_ENV).local wins, then .env.local, then .env.$(NODE_ENV), then .env.
How do you expose an env var to the browser in Next.js?
Prefix it with NEXT_PUBLIC_; never put secrets in NEXT_PUBLIC variables.