Next.js Environment Variables
Environment variables play a critical role in modern web application development, especially when deploying your Next.js applications to different environments. They allow you to keep sensitive information like API keys, database credentials, and other configuration settings separate from your codebase, enhancing security and flexibility.
Introduction to Environment Variables
Environment variables are dynamic values that can affect the way your application behaves. In Next.js, they serve several important purposes:
- Keeping sensitive data like API keys secure
- Configuring different behaviors based on the environment (development, staging, production)
- Allowing your application to adapt to different deployment environments
- Preventing hardcoded values in your codebase
Let's explore how Next.js handles environment variables and how you can use them effectively in your projects.
Getting Started with Environment Variables in Next.js
Next.js has built-in support for environment variables, making it easy to:
- Load environment variables from
.env
files - Access them on the server side
- Expose specific variables to the browser
Basic Setup
First, create a .env.local
file in the root of your Next.js project:
API_KEY=your_secret_api_key
DATABASE_URL=mongodb://localhost:27017/myapp
By default, environment variables are only available in the Node.js environment (server-side). To access them in your code, use process.env
:
// pages/api/data.js
export default function handler(req, res) {
// This runs on the server
const apiKey = process.env.API_KEY;
res.status(200).json({ message: "API key is available on the server" });
}
Exposing Environment Variables to the Browser
What if you need to access environment variables in client-side code? Next.js allows you to expose specific variables to the browser by prefixing them with NEXT_PUBLIC_
:
NEXT_PUBLIC_ANALYTICS_ID=UA-123456-7
NEXT_PUBLIC_API_URL=https://api.example.com
API_SECRET=super_secret_value_not_exposed_to_browser
Now you can use the public variables in both server and client components:
// app/page.js or any component
export default function HomePage() {
console.log(process.env.NEXT_PUBLIC_ANALYTICS_ID); // Works in the browser!
return (
<div>
<p>API URL: {process.env.NEXT_PUBLIC_API_URL}</p>
{/* process.env.API_SECRET would be undefined here in client components */}
</div>
);
}
Important security note: Any variable prefixed with NEXT_PUBLIC_
will be included in the JavaScript bundle sent to the browser. Never use this prefix for sensitive information!
Environment Variable Files
Next.js supports multiple .env
files for different environments:
File Name | Environment | Purpose |
---|---|---|
.env | All environments | Default values |
.env.local | All environments | Local overrides (not checked into git) |
.env.development | Development (next dev ) | Development-specific values |
.env.production | Production (next start ) | Production-specific values |
.env.test | Testing (next test ) | Test environment values |
The priority order (highest to lowest) is:
.env.local
.env.development
,.env.production
, or.env.test
(depending on environment).env
Example directory structure:
your-project/
├── .env # Base environment variables
├── .env.local # Local overrides (ignored by git)
├── .env.development # Development-specific variables
├── .env.production # Production-specific variables
├── .gitignore # Should include .env*.local files
└── ...
Make sure to add .env*.local
to your .gitignore
file to prevent committing sensitive information.
Runtime vs Build-time Environment Variables
In Next.js, environment variables are evaluated at build time by default. This means if you change an environment variable after building your app, those changes won't be reflected until you rebuild.
If you need environment variables that change at runtime (after deployment), you'll need to use runtime configuration. This is especially important for containerized deployments or serverless functions.
Runtime Configuration Example
You can create a runtime configuration by:
- Reading environment variables in a server component or API route
- Passing the value down to client components as props
// app/page.js (Server Component in Next.js 13+)
export default async function Page() {
// This runs on the server at request time
const runtimeConfig = {
apiUrl: process.env.API_URL,
environment: process.env.NODE_ENV
};
return <ClientComponent config={runtimeConfig} />;
}
// Client component
function ClientComponent({ config }) {
return (
<div>
<p>API URL: {config.apiUrl}</p>
<p>Environment: {config.environment}</p>
</div>
);
}
Practical Example: Configuring Multiple Environments
Let's see a complete example of configuring a Next.js application for different environments:
- First, create the environment files:
.env
(base defaults):
NEXT_PUBLIC_API_URL=https://api.production.com
NEXT_PUBLIC_ANALYTICS_ID=UA-DEFAULT
DATABASE_URL=postgres://default:default@localhost:5432/myapp
.env.development
(development environment):
NEXT_PUBLIC_API_URL=https://api.development.com
DATABASE_URL=postgres://dev:password@localhost:5432/myapp_dev
.env.production
(production environment):
NEXT_PUBLIC_ANALYTICS_ID=UA-PROD-123456
- Now use these variables in your application:
// app/layout.js
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
{/* Analytics script using environment variable */}
{process.env.NEXT_PUBLIC_ANALYTICS_ID && (
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_ANALYTICS_ID}`}
/>
)}
</head>
<body>
<header>
{/* Environment indicator */}
<div className="environment-badge">
{process.env.NODE_ENV === 'development' ? 'DEV' : 'PROD'}
</div>
</header>
{children}
<footer>
{/* Using public environment variable */}
<p>API: {process.env.NEXT_PUBLIC_API_URL}</p>
</footer>
</body>
</html>
);
}
- Server-side API route using secure variables:
// app/api/data/route.js
export async function GET() {
// Connect to database using secure environment variable
const db = await connectToDatabase(process.env.DATABASE_URL);
// Perform operations...
return Response.json({ success: true });
}
Environment Variables in CI/CD and Production
When deploying your Next.js application, you need to configure environment variables in your hosting environment. Here's how to do it on some popular platforms:
Vercel
Vercel, the platform from the creators of Next.js, makes environment variable management easy:
- Go to your project settings in the Vercel dashboard
- Navigate to the "Environment Variables" section
- Add your variables for Production, Preview, and Development environments
- Deploy your application
Netlify
- Go to your site settings in the Netlify dashboard
- Navigate to "Build & deploy" > "Environment"
- Add your environment variables
- Redeploy your application
Docker
When using Docker, you can provide environment variables in your Dockerfile or at runtime:
FROM node:18-alpine AS base
# ... other setup steps
ENV NODE_ENV production
ENV NEXT_PUBLIC_API_URL=https://api.example.com
# ... rest of your Dockerfile
Or when running the container:
docker run -p 3000:3000 -e DATABASE_URL=postgres://user:pass@host:port/db your-nextjs-app
Best Practices for Environment Variables
- Never commit sensitive information: Keep
.env.local
files out of git - Use appropriate prefixes: Only use
NEXT_PUBLIC_
for safe, non-sensitive values - Set defaults: Provide sensible defaults in
.env
files - Validate environment variables: Check that critical variables exist at startup
- Document requirements: Maintain a list of required environment variables in your README
- Use specific environments: Leverage
.env.development
and.env.production
for environment-specific defaults
Here's a simple validation pattern to ensure critical variables are present:
// lib/validateEnv.js
export function validateEnv() {
const requiredEnvVars = ['DATABASE_URL', 'API_KEY'];
const missingEnvVars = requiredEnvVars.filter(
env => !process.env[env]
);
if (missingEnvVars.length > 0) {
throw new Error(
`Missing required environment variables: ${missingEnvVars.join(', ')}`
);
}
}
// Call this early in your application startup
// e.g., in a custom server.js file or in a top-level API route
Summary
Environment variables are essential for configuring Next.js applications across different environments. They allow you to:
- Keep sensitive information secure
- Configure environment-specific settings
- Adapt your application to different deployment contexts
- Follow security best practices by separating configuration from code
By understanding how to properly use environment variables in Next.js, you can create more secure, configurable, and maintainable applications that are ready for production deployment.
Additional Resources
- Next.js Environment Variables Documentation
- Twelve-Factor App Methodology - Config best practices
- dotenv npm package - The library Next.js uses internally
Exercises
- Create a Next.js application that uses environment variables to configure API endpoints for development and production environments.
- Implement a system that loads different feature flags based on the environment.
- Build a Next.js application that connects to different databases in development and production using environment variables.
- Create a validation system that checks for required environment variables and provides helpful error messages when they're missing.
- Implement a debug mode that's enabled only in non-production environments using environment variables.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)