#
Environment variables
Environment variables are the primary means through which to pass configuration to your app at both build-time and runtime.
QuickDapp follows the Next.js conventions when it comes to specifying environment variables for your app.
The dotenv loads environment varibles from various .env*
files in the project root folder whilst still allowing for overrides specified directly via the shell/terminal environment itself.
Environment variables are loaded in the following order, with later places taking precendence over earlier ones:
.env
.env.development
or.env.production
, depending on the value of theNODE_ENV
environment variable..env.local
What this means is that if the same environment variable is declared in multiple places then its final value during runtime is determined by the above order.
Some key points to note:
- The
.env
file is required. This file should contain any values which are unlikely to change across environments. It gets bundled into production and Docker builds and will be checked into source control. - The
.env.development
and.env.production
files are already git-ignored and should never be checked into source control since they are intended to contain sensitive information (e.g API keys).- The
.env.development
file gets loaded when the app is run in dev server mode. - The
.env.production
file gets loaded when building production version of the app, running the production version and also gets bundled into Docker images.
- The
- The
.env.local
file is for further customization in all environments, e.g if you are temporarily testing a value different to the default. It also does not get checked into version control. However, note that it also does not get bundled into Docker images.
DO NOT store sensitive information (e.g API keys) in the .env
file. Use the environment-specific or .env.local
files to store such information.
The files use the INI file format:
# a comment
SERVER_WALLET_PRIVATE_KEY=0x...
# quotes are allowed
APP_NAME="quickest dapp"
# another comment after some space
NEXT_PUBLIC_BASE_URL=http://localhost:3000
Example
Let's assume that:
.env
containsAPP_NAME=root
.env.development
containsAPP_NAME=dev
.env.production
containsAPP_NAME=prod
.env.local
containsAPP_NAME=local
When the dev server is run, at runtime the process.env.APP_NAME
value will equal local
. If we delete the .env.local
file and restart the server then the runtime value will be dev
.
If we restore the .env.local
file but this time run the production server then the runtime value will be local
. However, if we delete the .env.local
file again and restart the production server then the runtime value will be prod
.
#
Client-side vs Server-side
There are two types of environment variables: client-side and server-side.
Client-side environment variables are made available client-side in the browser and are prefixed with NEXT_PUBLIC_
to indicate this. Any environment variable that needs to be accessible client-side must be given this prefix. Since these variables are accessible browser-side they must not hold sensitive passwords, API keys or any other information that browser clients are not meant to see.
Server-side environment variables are only available server-side and are never sent to the browser. Thus these variables can hold sensitive passwords, API keys and other information that browser clients are not meant to see.
Note: All client-side environment variables are automatically available server-side code.
#
Overriding at runtime
Server-side environment variables can be overridden at runtime by setting them in the shell/environment prior to starting the app. For example:
LOG_LEVEL=warning pnpm prod
However, client-side environment variables get bundled (i.e. hardcoded) into the frontend application as part of the build process and thus cannot be overridden at runtime.
#
Programmatic access
The src/config/**
modules are responsible for loading, parsing and ensuring the right syntax for each of the various environment variables. It is recommended that your code access environment variables through this rather than accessing process.env
directly.
#
Client-side
import { clientConfig } from '@/config/client'
console.log(clientConfig.NEXT_PUBLIC_BASE_URL) // http://localhost:3000
#
Server-side
import { serverConfig } from '@/config/server'
console.log(serverConfig.NEXT_PUBLIC_APP_NAME) // quickest dapp
#
Adding your own variables
To add your own custom environment variable:
- Add your variable to either
src/config/client.ts
orsrc/config/server.ts
depending on whether it is a client-side or server-side variable. Follow the conventions used for existing environment variables, including removing theNEXT_PUBLIC_
prefix at runtime for client-side variables. - Add a default value for your variable to the
.env
file, again following the conventions shown in in the file for other variables. If your variable does not have a default value then set its value inside.env
to the empty string (""
). - Optionally add a value override for your variable to either or both of
.env.development
and.env.production
.
#
Example
Let's add a client-side variable called SHOW_COOKIE_BANNER
which will specify whether a cookie consent banner should be shown to the user. Our requirements for this variable:
- It can only be a boolean value -
true
orfalse
. - It should be
false
in development environments. - It should be
true
in production environments.
First, we will edit src/config.client.ts
to add the variable:
// File: src/config/client.ts
export interface ClientConfigInterface {
...
SHOW_COOKIE_BANNER: boolean
}
export const clientConfig = (() => {
const env = require('env-var').from({
...
SHOW_COOKIE_BANNER: process.env.NEXT_PUBLIC_SHOW_COOKIE_BANNER,
})
return Object.freeze({
...
SHOW_COOKIE_BANNER: env.get('SHOW_COOKIE_BANNER').asBoolean(),
}) as ClientConfigInterface
})()
In .env
we set it to false
:
# File: .env
...
NEXT_PUBLIC_SHOW_COOKIE_BANNER=false
In .env.production
we set it to true
:
# File: .env.production
...
NEXT_PUBLIC_SHOW_COOKIE_BANNER=true