> ## 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.

# Get started with next-safe-env

> Install next-safe-env and define your first typed, validated environment schema in under 5 minutes, with automatic startup crash on missing vars.

This guide walks you through installing `next-safe-env`, writing your first environment schema, importing typed values in your app, and understanding what happens when a variable is missing or invalid. The whole setup takes less than five minutes.

<Steps>
  <Step title="Install">
    Add `next-safe-env` to your project using your package manager of choice.

    <CodeGroup>
      ```bash npm theme={null}
      npm install next-safe-env
      ```

      ```bash pnpm theme={null}
      pnpm add next-safe-env
      ```

      ```bash yarn theme={null}
      yarn add next-safe-env
      ```
    </CodeGroup>
  </Step>

  <Step title="Create src/env.ts">
    Create a single file that defines your entire environment schema. Split your variables into `server` (never exposed to the browser) and `client` (safe to use anywhere). Every key in `runtimeEnv` must reference its corresponding `process.env` value individually - do not spread the whole `process.env` object, as bundlers need individual references to inline values statically and keep server vars out of the client bundle.

    ```typescript src/env.ts theme={null}
    import { createEnv, str, url, port, bool } from 'next-safe-env'

    export const env = createEnv({
      server: {
        DATABASE_URL: url(),                              // must be a valid URL
        JWT_SECRET:   str().min(32),                      // string, at least 32 chars
        SMTP_PORT:    port().default(587),                // number, defaults to 587
        NODE_ENV:     str().enum(['development', 'production', 'test']),
        REDIS_URL:    url().optional(),                   // valid URL or undefined
      },
      client: {
        NEXT_PUBLIC_API_URL:      url(),
        NEXT_PUBLIC_APP_NAME:     str().default('My App'),
        NEXT_PUBLIC_ENABLE_DEBUG: bool().default(false),
      },
      // Pass each variable individually, not process.env as a whole.
      runtimeEnv: {
        DATABASE_URL:             process.env.DATABASE_URL,
        JWT_SECRET:               process.env.JWT_SECRET,
        SMTP_PORT:                process.env.SMTP_PORT,
        NODE_ENV:                 process.env.NODE_ENV,
        REDIS_URL:                process.env.REDIS_URL,
        NEXT_PUBLIC_API_URL:      process.env.NEXT_PUBLIC_API_URL,
        NEXT_PUBLIC_APP_NAME:     process.env.NEXT_PUBLIC_APP_NAME,
        NEXT_PUBLIC_ENABLE_DEBUG: process.env.NEXT_PUBLIC_ENABLE_DEBUG,
      },
    })
    ```

    The available validators are:

    | Validator | Output type | Notes                                          |
    | --------- | ----------- | ---------------------------------------------- |
    | `str()`   | `string`    | Raw string, no coercion                        |
    | `num()`   | `number`    | Coerces `"3000"` → `3000`                      |
    | `bool()`  | `boolean`   | Coerces `"true"/"1"/"yes"/"on"` → `true`       |
    | `url()`   | `string`    | Shorthand for `str().url()`                    |
    | `port()`  | `number`    | Shorthand for `num().port()` - integer 1–65535 |

    All validators are chainable. Common modifiers:

    ```typescript theme={null}
    str().min(8).max(64)                                     // length constraints
    str().regex(/^[a-z_]+$/)                                 // pattern match
    str().enum(['debug', 'info', 'warn', 'error'])           // literal union
    num().int().min(1).max(100).default(10)                  // integer with bounds
    url().optional()                                         // valid URL or undefined
    bool().default(false)                                    // boolean with fallback
    ```
  </Step>

  <Step title="Use env in your app">
    Import the `env` object anywhere in your project. Server vars and client vars are all available on the same object, with types fully inferred from your schema.

    ```typescript app/api/auth/route.ts theme={null}
    import { env } from '@/env'

    export async function POST() {
      const db    = await connectDB(env.DATABASE_URL)  // string
      const port  = env.SMTP_PORT                      // number, not string
      const debug = env.NEXT_PUBLIC_ENABLE_DEBUG        // boolean
    }
    ```

    ```typescript app/components/Header.tsx theme={null}
    import { env } from '@/env'

    export function Header() {
      // Client vars are fully typed and available in both server and client components.
      return <h1>{env.NEXT_PUBLIC_APP_NAME}</h1>
    }
    ```

    <Tip>
      Server vars carry a `ServerOnly<T>` brand visible in IDE tooltips, making their origin clear at a glance. For a hard compile error that prevents client components from importing server vars, add `import 'server-only'` at the top of your `env.ts` file.
    </Tip>
  </Step>

  <Step title="What happens on failure">
    If any variable is missing or invalid, `next-safe-env` refuses to start the app and prints every problem at once - no hunting for the first `undefined` at runtime.

    ```text theme={null}
    [next-safe-env] Environment validation failed - 3 error(s):

      ✗ DATABASE_URL     - Required. Expected a valid URL. Got: "postgres-localhost"
      ✗ JWT_SECRET       - Too short. Must be ≥ 32 characters. Got length: 12
      ✗ SMTP_PORT        - Invalid port. Must be 1–65535. Got: "99999"

      Server vars:  2 valid, 3 invalid
      Client vars:  2 valid, 0 invalid

      Set the correct values in your .env file or deployment environment and restart.
    ```

    Fix the values in your `.env` file or deployment environment and restart. The error lists every failing field so you can fix them all in one pass.
  </Step>
</Steps>

<Note>
  `next-safe-env` validates what is already in `process.env`. It does not load `.env` files on its own. Use [Next.js built-in `.env` support](https://nextjs.org/docs/app/building-your-application/configuring/environment-variables) or `dotenv` to load your `.env` files first, then `next-safe-env` will validate and type whatever ends up in `process.env`.
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Next.js guide" icon="layer-group" href="/guides/nextjs">
    Set up server/client splitting, `NEXT_PUBLIC_` prefix enforcement, and the `server-only` module guard.
  </Card>

  <Card title="Node.js guide" icon="node-js" href="/guides/nodejs">
    Use next-safe-env in plain Node.js servers, APIs, and CLI scripts.
  </Card>
</CardGroup>
