Declare a schema. Resolve a typed env at boot.
"@vlandoss/env"Describe every variable in a single Standard Schema contract — Zod, Valibot, ArkType. Resolve it against per-environment config files and your environment variables at boot. Missing or malformed values fail the process before user code ever reads them.
import { schema, type Config } from "@vlandoss/env";
import * as z from "zod";
export const Env = schema({
server: {
HOST: z.string(),
PORT: z.coerce.number().int().positive()
},
db: {
URL: z.string()
},
});
export type EnvConfig = Config<typeof Env>;process.env is a string-map of unknowns. The first time you find out a value is missing is when something else crashes downstream.
.env files duplicated per environment, secrets and defaults tangled.
A versioned config file per environment. Secrets stay in your env vars.
process.env.PORT is a string. process.env.MISSING is undefined. Silent.
env.server.PORT is number. Missing values throw at boot, with the dot-path.
Locked to one validator. Locked to one runtime. Locked to one bundler.
Standard Schema in. Any runtime out. Opt-in adapters for Node, Vite, React.
The core stays portable. Filesystem, bundlers, and browser hydration live in opt-in adapters with their own peer dependencies.
Declare a schema. Resolve a typed env at boot.
"@vlandoss/env"Discover & load per-environment config files from disk.
"@vlandoss/env/fs"Vite plugin: alias #config, inject envName into the bundle.
"@vlandoss/env/vite"<EnvScript /> ships the server-resolved env to the browser.
"@vlandoss/env/react"Opinionated Zod primitives: port, host, bool, secret…
"@vlandoss/env/zod"camelCase keys are converted automatically. Override the rare exception with a one-line entry in vars.
| schema path | env var |
|---|---|
server.PORT | →SERVER_PORT |
db.URL | →DB_URL |
sessionCookie.PREFIX | →SESSION_COOKIE_PREFIX |
db.kit.LOGGING | →DB_KIT_LOGGING |
PORT | →PORT |
defineEnv({
schema: Env,
vars: {
db: { URL: "DATABASE_URL" },
public: {
$: null, // flat branch
APP_NAME: "PUBLIC_APP_NAME"
},
},
});