Documentation Index
Fetch the complete documentation index at: https://next-safe-env.dev/llms.txt
Use this file to discover all available pages before exploring further.
createEnv() is the single entry point for next-safe-env. You call it once - typically in a dedicated src/env.ts file - and it validates every environment variable in your schema against runtimeEnv before your application serves a single request. If any variable is missing or malformed, it prints every problem at once and exits with a non-zero code. When all variables pass, it returns a fully-typed, frozen object.
Function signature
Config options
The schema for your server-only environment variables. Each key maps to a validator built with
str(), num(), bool(), url(), or port(), or to a Zod schema when using Zod interop.Variables defined here are branded as ServerOnly<T> in the returned object. They are never included in client bundles when the nextjs or edge adapter is active.The schema for environment variables that are safe to expose to the client bundle. Each key follows the same validator syntax as
server.When the nextjs adapter is active (including auto-detected), every key in client must be prefixed with NEXT_PUBLIC_. When the vite adapter is active, every key must be prefixed with VITE_. The adapter throws immediately in beforeValidate if a key violates this rule.An explicit map of every key in
server and client to its runtime value. You must list each key individually - do not spread the whole process.env object.Bundlers like Next.js and Vite inline each process.env.VAR reference statically at build time. Passing the entire process.env object prevents this inlining, defeats tree-shaking, and can leak server variables into the client bundle.The adapter that controls prefix enforcement and runtime key-stripping. When omitted,
Pass
createEnv() auto-detects the adapter using the following order:| Condition | Adapter selected |
|---|---|
process is undefined or has no version | edge |
process.env.NEXT_RUNTIME is set | nextjs |
Any client key starts with NEXT_PUBLIC_ | nextjs (with a console.warn) |
Any client key starts with VITE_ | vite (with a console.warn) |
| Otherwise | node |
adapter explicitly to suppress the Pages Router and Vite detection warnings.nextjs- enforcesNEXT_PUBLIC_prefix on allclientkeys; strips server vars from the result in browser context.node- no prefix rules, no key-stripping. Use for Express, Fastify, CLI scripts, and plain Node.js apps.edge- strips all non-NEXT_PUBLIC_keys from the result unconditionally. Server vars are still validated before being stripped.vite- enforcesVITE_prefix on allclientkeys; strips server vars from the result in browser context.
When
true, field-level validation and beforeValidate are skipped entirely. The afterValidate hook still runs, so adapter key-stripping still applies. Raw string values from runtimeEnv are returned in the typed shape.Use this in test environments where some variables are intentionally absent. Never set it to true in production or in CI validation steps.A custom handler called instead of the default
console.error(err.format()) + process.exit(1) when one or more variables fail validation.The handler receives a ValidationErrorShape (satisfied by EnvValidationError) and must never return. If it returns, execution continues with an invalid env object.Return type
createEnv() returns a Readonly-frozen object. Server variables carry the ServerOnly<T> brand; client variables are their plain inferred types.
Object.freeze() at runtime. Mutation will silently fail in non-strict mode and throw a TypeError in strict mode.
Each key from the
server schema returns its inferred type branded as ServerOnly<T>. The brand is T & { readonly [SERVER_ONLY_BRAND]: void } - assignment-compatible with T in TypeScript’s structural type system, and visible in IDE tooltips.For a hard compile error when client components import server vars, add import 'server-only' at the top of your env.ts file.Each key from the
client schema returns its plain inferred type - string, number, boolean, or their | undefined variants.Complete usage example
createEnv() does not load .env files. It validates what is already in process.env. Use Next.js’s built-in .env support or dotenv to load variables before calling createEnv().
