Skip to main content

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:

  1. Load environment variables from .env files
  2. Access them on the server side
  3. 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:

jsx
// 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:

jsx
// 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 NameEnvironmentPurpose
.envAll environmentsDefault values
.env.localAll environmentsLocal overrides (not checked into git)
.env.developmentDevelopment (next dev)Development-specific values
.env.productionProduction (next start)Production-specific values
.env.testTesting (next test)Test environment values

The priority order (highest to lowest) is:

  1. .env.local
  2. .env.development, .env.production, or .env.test (depending on environment)
  3. .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:

  1. Reading environment variables in a server component or API route
  2. Passing the value down to client components as props
jsx
// 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:

  1. 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
  1. Now use these variables in your application:
jsx
// 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>
);
}
  1. Server-side API route using secure variables:
jsx
// 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:

  1. Go to your project settings in the Vercel dashboard
  2. Navigate to the "Environment Variables" section
  3. Add your variables for Production, Preview, and Development environments
  4. Deploy your application

Netlify

  1. Go to your site settings in the Netlify dashboard
  2. Navigate to "Build & deploy" > "Environment"
  3. Add your environment variables
  4. Redeploy your application

Docker

When using Docker, you can provide environment variables in your Dockerfile or at runtime:

dockerfile
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:

bash
docker run -p 3000:3000 -e DATABASE_URL=postgres://user:pass@host:port/db your-nextjs-app

Best Practices for Environment Variables

  1. Never commit sensitive information: Keep .env.local files out of git
  2. Use appropriate prefixes: Only use NEXT_PUBLIC_ for safe, non-sensitive values
  3. Set defaults: Provide sensible defaults in .env files
  4. Validate environment variables: Check that critical variables exist at startup
  5. Document requirements: Maintain a list of required environment variables in your README
  6. 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:

jsx
// 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

Exercises

  1. Create a Next.js application that uses environment variables to configure API endpoints for development and production environments.
  2. Implement a system that loads different feature flags based on the environment.
  3. Build a Next.js application that connects to different databases in development and production using environment variables.
  4. Create a validation system that checks for required environment variables and provides helpful error messages when they're missing.
  5. 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! :)