Environment Variables
Create T3 App uses its newly published package @t3-oss/env-nextjsâ and zodâ under the hood for validating environment variables at runtime and buildtime by providing a simple logic in src/env.ts
.
env.ts
TLDR; If you want to add a new environment variable, you must add it to your .env
as it is defined in the src/env.ts
validator.
import { z } from "zod";
export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
});
T3 Env brings a new concept across the createEnv
, which is responsible for creating the schema and will include the main validation logic for client and server-sided environment variables.
For more information about how createEnv
internally works, check out the T3 Envâ docs
Using Environment Variables
When you want to use your environment variables, you can import them from the created env.ts
(or env.mjs
) and use them as you would normally do. If you import this on the client and try accessing a server-side environment variable, you will get a runtime error.
import { env } from "../../env.ts";
// `env` is fully typesafe and provides autocompletion
const dbUrl = env.DATABASE_URL;
import { env } from "../env.ts";
// â This will throw a runtime error
const dbUrl = env.DATABASE_URL;
// â
This is fine
const wsKey = env.NEXT_PUBLIC_WS_KEY;
.env.example
Since the default .env
file is not committed to version control, we have also included a .env.example
file, in which you can optionally keep a copy of your .env
file with any secrets removed. This is not required, but we recommend keeping the example up to date to make it as easy as possible for contributors to get started with their environment.
Some frameworks and build tools, like Next.js, suggest that you store secrets in a .env.local
file and commit .env
files to your project. This is not recommended, as it could make it easy to accidentally commit secrets to your project. Instead, we recommend that you store secrets in .env
, keep your .env
file in your .gitignore
and only commit .env.example
files to your project.
Adding Environment Variables
To ensure your build never completes without the environment variables the project needs, you will need to add new environment variables in two locations:
đ .env
: Enter your environment variable like you would normally do in a .env
file, i.e. KEY=VALUE
đ env.ts
: Add the appropriate validation logic for the environment variable by defining a Zod schema inside createEnv
, e.g. KEY: z.string()
, and destruct the environment variable from process.env
in the processEnv
object, e.g. KEY: process.env.KEY
.
Optionally, you can also keep .env.example
updated:
đ .env.example
: Enter your environment variable, but be sure to not include the value if it is secret, i.e. KEY=VALUE
or KEY=
Example
I want to add my Twitter API Token as a server-side environment variable
- Add the environment variable to
.env
:
TWITTER_API_TOKEN=1234567890
- Add the environment variable to
env.ts
:
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
TWITTER_API_TOKEN: z.enum(["development", "test", "production"]),
},
// ...
});
An empty string is still a string, so z.string()
will accept an empty string
as a valid value. If you want to make sure that the environment variable is
not empty, you can use z.string().min(1)
.
- Optional: Add the environment variable to
.env.example
and make sure not to include the secret
TWITTER_API_TOKEN=