lunx.docs
DocsPluginsplugin-env

@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-env
typescriptlunx.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

FieldTypeDefaultDescription
schemastringPath to a Zod schema file. If provided, all env vars are validated at build start.
prefixstring'LUNX_PUBLIC_'Custom prefix for browser-safe variables. Change for multi-tenant setups.
failOnMissingbooleantrueAbort the build if any required schema field is missing from the environment.
envFilesstring[]['.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.