Trendy Coder Logo
  • Home
  • About
  • Blog
  • Newsletter

Next.js Environment Variables: Quick Start Guide

Posted on: September 01 2025
By Dave Becker
Hero image for Next.js Environment Variables: Quick Start Guide

Environment variables are an essential part of securing and configuring apps but when working with Next.js, it has some added support and functionality for handling environment variables that you won't find in a typical Node.js app.

Next.js has built-in flow support for loading environment variables. Having a solid understanding of this process will help avoid any security risks and unintended results.

This guide will cover the basic steps for setting environment variables for each environment, including:

  • How Next.js loads environment variables.
  • What environments does Next.js support?
  • Do I need to use third party packages for .env support?
  • How the environment is set in test mode.
  • How to run tests using the Next.js recommended way.

This post will quickly help developers understand how to use Next.js environment variables like a pro.

For a quick start guide on Node.js .env file usage, here's a recap on Nodes.js environment variables. Next.js builds on some of the best strategies when loading .env files.

Let's get started.

Next.js Environment variables

Next.js supports the following standard Node.js environments:

  • development
  • production
  • test

Next.js will display a warning message if any environments besides the standard are used.

⚠ You are using a non-standard "NODE_ENV" value in your environment. This creates inconsistencies in the project and is strongly advised against. Read more: https://nextjs.org/docs/messages/non-standard-node-env

It's best to stick to the standard environments to avoid introducing any inconsistencies.

Starting different environments

The Next.js runtime will automatically set the NODE_ENV when using the following commands:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

Each command sets the following:

  • next dev: sets development mode
  • next build: sets production mode
  • next start: sets production mode

One thing to note, is that the build step will use production variables.

Next.js will build static and server side rendered resources during the build phase and so it uses production variables to render the production content.

How Next.js loads .env files.

By default, Next.js will look for .env* files in the root of the project.

Built-in loading order for .env

It will use a specific flow order and it will resolve variables in the following locations.

  1. process.env (Any command line vars will take priority)
  2. .env.[NODE_ENV].local (override to .env.local)
  3. .env.local (except for test env)
  4. .env.[NODE_ENV]
  5. .env

Types of .env variable files

Here's some examples of what files it will look for.

  • .env
  • .env.local
  • .env.development.local
  • .env.development
  • .env.production.local
  • .env.production
  • .env.test

How to know which .env files Next.js loads?

When starting up a Next.js app, it will console log all of the environments that it finds including the flow order it will use to resolve variables.

An image showing the environments files found during startup.

The Next.js runtime will use the first variable it finds in the sequence path and put the resulting values in the process.env object.

This process allows for max flexibility with the ability to override as needed.

Purposes of different .env files.

Here's a general idea of the purposes for each of the different .env files.

FileCommitted?Recommended Use
.env✅ YesDefault values common to all environments.
.env.local❌ NoSecrets and local-only overrides. Do NOT commit.
.env.development✅ YesDevelopment-specific config shared across team.
.env.development.local❌ NoDeveloper’s local overrides during development.
.env.production✅ YesProduction defaults (safe to commit).
.env.production.local❌ NoProduction-only secrets (API keys, DB creds).

This approach has the following benefits:

  • Allows for default base environment variables to be checked into the repo for other developers to use as a starting point.
  • A production environment can use .env.production for defaults and add secrets locally in .env.production.local to debug a production environment.
  • Using local files like .env.local or .env.*.local to override any local setup or secret keys needed.

General tips

  • Never commit .env.local, .env.*.local. Add them to .gitignore.
  • Use .env only for non-sensitive shared defaults.

Depending on your development process, you may opt to not check any of these files into the repo, however, if you're using this systematic approach it can offer great flexibility.

Example overriding with local

For example, we can set some default values in .env and .env.development files for some database info.

Sets the base setup variables.

.env
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=default
DB_PASS=
DB_NAME=default

Set some development standard setup.

.env.development
DB_USER=manager
DB_NAME=nw-stage-db1

A developer can then override and add their secrets using .env.development.local.

.env.development.local
DB_USER=admin
DB_PASS=super-secret
DB_NAME=nw-stage-db2 # even override the db name for dev

The approach for a production flow is the same with only the NODE_ENV being set to production. This can be useful when a production issue needs to be debugged.

Accessing .env variables in the client

Since environment variables are only available on the server, they cannot be accessed by client code that runs in the Browser. To make them available in the Browser, Next.js uses a prefix.

  • NEXT_PUBLIC_: Any variable with this prefix will be available in the client environment.

Using the Next.js public prefix

Any variables prefixed, will be bundled and available in the Browser.

SERVER_URL=http://localhost:3000

# change to 

NEXT_PUBLIC_SERVER_URL=http://localhost:3000

This is useful for defining API and server URLs for fetch calls among other things.

'use client'

