Environment Configs
Managing environment variables in Next.js applications
🔐 What are Environment Variables?
Environment variables store configuration values like API keys, database URLs, and secrets outside your code. Next.js provides built-in support for environment variables, keeping sensitive data secure and allowing different configurations for development and production.
# .env.local
DATABASE_URL="postgresql://localhost:5432/mydb"
API_KEY="your-secret-key"
Environment File Types
.env.local
Local development secrets
.env.development
Development environment only
.env.production
Production environment only
.env
Default for all environments
🔹 Creating Environment Files
Create environment files in your project root. Next.js automatically loads these files based on the current environment. Use .env.local for secrets that should never be committed to version control.
# .env.local (for secrets - add to .gitignore)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
API_SECRET_KEY="super-secret-key-12345"
STRIPE_SECRET_KEY="sk_test_..."
# .env.development (can be committed)
NEXT_PUBLIC_API_URL="http://localhost:3000/api"
NEXT_PUBLIC_SITE_NAME="My App (Dev)"
# .env.production (can be committed)
NEXT_PUBLIC_API_URL="https://api.myapp.com"
NEXT_PUBLIC_SITE_NAME="My App"
File Priority (highest to lowest):
- .env.local
- .env.development or .env.production
- .env
🔹 Server-Side Variables
Server-side environment variables are only accessible in server components, API routes, and server actions. They're never exposed to the browser, making them perfect for sensitive data like database credentials and API secrets.
// app/api/users/route.ts
export async function GET() {
// Access server-only variable
const dbUrl = process.env.DATABASE_URL
// This is secure - never sent to client
const apiKey = process.env.API_SECRET_KEY
return Response.json({ message: 'Success' })
}
// app/actions.ts (Server Action)
'use server'
export async function createUser(formData: FormData) {
const db = process.env.DATABASE_URL
// Use database connection
}
🔹 Client-Side Variables
Expose variables to the browser by prefixing with NEXT_PUBLIC_. These are embedded in the JavaScript bundle at build time, so only use them for non-sensitive data like API endpoints or feature flags.
# .env.local
NEXT_PUBLIC_API_URL="https://api.example.com"
NEXT_PUBLIC_ANALYTICS_ID="GA-123456"
NEXT_PUBLIC_SITE_NAME="My Awesome App"
// app/components/header.tsx
'use client'
export default function Header() {
// Access in client component
const siteName = process.env.NEXT_PUBLIC_SITE_NAME
const apiUrl = process.env.NEXT_PUBLIC_API_URL
return (
<header>
<h1>{siteName}</h1>
<p>API: {apiUrl}</p>
</header>
)
}
⚠️ Important:
- NEXT_PUBLIC_ variables are visible in browser
- Never put secrets in NEXT_PUBLIC_ variables
- They're embedded at build time, not runtime
🔹 Loading Environment Variables
Next.js automatically loads environment variables from .env files. You can also load them programmatically or use different files for testing. Variables are available immediately in your application code.
// next.config.js
module.exports = {
env: {
// Custom environment variables
CUSTOM_KEY: process.env.CUSTOM_KEY,
},
// Or use publicRuntimeConfig for runtime values
publicRuntimeConfig: {
apiUrl: process.env.API_URL,
},
serverRuntimeConfig: {
secretKey: process.env.SECRET_KEY,
},
}
🔹 Default Values and Validation
Provide fallback values and validate required environment variables at startup. This prevents runtime errors and makes configuration requirements clear. Use a validation library or custom checks to ensure all needed variables are set.
// lib/env.ts
const requiredEnvVars = [
'DATABASE_URL',
'API_SECRET_KEY',
] as const
// Validate environment variables
requiredEnvVars.forEach((envVar) => {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`)
}
})
// Export typed environment variables
export const env = {
databaseUrl: process.env.DATABASE_URL!,
apiSecretKey: process.env.API_SECRET_KEY!,
apiUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000',
nodeEnv: process.env.NODE_ENV || 'development',
} as const
// Use in your app
import { env } from '@/lib/env'
// TypeScript knows these exist
const db = env.databaseUrl
const apiKey = env.apiSecretKey
🔹 Best Practices
Follow these guidelines to manage environment variables securely and effectively:
Security & Organization:
- Never commit secrets: Add .env.local to .gitignore
- Use NEXT_PUBLIC_ carefully: Only for non-sensitive data
- Document variables: Create .env.example with dummy values
- Validate on startup: Check required variables exist
- Use different values: Separate dev/staging/production configs
- Rotate secrets regularly: Update API keys periodically
# .env.example (commit this)
DATABASE_URL="postgresql://user:password@localhost:5432/dbname"
API_SECRET_KEY="your-secret-key-here"
NEXT_PUBLIC_API_URL="https://api.example.com"
# Instructions for team:
# 1. Copy this file to .env.local
# 2. Replace values with your actual credentials
# 3. Never commit .env.local