Environment variables in Next.js
Environment Variables in Next.js
Next.js has built-in support for environment variables with special conventions for server-only and public (client-accessible) variables.
File Conventions
.env β All environments
.env.local β Local overrides (git-ignored)
.env.development β Development only
.env.production β Production only
.env.test β Test onlyPriority (highest to lowest): .env.local > .env.[environment] > .env
Server vs Client Variables
bash
# .env.local
# β
Server-only (default) β NOT exposed to browser
DATABASE_URL=postgresql://localhost:5432/mydb
JWT_SECRET=super-secret-key
API_KEY=sk-1234567890
# β
Public β exposed to browser (NEXT_PUBLIC_ prefix)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=pk_live_xxxUsage
tsx
// Server Component or API Route β has access to ALL variables
async function ServerComponent() {
const dbUrl = process.env.DATABASE_URL; // β
Available
const apiUrl = process.env.NEXT_PUBLIC_API_URL; // β
Available
const secret = process.env.JWT_SECRET; // β
Available
}
// Client Component β ONLY NEXT_PUBLIC_ variables
"use client";
function ClientComponent() {
const apiUrl = process.env.NEXT_PUBLIC_API_URL; // β
Available
const dbUrl = process.env.DATABASE_URL; // β undefined!
const secret = process.env.JWT_SECRET; // β undefined!
}Important Rules
| Rule | Details |
|---|---|
| Default is server-only | Variables without NEXT_PUBLIC_ are server-only |
NEXT_PUBLIC_ prefix | Required to expose a variable to the browser |
| Static replacement | NEXT_PUBLIC_ vars are inlined at build time |
.env.local is git-ignored | Use for secrets, override per developer |
| Restart required | Changes to .env files require restarting the dev server |
Static Replacement (Build Time)
NEXT_PUBLIC_ variables are replaced at build time, not runtime:
tsx
// β
This works β direct reference
const url = process.env.NEXT_PUBLIC_API_URL;
// β This does NOT work β dynamic access
const key = "NEXT_PUBLIC_API_URL";
const url = process.env[key]; // undefined in client!Type Safety with TypeScript
typescript
// env.d.ts
declare namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
JWT_SECRET: string;
NEXT_PUBLIC_API_URL: string;
NEXT_PUBLIC_GA_ID: string;
NODE_ENV: "development" | "production" | "test";
}
}Runtime Environment Variables
For variables that need to change after build (e.g., in Docker):
tsx
// next.config.js
module.exports = {
// Server-side runtime variables
serverRuntimeConfig: {
apiSecret: process.env.API_SECRET,
},
// Available on both server and client
publicRuntimeConfig: {
apiUrl: process.env.API_URL,
},
};Security Best Practices
- Never put secrets in
NEXT_PUBLIC_variables - Always use
.env.localfor sensitive values - Add
.env.localto.gitignore - Provide
.env.examplewith placeholder values for team - Use TypeScript declarations for type safety
Important:
By default, environment variables in Next.js are server-only and not exposed to the browser. Use the NEXT_PUBLIC_ prefix to explicitly make a variable available on the client. Remember that public variables are inlined at build time and cannot be changed without rebuilding. Never expose secrets with NEXT_PUBLIC_.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.