Env typing and config
Validate and type environment variables; expose safe client vars with NEXT_PUBLIC; centralize config for server and client.
Intro
Goal: Centralize validated environment variables and keep types in sync. You will parse process.env with zod, export a typed env object, and expose only NEXT_PUBLIC_* to the client.
- Runtime validation
- Server vs client exposure
- Single source of truth
Schemas & parser
Create separate schemas for server and client. Fail fast on invalid config during boot.
// app/lib/env.ts
import { z } from "zod"
const serverSchema = z.object({
NODE_ENV: z.enum(["development", "test", "production"]),
DATABASE_URL: z.string().url(),
API_SECRET: z.string().min(1)
})
const clientSchema = z.object({
NEXT_PUBLIC_API_BASE: z.string().url()
})
function parseEnv<T extends z.ZodTypeAny>(schema: T, source: Record<string, unknown>) {
const r = schema.safeParse(source)
if (!r.success) {
console.error(r.error.format())
throw new Error("Invalid environment variables")
}
return r.data as z.infer<T>
}
export const serverEnv = parseEnv(serverSchema, process.env)
export const clientEnv = parseEnv(clientSchema, process.env)All lessons in this course
- App Router types; server vs client components
- Data fetching & action typing
- Env typing and config