export default Component() {

  const resp = fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/posts`, { method: 'GET'})

  const posts = resp.json();
  ...

  return {posts.map(post => <div key={post.id}>{post.title}</div>)}
}

General tips

  • Only put non-sensitive values in public variables.
  • Never put payment gateway details in public variables, it's better to create a proxy endpoint to make those calls on the server side.
  • Never commit public variables with sensitive values into the repo.

Referencing variables

Next.js has built-in support for referencing other variables in the same .env file. Other variables can be referenced using the $.

For example:

# Defines a base path uri
CONTENT_BASE=/resources/media

# Defines sub paths using the $
AVATARS=$CONTENT_BASE/avatars
ICONS=$CONTENT_BASE/icons

This is really useful and makes it easy to change many variables with a single base variable.

If you need to use the actual $ character in any value, you can escape it using the backslash \$.

DEFAULT_DISCOUNT_AMT=10.00
USD_DISCOUNT=\$${DEFAULT_DISCOUNT_AMT}

Testing using Next.js .env variables

The last section we need to cover is how to lauch Next.js in test mode properly.

To run tests using Next.js in test mode, we'll need to add a few things.

Install Jest test dependencies

The testing packages are not installed by default and so we'll need to add:

  • Jest test runner and some helpers.
  • React Testing Library (RTL).
  • @types/jest
npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node @types/jest
# or
yarn add -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node @types/jest
# or
pnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node @types/jest

Once these packages are installed, you can easily run your Jest tests directly.

However, running them this way will not load the expected test environment variables automaticallly.

package.json
 {
  "scripts": {
    "test": "jest test"
  }
 }

By running tests using the next test command is the recommended way.

This way Next.js can set everything up and load the test mode environment variables.

package.json
 {
  "scripts": {
    "test": "next test"
  }
 }

In order to let Next.js lauch and execute the Jest test runner, we'll need a wrapper to do the job.

Create a Jest test wrapper

Next.js provides a nextJest wrapper for the Jest test runner.

The benefits of using this approach include:

  • Loads .env and .env.test variables.
  • Add ignores to .next and node_modules by default.
  • Sets transform using the Next.js compiler.
  • Automatically mocks style sheet modules.
  • Uses next.config.js for config flags to enable SWC transforms.
  • It will use tsconfig.json config settings for things like path aliases, etc.

Here's how to create a nextJest wrapper. This wrapper sets the project directory for the Jest test runner and allows for any pass through settings for Jest.

The nextJest helper function will set the Next.js runtime details automatically.

jest config
import type { Config } from 'jest'
import nextJest from 'next/jest.js'

const createJestConfig = nextJest({
  // project root
  dir: './',
})

// Add any custom config to be passed to Jest
const config: Config = {
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  // call the jest.setup.ts
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

// wrap the config in a createJestConfig()
export default createJestConfig(config)

I'll add a global setup file too.

jest setup
// Learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";

// add other global setup here.

How Next.js sets test environment variables

When running in test environment, it will only use the following flow and omit any development or production files.

  1. process.env (Any command line vars will take priority)
  2. .env.test
  3. .env

I'll add a base .env value but override it with the .env.test value.

.env
SITE_URL=http://localhost
.env.test
SITE_URL=http://plantsandnature.co

Create a unit test page

I'll add a simple Next.js page with a link that uses a SITE_URL environment variable so we can run a unit test against it.

const SITE_URL = process.env.SITE_URL

export default function Page() {
  return (
    <div>
      <a href={`${SITE_URL}/plants`}>Click Me</a>
    </div>
  );
}


Here's a simple react test using the Next.js Jest wrapper which will load the environment and check the link value.

  • It should not contain the .env value.
  • It should contain the .env.test value.
import React from "react";
import { render, screen } from "@testing-library/react";
import Page from "./page";

test("link should not contain .env site url", () => {
  render(<Page />);

  expect(screen.getByText("Click Me").getAttribute("href")).not.toContain("http://localhost");
});

test("renders a link containg .env.test site url", () => {
  render(<Page />);

  const SITE_URL = process.env.SITE_URL;

  expect(screen.getByText("Click Me").getAttribute("href")).toContain(SITE_URL);
});

Launching Next.js tests

To run any tests, call next test. The next runtime will start the Jest test runner and set the environment and config details automatically.

package.json
{
   "scripts": {
    "test": "next test"
  }
}

You can still run npx jest manually if needed, but next test is the recommended way in a Next.js app.

Next.js will pass any Jest args, like filter paths and flags from command line.

npm run test /app/page.spec.tsx

# or pnpm

pnpm test /app/pages/*.spec.tsx

In Conclusion

So as you can see, Next.js provides complete environment flow control. You can easilly set environment variables the way you need too, for large or small projects.

A few key takeaways.

  • By understanding the Next.js environment flow, you can utilize it more confidently.
  • Keep things simple at first and only add .env files as you need flexibility.
  • All three environments are fully supported.

I hope this has helped shed some light on Next.js environment variables.

Topics

SEOLinuxSecuritySSHEmail MarketingMore posts...

Related Posts

Hero image for Build a Blog with MDX and Next.js
Posted on: September 05 2025
By
Build a Blog with MDX and Next.js
Hero image for What are the advantages of using Next.js?
Posted on: September 05 2025
By
What are the advantages of using Next.js?
Hero image for How to debug Next.js in NPM Workspaces
Posted on: September 05 2025
By
How to debug Next.js in NPM Workspaces
Hero image for Next.js Layouts: Maximum Flexibility
Posted on: September 05 2025
By
Next.js Layouts: Maximum Flexibility
Hero image for Top 10 Libraries and Tools for Next.js
Posted on: September 05 2025
By
Top 10 Libraries and Tools for Next.js
Hero image for GraphQL Optimization in Payload CMS
Posted on: September 05 2025
By
GraphQL Optimization in Payload CMS
Hero image for How to Build an Opt-In Page Using Tailwind CSS and Astro
Posted on: September 05 2025
By
How to Build an Opt-In Page Using Tailwind CSS and Astro
Hero image for Create Custom Forms Using Payload CMS Form Builder Plugin
Posted on: September 05 2025
By
Create Custom Forms Using Payload CMS Form Builder Plugin
Trendy Coder Logo
Resources
  • Blog
Website
  • Home
  • About us
Subscribe

Get the latest news and articles to your inbox periodically.

We respect your email privacy

© TrendyCoder.com. All rights reserved.