GitHub

Customization

Below are some examples of how you can customize the behavior of the library. The default values are shown in the snippets below.

Skipping validation

⚠️

Skipping validation is not encouraged and will lead to your types and runtime values being out of sync. It is available to let you opt out of validation during linting (or similar), or if you're building with Docker and not all environment variables are present when building the image.

src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Tell the library to skip validation if condition is true.
  skipValidation: false,
});
src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Tell the library to skip validation if condition is true.
  skipValidation: false,
});

Overriding the default error handler

src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Called when the schema validation fails.
  onValidationError: (error: ZodError) => {
    console.error(
      "❌ Invalid environment variables:",
      error.flatten().fieldErrors
    );
    throw new Error("Invalid environment variables");
  },
  // Called when server variables are accessed on the client.
  onInvalidAccess: (variable: string) => {
    throw new Error(
      "❌ Attempted to access a server-side environment variable on the client"
    );
  },
});
src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Called when the schema validation fails.
  onValidationError: (error: ZodError) => {
    console.error(
      "❌ Invalid environment variables:",
      error.flatten().fieldErrors
    );
    throw new Error("Invalid environment variables");
  },
  // Called when server variables are accessed on the client.
  onInvalidAccess: (variable: string) => {
    throw new Error(
      "❌ Attempted to access a server-side environment variable on the client"
    );
  },
});

Tell when we're in a server context

src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Tell the library when we're in a server context.
  isServer: typeof window === "undefined",
});
src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Tell the library when we're in a server context.
  isServer: typeof window === "undefined",
});

Treat empty strings as undefined

By default, T3 Env will feed the environment variables directly to the Zod validator. This means that if you have an empty string for a value that is supposed to be a number (e.g. PORT= in a ".env" file), Zod will flag it as a type mismatch violation. Additionally, if you have an empty string for a value that is supposed to be a string with a default value (e.g. DOMAIN=in an ".env" file), the default value will never be applied. In order to solve these issues, you can set theemptyStringAsUndefinedoption totrue.

src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Treat empty strings as undefined.
  emptyStringAsUndefined: false,
});
src/env.ts
import { createEnv } from "@t3-oss/env-core";
 
export const env = createEnv({
  // ...
  // Treat empty strings as undefined.
  emptyStringAsUndefined: false,
});

Extending presets

Your env object may extend other presets by using the extends property. This can be used to include system environment variables for your deployment provider, or if you have a monorepo with multiple packages that share some environment variables.

src/env.ts
import { createEnv } from "@t3-oss/env-core";
import { vercel } from "@t3-oss/env-core/presets";
 
export const env = createEnv({
  // ...
  // Extend the Vercel preset.
  extends: [vercel()],
});
 
env.VERCEL_URL; // string
src/env.ts
import { createEnv } from "@t3-oss/env-core";
import { vercel } from "@t3-oss/env-core/presets";
 
export const env = createEnv({
  // ...
  // Extend the Vercel preset.
  extends: [vercel()],
});
 
env.VERCEL_URL; // string

T3 Env ships the following presets out of the box, all importable from the /presets entrypoint.

  • vercel - Vercel environment variables. See full list here.
  • uploadthing - All environment variables required to use UploadThing. More info here.
  • render - Render environment variables. See full list here.
  • railway - Railway provided system environment variables. See full list here.

Feel free to open a PR with more presets!

A preset is just like any other env object, so you can easily create your own:

// packages/auth/env.ts
import { createEnv } from "@t3-oss/env-core";
export const env = createEnv({
  // ...
});
 
// apps/web/env.ts
import { createEnv } from "@t3-oss/env-nextjs";
import { env as authEnv } from "@repo/auth/env";
 
export const env = createEnv({
  // ...
  extends: [authEnv],
});
// packages/auth/env.ts
import { createEnv } from "@t3-oss/env-core";
export const env = createEnv({
  // ...
});
 
// apps/web/env.ts
import { createEnv } from "@t3-oss/env-nextjs";
import { env as authEnv } from "@repo/auth/env";
 
export const env = createEnv({
  // ...
  extends: [authEnv],
});