- Learn
- Stack Essentials
- Vercel
- Environment Variables
Manage environment variables securely in Vercel for different environments and integrations.
Environment Variables
Environment variables store secrets and configuration that differ between development, preview, and production.
Understanding Environments
Vercel has three environments:
| Environment | Branch | Use Case |
|---|---|---|
| Production | main | Live site |
| Preview | feature branches | Testing PRs |
| Development | Local | Local dev |
Each can have different variable values.
Adding Variables
Via Dashboard
Project → Settings → Environment Variables
Name: SUPABASE_SERVICE_ROLE_KEY
Value: eyJ...
Environments: ☑ Production ☑ Preview ☐ Development
Via CLI
# Add to all environments
vercel env add VARIABLE_NAME
# Add to specific environment
vercel env add VARIABLE_NAME production
# Pull to local .env.local
vercel env pull .env.local
Via vercel.json
For non-sensitive build-time variables:
{
"build": {
"env": {
"NEXT_PUBLIC_APP_NAME": "My App"
}
}
}
Variable Types
Server-Side Only (Secrets)
Never exposed to browser:
# Database credentials
DATABASE_URL=postgresql://...
# API keys
SUPABASE_SERVICE_ROLE_KEY=eyJ...
# Third-party secrets
STRIPE_SECRET_KEY=sk_live_...
OPENAI_API_KEY=sk-...
Access in Server Components and API routes:
// app/api/route.ts
export async function GET() {
const apiKey = process.env.OPENAI_API_KEY
// Safe - only runs on server
}
Client-Side (Public)
Exposed to browser—prefix with NEXT_PUBLIC_:
# Client-safe values
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
NEXT_PUBLIC_APP_URL=https://myapp.com
Access in Client Components:
'use client'
function Component() {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL
// Available in browser
}
Environment-Specific Values
Different Values Per Environment
Production:
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgresql://prod-db...
Preview:
NEXT_PUBLIC_API_URL=https://staging-api.example.com
DATABASE_URL=postgresql://staging-db...
Development:
NEXT_PUBLIC_API_URL=http://localhost:3001
DATABASE_URL=postgresql://localhost...
Supabase Configuration
Typical setup:
# Both environments (same project)
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
# Production only (server-side)
SUPABASE_SERVICE_ROLE_KEY=eyJ...
# Or separate projects
# Production
NEXT_PUBLIC_SUPABASE_URL=https://prod.supabase.co
# Preview
NEXT_PUBLIC_SUPABASE_URL=https://staging.supabase.co
System Variables
Vercel provides automatic variables:
# Always available
VERCEL=1
VERCEL_ENV=production|preview|development
VERCEL_URL=my-app-abc123.vercel.app
VERCEL_GIT_COMMIT_SHA=abc123...
VERCEL_GIT_COMMIT_MESSAGE="feat: add login"
VERCEL_GIT_REPO_SLUG=my-repo
Using System Variables
// Get current URL dynamically
function getBaseUrl() {
if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`
}
return 'http://localhost:3000'
}
// Check environment
if (process.env.VERCEL_ENV === 'production') {
// Production-only code
}
Integration Variables
Connecting Services
Vercel Integrations auto-add variables:
Marketplace → Supabase → Connect
Auto-added:
- SUPABASE_URL
- SUPABASE_ANON_KEY
- SUPABASE_SERVICE_ROLE_KEY
- POSTGRES_URL
Popular Integrations
| Service | Variables Added |
|---|---|
| Supabase | SUPABASE_URL, keys |
| PlanetScale | DATABASE_URL |
| Vercel KV | KV_URL, KV_TOKEN |
| Vercel Blob | BLOB_READ_WRITE_TOKEN |
Local Development
.env.local
Create .env.local for local development:
# .env.local (never commit!)
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
Pull from Vercel
Sync production variables locally:
# Pull to .env.local
vercel env pull .env.local
# Pull specific environment
vercel env pull .env.local --environment=preview
.env.example
Create .env.example for documentation:
# .env.example (commit this!)
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-key
Security Best Practices
Never Expose Secrets
// WRONG - exposes secret to client
'use client'
function Component() {
// This will be undefined (correct behavior)
const key = process.env.SUPABASE_SERVICE_ROLE_KEY
}
// CORRECT - only in server code
// app/api/admin/route.ts
export async function GET() {
const key = process.env.SUPABASE_SERVICE_ROLE_KEY
// Safe - server only
}
gitignore
# .gitignore
.env
.env.local
.env.*.local
Rotate Compromised Keys
If a secret is exposed:
- Regenerate key in service (Supabase, Stripe, etc.)
- Update in Vercel dashboard
- Redeploy application
- Check logs for unauthorized access
Variable Patterns
Feature Flags
NEXT_PUBLIC_FEATURE_NEW_UI=true
NEXT_PUBLIC_FEATURE_BETA_API=false
function Component() {
if (process.env.NEXT_PUBLIC_FEATURE_NEW_UI === 'true') {
return <NewUI />
}
return <OldUI />
}
API Versioning
# Production - stable API
API_VERSION=v1
# Preview - test new API
API_VERSION=v2
Debug Mode
# Production
DEBUG_MODE=false
# Preview
DEBUG_MODE=true
if (process.env.DEBUG_MODE === 'true') {
console.log('Debug info:', data)
}
Managing Variables
List Variables
# Via CLI
vercel env ls
# Output
> Environment Variables for my-project
> NEXT_PUBLIC_SUPABASE_URL (Production, Preview, Development)
> SUPABASE_SERVICE_ROLE_KEY (Production)
Remove Variables
# Via CLI
vercel env rm VARIABLE_NAME
Update Variables
Dashboard:
Settings → Environment Variables → Edit → Save
Note: Changes require redeployment to take effect.
Troubleshooting
Variable Not Available
- Check prefix: Client-side needs
NEXT_PUBLIC_ - Check environment: Is it enabled for this environment?
- Redeploy: Variables update after deployment
Undefined in Browser
// If undefined, likely missing NEXT_PUBLIC_ prefix
console.log(process.env.API_KEY) // undefined in browser
console.log(process.env.NEXT_PUBLIC_API_KEY) // works
Build vs Runtime
Some variables are only available at build time:
// Build time - baked into bundle
const buildTime = process.env.NEXT_PUBLIC_BUILD_ID
// Runtime - for dynamic values, use API route
Summary
- Server secrets: No prefix, never exposed to browser
- Client variables:
NEXT_PUBLIC_prefix required - Environments: Production, Preview, Development
- Pull locally:
vercel env pull .env.local - Never commit: Add
.env.localto.gitignore
Next Steps
Learn advanced Vercel features like Edge Functions and Analytics.