Back to blog

Published on Wednesday, February 26, 2025

Next.js Env Validation with @t3-oss/env-nextjs

Next.js Env Validation with @t3-oss/env-nextjs

Video Tutorial

Introduction

Environment variables are a crucial part of modern web applications, especially in frameworks like Next.js. They store sensitive data such as API keys, database URLs, and configuration settings. However, relying on raw process.env variables can lead to runtime errors and unexpected behavior. This is where type safety comes in.

In this guide, we will explore how to implement type safety for environment variables in Next.js using @t3-oss/env-nextjs. This package helps validate and enforce type constraints on environment variables at build time, reducing the risk of misconfigurations.

Why Use @t3-oss/env-nextjs?

Using @t3-oss/env-nextjs provides several benefits:

  • Type safety: Ensures environment variables have correct types.
  • Validation: Prevents missing or incorrectly formatted values.
  • Separation of concerns: Differentiates between client and server variables.
  • Better developer experience: Catches errors early and provides autocompletion in TypeScript.

Step 1: Install Dependencies

Run the following command to install the required packages:

npm install @t3-oss/env-nextjs zod

We use Zod, a powerful schema validation library, to define and enforce the structure of our environment variables.

Step 2: Define Environment Variables in a .env.local File

Ensure that your .env.local file contains the necessary environment variables:

.env.local
# Public envs (expose in browser)
NEXT_PUBLIC_SITE_TITLE="My Next.js App"
NEXT_PUBLIC_SITE_URL=https://example.com

# Private envs (not expose in browser)
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
SECRET_KEY=supersecuresecretkeythatshouldbekeptprivate

Step 3: Create an env.ts File

Inside your Next.js project, create a file named env.ts in the root directory or in a src folder:

src/env.ts
import { z } from "zod";
import { createEnv } from "@t3-oss/env-nextjs";

export const env = createEnv({
  client: {
    NEXT_PUBLIC_SITE_TITLE: z.string().min(1),
    NEXT_PUBLIC_SITE_URL: z.string().url(),
  },
  server: {
    DATABASE_URL: z.string().min(1),
    SECRET_KEY: z.string().min(32),
  },
  experimental__runtimeEnv: {
    NEXT_PUBLIC_SITE_TITLE: process.env.NEXT_PUBLIC_SITE_TITLE,
		NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
  },
});

Step 4: Use Environment Variables in Your Code

Now that we have type-safe environment variables, we can safely use them in our application:

Server-side Usage (API Routes, getServerSideProps, Middleware):

import { env } from "../env";

export default function handler(req, res) {
  res.json({
    message: "Database URL is " + env.DATABASE_URL
  });
}

Client-side Usage (React Components):

import { env } from "../env";

export default function Home() {
  return <h1>Welcome to {env.NEXT_PUBLIC_SITE_TITLE}</h1>;
}

Conclusion

Using @t3-oss/env-nextjs with Zod provides a robust, type-safe, and error-proof way to manage environment variables in a Next.js application. This approach ensures that variables are always correctly defined, reducing runtime errors and making your codebase more maintainable.

By following the steps in this guide, you can enforce validation, improve security, and enhance developer experience in your Next.js projects.