The correct way to load environment variables in Next.js
Load environment variables with build-time type-safety in Next.js 15
Published June 2, 2025 (Updated June 2, 2025)

This article has been updated for the latest Next.js version 15
GitHub repository: https://github.com/AustinShelby/the-correct-way-to-load-environment-variables-in-nextjs
This will be the only post you will ever need on this subject, and I can guarantee you will never again crash your production environment because you mistyped API_KEY.
If you have ever written code that looks like this:
Then you might have a nasty bug on your hands!
Here's what I mean.
In a scenario where you build the application without having set the API_KEY
environment variable the application will use undefined
instead.
Obviously undefined
is not the correct api key which will make any request using that URL fail.
The problem here is that when the error surfaces, the message will be very misleading and look something like this:
Error: Unauthorized
And this error will only show up when you send a request to the URL.
If calling the API is an essential feature, the application should not have even been built without the API key being available.
Naively expecting the API_KEY
environment variable to exist will hide the bug and make this problem a pain to debug due to the misleading error message.
When a problem exists that causes the application to not function, the application needs to fail immediately and visibly.
How to load environment variables in Next.js with type-safety
Create a .env
file. Here you will put all of your environment variables you want to use on your local development environment.
Next.js automatically adds this file to .gitignore
so you don't have to worry about it ending up in your version control system.
All environment variables are available on the server-side.
Only environment variables that are prefixed with NEXT_PUBLIC_
are available on the client-side.
Now to the bread and butter.
Validating environment variables for type-safety
Create a validateEnvironmentVariables.ts
file with this code to validate the environment variables and extend the NodeJS namespace in a type-safe way.
Let's break it down line by line and see what it does.
On lines 1 and 2, we import zod, which we use to validate our environment variables and @next/env which we use to load the environment variables from the local .env
file.
On lines 4 to 7, we define the schema for our environment variables. We define a required string schema for the variables API_KEY
and NEXT_PUBLIC_MESSAGE
that we defined in our .env
file.
On line 9, we infer a type from our zod schema.
On line 11, we save our current working directory location to a variable projectDir.
On line 13, we use the loadEnvConfig to load environment variables either from the local .env
file.
On lines 15 to 19, we extend the ProcessEnv interface with the type of our zod schema.
To summarize, we load the environment variables either from a .env
file or from the environment and validate that they fit our schema. Then we extend the NodeJS namespace with the type of our schema so we get type-safe autocompletions in our IDE.
Adding a build time check
To run this environment variable check before we build our application, we can add a pre-build step in our package.json file.
On line 10, we add the predev
command which runs before you run npm run dev
automatically.
On line 11, we add the prebuild
command which runs before you run npm run build
automatically.
Note: You need to use Node.js version 22.6.0 or higher. If you are using Node.js version 23.6.0 or higher, you can remove the
--experimental-strip-types
.
Extra
Create a .env.example
file so anyone who pulls your repository knows what environment variables they should set.
Also add the following line to your .gitignore
file to make sure the .env.example
file gets committed to the repository.
Why this is the correct way to load environment variables
In a case where you forgot to add the environment variables API_KEY
or NEXT_PUBLIC_MESSAGE
, the application won't even build, and it will throw an error saying that the environment variable wasn't found.
Our application now fails immediately and visibly.
This is called failing fast.
It is part of the clean code principles, which you can read more about here: https://www.martinfowler.com/ieeeSoftware/failFast.pdf.
Because we are using TypeScript, we can be 100% sure that all the environment variables exist.
Additionally, TypeScript helps us with autocompletions.
Conclusion
While this might seem pedantic, keeping these small things in your mind while writing code will make you a better software engineer.