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.
next-safe-env gives you a single env object where every variable is validated at startup, typed precisely, and automatically split between server and client bundles. Instead of scattering process.env.X calls across your codebase and discovering missing values mid-request, you define your schema once in src/env.ts and get full TypeScript autocomplete everywhere you import it.
Create src/env.ts
Define your server and client schemas. Pass each
process.env reference individually in runtimeEnv - this lets the Next.js bundler inline each value statically and prevents server vars from leaking into the client bundle.next-safe-env validates what is already in process.env. It does not load .env files. Next.js loads .env files automatically, so no extra setup is needed.Use it in a server context
Import
env in any server-side file - API routes, Server Components, server actions. All vars from both schemas are available here.Use it in a client component
Import the same
env object in Client Components. Client vars are fully typed and autocomplete. Server vars carry the ServerOnly<T> brand, which is visible in IDE tooltips.The
ServerOnly<T> brand is visible in IDE tooltips and communicates a variable’s origin at a glance, but it does not produce a TypeScript compile error on its own due to structural typing. To get a hard build-time error when env.ts is imported in a client bundle, add import 'server-only' at the top of src/env.ts. Next.js will then throw at build time if the module is included in any client bundle.NEXT_PUBLIC_ prefix enforcement
The nextjs adapter checks every key in your client schema before any validation runs. If a key is missing the NEXT_PUBLIC_ prefix, createEnv throws immediately:
undefined at runtime with no warning. next-safe-env surfaces the mistake at startup instead.
Browser context stripping
When your code runs in a browser context (typeof window !== 'undefined'), the nextjs adapter strips every non-NEXT_PUBLIC_ key from the returned env object before it reaches your component. This is a runtime safety net layered on top of the TypeScript enforcement - even if a server var somehow ends up referenced in a client bundle, its value will be undefined rather than the secret it holds.
On the server side, all vars from both schemas are returned unchanged.
Adapter auto-detection
You do not need to setadapter: 'nextjs' explicitly in most cases. next-safe-env auto-detects the correct adapter using this 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 + console.warn |
| Otherwise | node |
NEXT_RUNTIME automatically, so detection is reliable. Set adapter: 'nextjs' explicitly if you want to suppress the Pages Router heuristic warning or prefer predictable, self-documenting config.
What happens when validation fails
If any variable is missing or invalid, the app refuses to start and prints every problem at once. You never see just the first failure..env file or deployment environment and restart. The full list is always shown before exit.
