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.
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.3
Use env in your middleware logic
After
createEnv runs, only NEXT_PUBLIC_ vars are present on the returned object. Access them directly.Edge adapter behavior
Theedge 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:
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.
Edge adapter vs nextjs adapter
Both adapters strip server vars from the result, but they do so under different conditions:
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.

