name: environment-variables description: Use compile-time validated environment variables with t3-oss/env-nextjs. Ensures type-safe access to environment variables with automatic validation at build time. Use when accessing any environment variable or adding new environment configurations.
Environment Variables
Use type-safe, compile-time validated environment variables with automatic validation at build time using t3-oss/env-nextjs.
Overview
This project uses @t3-oss/env-nextjs to validate environment variables at build time, preventing runtime errors from missing or invalid configuration. All environment variables are defined in env.ts with Zod schemas and are validated when Next.js builds.
How It Works
- Build-Time Validation:
next.config.mjsimportsenv.ts, triggering validation before the app builds - Type Safety: TypeScript provides autocomplete and type checking for all environment variables
- Runtime Access: Import
envfrom@/envto access validated variables anywhere in the app
File Structure
/env.ts # Environment variable schema and validation
/next.config.mjs # Imports env.ts for build-time validation
/.env.local # Local development environment variables
/.env.example # Template showing all required variables
Usage Examples
Accessing Environment Variables
Before (process.env - not type-safe, no validation):
// ❌ No type checking, could be undefined
const apiKey = process.env.ANTHROPIC_API_KEY;
After (env - type-safe, validated):
// ✅ Type-safe, guaranteed to exist and be valid
import { env } from "@/env";
const apiKey = env.ANTHROPIC_API_KEY; // string (validated at build time)
Common Patterns
Server-side usage (Server Actions, API Routes):
import { env } from "@/env";
export async function createUser() {
const supabase = createClient<Database>(
env.NEXT_PUBLIC_SUPABASE_URL,
env.SUPABASE_SECRET_KEY // Server-only variable
);
}
Client-side usage (Components):
"use client";
import { env } from "@/env";
export function SupabaseProvider() {
// Only NEXT_PUBLIC_* variables are available on client
const client = createBrowserClient(
env.NEXT_PUBLIC_SUPABASE_URL,
env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY
);
}
Adding New Environment Variables
When adding a new environment variable, follow these steps:
1. Add to .env.example and .env.local
# .env.example
NEW_SERVICE_API_KEY=your-api-key-here
NEXT_PUBLIC_NEW_SERVICE_URL=https://api.example.com
2. Add to env.ts Schema
Determine if the variable is server-only or client-side (must start with NEXT_PUBLIC_):
Server-only variable:
// env.ts
export const env = createEnv({
server: {
// Add new server variable
NEW_SERVICE_API_KEY: z.string().min(1),
// ... existing variables
},
client: {
// ... existing client variables
},
runtimeEnv: {
// Add to runtimeEnv
NEW_SERVICE_API_KEY: process.env.NEW_SERVICE_API_KEY,
// ... existing mappings
},
});
Client-side variable (NEXT_PUBLIC_*):
// env.ts
export const env = createEnv({
server: {
// ... existing server variables
},
client: {
// Add new client variable
NEXT_PUBLIC_NEW_SERVICE_URL: z.string().includes("://"),
// ... existing client variables
},
runtimeEnv: {
// Add to runtimeEnv
NEXT_PUBLIC_NEW_SERVICE_URL: process.env.NEXT_PUBLIC_NEW_SERVICE_URL,
// ... existing mappings
},
});
3. Use in Your Code
import { env } from "@/env";
const apiKey = env.NEW_SERVICE_API_KEY; // Type-safe access
Validation Rules
Common Zod Validators
// Required string with minimum length
API_KEY: z.string().min(1)
// Optional string
OPTIONAL_KEY: z.string().optional()
// URL validation
SERVICE_URL: z.string().includes("://")
// Email validation
EMAIL: z.string().includes("@")
// Enum validation
NODE_ENV: z.enum(["development", "production", "test"])
// Number validation
PORT: z.coerce.number().min(1000).max(9999)
Special Cases
Email with optional display name:
DEV_EMAIL_FROM: z.string().includes("@").or(z.string().regex(/^.+\s<.+@.+>$/))
Optional environment variable:
ADMIN_EMAIL: z.string().includes("@").optional()
Build-Time Validation
When you run bun run build or bun run dev, Next.js automatically validates all environment variables:
# If validation fails:
❌ Invalid environment variables:
ANTHROPIC_API_KEY: Required
RESEND_API_KEY: Required
Skip Validation (CI/CD)
In CI/CD environments where environment variables aren't available during build:
SKIP_ENV_VALIDATION=true bun run build
Important Notes
- Never commit
.env.localor.env.production- these files are in.gitignore - Always update
.env.examplewhen adding new variables - Server variables are only accessible on the server (API routes, Server Components, Server Actions)
- Client variables must be prefixed with
NEXT_PUBLIC_and are exposed to the browser - Build fails if any required environment variable is missing or invalid
Reference
- Schema definition:
env.ts - Build validation:
next.config.mjs(importsenv.ts) - Example template:
.env.example - Documentation: https://env.t3.gg/docs/nextjs