Customizing environment variables in Next.js 13
Tags: nextjs, webdev
Published: 2023-09-13 16:58:56

**Written by [Joseph Mawa](https://blog.logrocket.com/author/josephmawa/)✏️**

The first steps in app production are the development and testing stages. In each stage, the application runs in a different context and environment. Different sets of tools and packages are needed for each of these stages. Environment variables can be used to modify an application's behavior to suit the needs and requirements of a specific environment during production. 

Most frontend frameworks, cloud hosting services, and platforms have built-in functionality for configuring and managing environment variables. Next.js is no exception. In this article, we will take a deep dive into environment variables and explore their customization in Next.js. 

_Jump ahead_:

*   [Understanding environment variables](#understanding-environment-variables)
    *   [What do you store in environment variables?](#what-store-environment-variables)
*   [Built-in support for environment variables in Next.js 13](#built-in-support-environment-variables-next-js-13)
*   [Building a sample application](#building-sample-application)
*   [Public and private environment variables in Next.js](#public-private-environment-variables-next-js)
*   [Using environment variables in local development vs. production](#using-environment-variables-local-development-vs-production)
*   [Manipulating environment variables with `next.config.js`](#manipulating-environment-variables-next-config-js)
*   [Securely storing secrets for local development](#securely-storing-secrets-local-development)
*   [Dynamic environment variables in Next.js 13](#dynamic-environment-variables-next-js-13)
*   [Order of environment variable lookup in Next.js](#order-environment-variable-lookup-next-js)
*   [Interpolating environment variables in Next.js](#interpolating-environment-variables-next-js)

## Understanding environment variables

Environment variables are variables whose values are usually configured and managed outside an application but who affect the application’s behavior. Environment variables consist of name-value pairs like in the example below:

```bash
API_KEY=1234
DB_CONN_STRING="http://localhost:3000"
```

An application can have different requirements when running in development, testing, and production environments. Instead of having different code bases for the same application, where each code base is tailored towards a specific environment, an application can have a single code base whose behavior in the different environments is determined using the environment variable settings. 

The application can read the environment variable settings and modify its behavior to meet the requirements of that specific environment. This keeps the code base short, clean, and organized:

```javascript
process.env.API_KEY;
process.env.DB_CONN_STRING;
```

Typically, in a development environment, you may need tools for code formatting, linting, and running tests. However, in production, these tools are not necessary. Therefore, when working with tools such as npm, setting the value of the built-in `NODE_ENV` environment variable to `production` will, by default, install dependencies the application needs in production, excluding development dependencies. However, this behavior is configurable. 

Similarly, during development, you may need to set up a local instance of your database server separate from the production server. Therefore, you will have to use environment variables to pick the correct database connection string. 

Usually, modifying an environment variable modifies the behavior of an application without requiring you to rebuild or redeploy the application. However, in frameworks like Next.js, some environment variables are hard-coded in the code base at build time. So, you may need to build and redeploy after modifying an environment variable.

### What do you store in environment variables? <a name="what-store-environment-variables">

You can use environment variables to store the following:

*   Information about the environment or context in which your application runs. The requirements of a production environment are almost always different from the requirements of development, staging, and testing environments
*   Credentials for third-party services like API keys that you don't want to expose
*   Resource URIs, database connection strings, and API endpoints you want to keep private
*   Constants and default values that you want to declare at a central location but want to reference from different modules or places in your code

## Built-in support for environment variables in Next.js 13 <a name="built-in-support-environment-variables-next-js-13">

As mentioned earlier, Next.js has built-in support for environment variables. To start using them, you can declare `.env.local` at the root of your project directory:

```bash
API_KEY=123456789
USERNAME=username
PASSWORD=password
```

Next.js will load the above environment variables into the `process.env` object out of the box so that you can access them in the Node.js environment:

```javascript
export async function getStaticProps() {
  console.log(process.env.API_KEY); 
  console.log(process.env.USERNAME);
  console.log(process.env.PASSWORD);
}
```

The above environment variables are only available in the Node.js environment and are referred to as private environment variables. Prefixing the variable name with `NEXT_PUBLIC_` turns them into public environment variables:

```bash
NEXT_PUBLIC_API_KEY=123456789
NEXT_PUBLIC_USERNAME=username
NEXT_PUBLIC_PASSWORD=password
```

Public environment variables are available both in the browser and Node.js environments. We will explore public and private environment variables later in this article. 

In addition to the `.env.local` file, Next.js also gives you the flexibility to store constants and default values in `.env`, `env.development`, and `env.production` environment files. These files are not meant for storing secrets but for environment-specific configurations and settings. 

As its name suggests, the `env.development` file is for environment variables you want to use only in development. In Next.js, you can launch the development server using the `next dev` command. The variables you declare in the `env.development` file won't be available in production. 

The `env.production` file, on the other hand, is for variables that you want to use only in production. The `next start` command builds the project and launches the production environment. 

The variables you declare in the `env.production` file won’t be available in the development environment. The variables you declare in the `.env` file will be available in both development and production environments. Be aware that an environment variable that you look up dynamically, such as in the example below, will not be hard-coded into your production build as we just described:

```javascript
const variableName = 'BASE_URL';
console.log(process.env[variableName]);

const envir = process.env;
console.log(envir.BASE_URL);
```

## Building a sample application <a name="building-sample-application">

You can use this [sample application](https://github.com/nibble0101/next-env-var-demo) to try out the examples in this article. Follow the steps below to clone the repository to your machine and experiment with the environment variables this article highlights. 

First, clone a sample application. Use `git clone` to clone the sample application to your machine. Then, install dependencies by running the `npm install` command.

There are several environment variable files at the root of your project directory. In Next.js, you only store secrets in the `env.local` file. Because environment variables holding secrets should not be shared, there is a `env.local.template` file you can use to create your `env.local` file. 

To add secrets, create a `env.local` file at the root of your project repository and copy the contents of `env.local.template` into it. You can add any secrets you don't want to expose in a version control system in the `env.local` file. 

Next, you can launch the development server using the `npm run dev` command. The environment variables in the `.env.development` file are available only in the development environment. On the other hand, you can build the project and launch the production server using the `npm run build` and `npm run start` commands. The environment variables in the `.env.production` file are available only in the production environment. 

Now, the environment variables in the `.env` file are available in both the development and production environments.

## Public and private environment variables in Next.js <a name="public-private-environment-variables-next-js">

Environment variables in Next.js can be categorized into public and private environment variables, but Next.js environment variables are private by default. Private environment variables are only accessible from the Node.js environment. You can declare private environment variables in any of your `.env*` files like so:

```bash
ENV_VARIABLE=env_variable
```

On the other hand, public environment variables are accessible from both the Node.js and browser environments. To make an environment variable public, prefix its name with `NEXT_PUBLIC_` as in the example below:

```bash
NEXT_PUBLIC_ENV_VARIABLE=nex_public_env_variable
```

At build time, Next.js will access and replace references to the public environment variables with their actual values in the code base bundled for the browser environment. 

Therefore, in the example below, `process.env.NEXT_PUBLIC_ENV_VARIABLE` will be replaced in line with the actual value of the environment variable at build time:

```javascript
<p>{process.env.NEXT_PUBLIC_ENV_VARIABLE}</p>
```

Public environment variables are mostly used for storing constants or default values that you don't want to import or declare in multiple files. You can declare such variables once in a `.env*` file, as in the example above, and access them from anywhere in your code base. They are available both in the browser and in Node.js.

## Using environment variables in local development vs. production <a name="using-environment-variables-local-development-vs-production">

As mentioned above, the requirements of an application while in development may not be the same as those in production. Therefore, some environment variables may only be required in development, others in production, and some in both environments. Next.js supports all three out of the box. 

As we learned earlier, Next.js environment variables declared in the `.env.production` file are available only in the production environment, those in the `.env.development` file are available in the development environment, and those in the `.env` file are available in both environments. 

For example, if you declare the environment variables below in the `.env.production` file, they will be available only in the production environment:

```bash
BASE_URL='http://localhost:3000'
NEXT_PUBLIC_BASE_URL='http://localhost:3000'
```

Irrespective of the file in which you declare the above environment variables, the `BASE_URL` environment variable will be available in the Node.js environment because it is a private variable. And `NEXT_PUBLIC_BASE_URL` will be available in both the browser and Node.js environments because it is a public environment variable.

## Manipulating environment variables with `next.config.js` <a name="manipulating-environment-variables-next-config-js">

Next.js offers flexible ways of working with environment variables. You can use the legacy `env` property of the `next.config.js` file to configure environment variables, or the newer, more intuitive, and ergonomic `.env*` files described above. 

You can declare the environment variable as a property of the `env` object in the `next.config.js` file and access it in your code base as a property of the `process.env` object:

```javascript
module.exports = {
  env: {
    BASE_URL: "http://localhost:3000",
  },
};
```

Be aware that using the `next.config.js` file for your environment variables will inline the values of the variables at build time and bundle them in your frontend code, irrespective of whether you prefix the variable name with `NEXT_PUBLIC_` or not:

```javascript
export const App = () => {
  return <p>{process.env.BASE_URL}</p>
}
```

## Securely storing secrets for local development <a name="securely-storing-secrets-local-development">

Software development across remote, distributed teams requires the use of version control systems such as Git and cloud Git hosting services like GitHub, BitBucket, and GitLab. During development, certain secrets such as API endpoints, usernames, passwords, API keys, database connection strings, and other credentials that are specific to your local development environment must not be exposed. 

In Next.js, you can securely store secrets in the `env.local` file. You can add the `.env.local` file to your `.gitignore` file to avoid checking it into a version control system like Git and pushing it to a cloud Git hosting service like GitHub. Do not store secrets in other environment variables that are not meant for storing secrets. 

Checking environment variables to a version control system may result in incurring significant costs if unknown individuals get access to your API keys or production database connection string. 

You can share a template of the `env.local` file and its contents in a `.env.local.example` or `.env.local.template` file so that project contributors can set up their development environment using the file template.

## Dynamic environment variables in Next.js 13 <a name="dynamic-environment-variables-next-js-13">

Next.js will evaluate all references to environment variables and hard-code them in your client code at build time. After that, all the evaluated values won't respond to changes in the environment variable. 

If your frontend application needs access to dynamic environment variables at runtime, you should set up your own API and provide the variables to your client code. 

Similarly, dynamically looking up or destructuring environment variables in your frontend code, as in the example below, won't work. The value of the environment value will be `undefined`. Always access your environment variables using `process.env.ENV_VARIABLE_NAME` on the client side:

```javascript
const varName = "BASE_URL";
console.log(`${varName} = ${process.env[varName]}`);

const { BASE_URL } = process.env;
console.log(`${varName} = ${BASE_URL}`);
```

## Order of environment variable lookup in Next.js <a name="order-environment-variable-lookup-next-js">

As explained above, you can declare environment variables in different files. These files are for environment variables that are usually made available in specific environments. 

Next.js follows the order below when looking for an environment variable and stops after finding the variable it needs. The value of `NODE_ENV` is set to `development` in a development environment, `production` in a production environment, and `test` in a test environment:

1.  `process.env`
2.  `env.${NODE_ENV}.local`
3.  `env.local` (`env.local` is not checked when `NODE_ENV` is `test`)
4.  `env.${NODE_ENV}`
5.  `.env`

If you declare the same environment variable in multiple files, the environment variable declared in the lowest file in the above list wins.

## Interpolating environment variables in Next.js <a name="interpolating-environment-variables-next-js">

In Next.js, you can create an environment variable by referencing or composing other environment variables using the `${VARIABLE_NAME}` syntax. Next.js will expand and replace any referenced variable with its actual value. 

The example below uses the `BASE_URL` and `API_KEY` environment variables to create `API_URL`. The value of the `API_URL` variable will evaluate to `https://www.logrocket.com/api/v1?apiKey=12345`:

```bash
BASE_URL="https://www.logrocket.com"
API_KEY=12345
API_URL="${BASE_URL}/api/v1?apiKey=${API_KEY}"
```

Such composition avoids repetition and keeps your environment variable files organized. You can now reference each environment variable independently from your code base:

```javascript
console.log(process.env.BASE_URL);
console.log(process.env.API_KEY);
console.log(process.env.API_URL);
```

Cross-file environment variable referencing is also possible in Next.js. You can reference an environment variable declared in the `env.local` file from the `.env` file. However, you should pay attention to the order of the environment variable lookup as highlighted above if you have variables with similar names in different files. 

Referencing a variable declared in `.env.development` from `.env.production` and vice versa won’t work because those environment variables will only be available in their respective environments.

## Conclusion

Environment variables influence the way an application runs or behaves in different contexts and environments. Next.js, like most web frameworks, has the necessary setup for flexibly configuring and using environment variables in your application. 

In this article, we explored the differences between private and public environment variables in Next.js. We also learned about functionalities that allow you to declare development-only and production-only environment variables, such as the `.env.development` and `env.production` files. 

Finally, we learned that in a typical Next.js project, you only need the `.env.local` file to store credentials that you want to keep secret. Always add the `.env.local` file to your `.gitignore` file to avoid exposing your secrets in a version control system like Git. 

Happy coding!

---

## [LogRocket](https://lp.logrocket.com/blg/nextjs-signup): Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket](https://lp.logrocket.com/blg/nextjs-signup).

[![LogRocket Signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://lp.logrocket.com/blg/nextjs-signup)

[LogRocket](https://lp.logrocket.com/blg/nextjs-signup) is like a DVR for web and mobile apps, recording literally everything that happens on your Next.js app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — [start monitoring for free](https://lp.logrocket.com/blg/nextjs-signup).