Skip to content
Configuration25-40 min

Environment Validation with Zod

This guide creates a typed env module, validates required variables, separates server and client config, and wires validation into builds.

TypeScriptZodNode.js

Prerequisites

  • A TypeScript project.
  • Environment variables loaded by your runtime or hosting provider.
  • A list of required secrets and public config values.
1

Install Zod

Implementation snippet
npm install zod
2

Create the env schema

Implementation snippet
import { z } from "zod";

const envSchema = z.object({
  NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
  DATABASE_URL: z.string().url(),
  JWT_ACCESS_SECRET: z.string().min(32),
  STRIPE_SECRET_KEY: z.string().startsWith("sk_"),
  APP_URL: z.string().url(),
});

export const env = envSchema.parse(process.env);
3

Use the typed env object

  1. Import `env` wherever server config is needed.
  2. Stop reading `process.env` directly across the codebase.
  3. Let TypeScript autocomplete available config keys.
  4. Fail startup immediately when required config is missing.
Implementation snippet
import { env } from "./env";

app.listen(3000, () => {
  console.log(`API running for ${env.NODE_ENV} at ${env.APP_URL}`);
});
4

Separate public client env

Client-side variables are visible to users. Keep secrets server-only and expose only safe public values.

Implementation snippet
const clientEnvSchema = z.object({
  VITE_APP_URL: z.string().url(),
  VITE_PUBLIC_ANALYTICS_ID: z.string().optional(),
});

export const clientEnv = clientEnvSchema.parse(import.meta.env);
5

Run validation before build

Implementation snippet
"scripts": {
  "env:check": "tsx src/env.ts",
  "prebuild": "npm run env:check",
  "build": "vite build"
}
6

Verification checklist

Checklist
  • Removing DATABASE_URL causes startup or build to fail.
  • Invalid URL values produce readable Zod errors.
  • Client env does not include private keys.
  • Production hosting has every required variable configured.

Need implementation help?

Want this built correctly in your codebase?

Send us your stack, repo context, and the feature you need. We will help you implement it cleanly and hand over the working code.

Free scoping callFixed timelineFull source ownership
Get implementation help