Skip to main content

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.

The Edge Runtime environment used by Next.js Middleware and Vercel Edge Functions is not a full Node.js process. It runs a Web API subset and only exposes NEXT_PUBLIC_ variables at runtime - server-only secrets are never available there. next-safe-env provides a dedicated edge adapter that reflects this constraint: server vars are validated at startup but unconditionally stripped from the returned object, so your types match what is actually accessible.
1

Install next-safe-env

Add the package to your project.
npm install next-safe-env
2

Create your env config in middleware.ts

Define your schema with adapter: 'edge'. Keep the server schema empty or omit server vars - they are validated but never returned.
// middleware.ts
import { createEnv, str, url } from 'next-safe-env'

export const env = createEnv({
  server: {},  // prefer empty - server vars are validated but stripped from the result
  client: {
    NEXT_PUBLIC_API_URL:  url(),
    NEXT_PUBLIC_APP_NAME: str().default('My App'),
  },
  runtimeEnv: {
    NEXT_PUBLIC_API_URL:  process.env.NEXT_PUBLIC_API_URL,
    NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME,
  },
  adapter: 'edge',
})
3

Use env in your middleware logic

After createEnv runs, only NEXT_PUBLIC_ vars are present on the returned object. Access them directly.
// middleware.ts (continued)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const apiUrl = env.NEXT_PUBLIC_API_URL    // string
  const appName = env.NEXT_PUBLIC_APP_NAME  // string

  // use apiUrl or appName in your middleware logic
  return NextResponse.next()
}

Edge adapter behavior

The edge adapter applies two rules to the validation pipeline: Before validation - if your server schema contains any keys, the adapter emits a console.warn to alert you that those vars will not be accessible:
[next-safe-env] Edge adapter: server vars (API_SIGNING_KEY) will be validated
but stripped from the result - they are not accessible in Edge Runtime.
Validation still runs for those server vars. If a server var is required and missing, createEnv still fails at startup with a validation error. The warning is informational, not a skip. After validation - the adapter unconditionally strips every key that does not start with NEXT_PUBLIC_ from the returned object. This always happens, regardless of typeof window, because the Edge Runtime has no window object.
Do not put secrets in your server schema when using the edge adapter. They are validated but never returned, so accessing them on the env object at runtime will yield undefined despite passing validation. Keep your edge server schema empty, or move secrets to a separate createEnv call used only in a Node.js context.

Edge adapter vs nextjs adapter

Both adapters strip server vars from the result, but they do so under different conditions:
AdapterWhen server vars are stripped
nextjsOnly in browser context (typeof window !== 'undefined')
edgeAlways, unconditionally
Use adapter: 'nextjs' for App Router routes and Server Components, where you need server vars to be available in the Node.js context. Use adapter: 'edge' in middleware.ts and any Vercel Edge Function, where server vars are structurally inaccessible regardless of context.
Set adapter: 'edge' explicitly rather than relying on auto-detection. The auto-detection heuristic selects edge when process is undefined or has no version, but Middleware runs in a constrained environment where the detection can be ambiguous. Being explicit makes your intent clear and avoids unexpected adapter selection.