@lunx/plugin-env
Schema-validated, type-safe environment variable access. Enforces the LUNX_PUBLIC_ browser exposure boundary so backend secrets never leak into your client bundle.
Installation
bash
npm install --save-dev @lunx/plugin-envtypescriptlunx.config.ts
import { defineConfig } from 'lunx' import env from '@lunx/plugin-env' export default defineConfig({ framework: 'react', plugins: [ env({ schema: './src/env.schema.ts', // optional: path to Zod schema }), ], })
How it works
At build time, plugin-env intercepts all import.meta.env accesses and:
- Validates each value against your Zod schema (optional but recommended)
- Statically replaces the access with the actual value in the bundle
- Blocks any variable without the
LUNX_PUBLIC_prefix from being bundled - Throws a build-time error if a required variable is missing
Defining your schema
typescriptsrc/env.schema.ts
import { z } from 'zod' export const envSchema = z.object({ // Required browser-safe variables LUNX_PUBLIC_API_URL: z.string().url(), LUNX_PUBLIC_APP_NAME: z.string().min(1), LUNX_PUBLIC_SENTRY_DSN: z.string().url().optional(), // Feature flags LUNX_PUBLIC_ENABLE_ANALYTICS: z .string() .transform(v => v === 'true') .default('false'), })
Setting environment variables
bash.env
# Browser-safe — exposed to client bundle (LUNX_PUBLIC_ prefix required) LUNX_PUBLIC_API_URL=https://api.example.com LUNX_PUBLIC_APP_NAME=My Lunx App LUNX_PUBLIC_ENABLE_ANALYTICS=true # Server-only — never bundled (no prefix) DATABASE_URL=postgres://localhost:5432/mydb STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxx JWT_SECRET=my-super-secret-jwt-key
bash.env.local
# Local overrides (not committed to git) LUNX_PUBLIC_API_URL=http://localhost:8080 LUNX_PUBLIC_ENABLE_ANALYTICS=false
Accessing env vars in your app
typescriptsrc/config.ts
// Fully typed — TypeScript knows the exact shape from your schema const config = { apiUrl: import.meta.env.LUNX_PUBLIC_API_URL, appName: import.meta.env.LUNX_PUBLIC_APP_NAME, analytics: import.meta.env.LUNX_PUBLIC_ENABLE_ANALYTICS === 'true', sentryDsn: import.meta.env.LUNX_PUBLIC_SENTRY_DSN, } as const export default config
Build-time validation errors
bash
lunx build ✗ plugin-env: schema validation failed Missing required variables: LUNX_PUBLIC_API_URL — Expected string URL, received: undefined → Add to .env or .env.production Invalid format: LUNX_PUBLIC_SENTRY_DSN — Expected URL, got: "not-a-url" Build aborted.
Plugin options
| Field | Type | Default | Description |
|---|---|---|---|
| schema | string | — | Path to a Zod schema file. If provided, all env vars are validated at build start. |
| prefix | string | 'LUNX_PUBLIC_' | Custom prefix for browser-safe variables. Change for multi-tenant setups. |
| failOnMissing | boolean | true | Abort the build if any required schema field is missing from the environment. |
| envFiles | string[] | ['.env', '.env.local', '.env.[mode]'] | Ordered list of .env files to load. Later files override earlier ones. |
Never access server variables in browser code
Accessing
import.meta.env.DATABASE_URL or any non-prefixed variable in browser code will throw a compile-time error with plugin-env installed. This is intentional — it prevents accidental secret exposure.