Skip to content
LogoLogo

Getting Started

This page walks you through installing @zap-studio/env and validating your first env object. For deeper details, check the other pages in this section.

Install

You also need a schema library that implements Standard Schema, such as Zod, Valibot, or ArkType.

Define a Schema

Split your vars into server (server-only) and client (readable everywhere, exposed to the browser). Use shared for vars that don't need the client/server split at all.

import { z } from "zod";
 
const schema = {
  server: {
    DATABASE_URL: z.string().url(),
  },
  client: {
    NEXT_PUBLIC_API_URL: z.string().url(),
  },
  clientPrefix: "NEXT_PUBLIC_",
};

clientPrefix is required as soon as client is declared — see server/client/shared for why.

Validate Your Env

Call createEnvironment(...) with the schema and the resolved env object to validate against.

import { createEnvironment } from "@zap-studio/env";
import { z } from "zod";
 
export const env = createEnvironment({
  server: {
    DATABASE_URL: z.string().url(),
  },
  client: {
    NEXT_PUBLIC_API_URL: z.string().url(),
  },
  clientPrefix: "NEXT_PUBLIC_",
  runtimeEnvStrict: {
    DATABASE_URL: process.env.DATABASE_URL,
    NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
  },
});

Each var is on its own line. Bundlers (webpack, Next.js, Vite) replace a literal process.env.X line at build time — they cannot do this with a spread of the whole object. This matters for client vars, since they must end up in the browser bundle. See Advanced Options for when runtimeEnv: process.env is fine instead.

If any declared var fails validation, createEnvironment throws an EnvironmentValidationError listing every invalid key.

Read Values

The returned env object is fully typed from your schemas. On the server, every declared var is readable. Off the server, reading a server-only key throws instead of silently returning undefined.

env.DATABASE_URL; // string — throws if read from a client bundle
env.NEXT_PUBLIC_API_URL; // string — readable everywhere

isServer defaults to typeof window === "undefined". Set it yourself when that default is wrong, such as in some edge or SSR contexts — see server/client/shared.

Next Steps