Configuration
The three layers
Configuration in the kit flows through three layers, in order:
.envfiles — raw values and secrets for your environment.src/env.ts— a Zod schema that validates those values at boot and exports a typedenvobject. All code reads from@/env, neverprocess.envdirectly.src/config/*.config.ts— typed feature flags that read from@/envand expose intent to the rest of the app.
Business logic imports config, not env: import { authConfig } from "@/config/auth.config". This keeps toggles in one place and fails fast when a
required variable is missing.
Feature flags live in config files
Each domain has a config file where every option carries a one-line comment describing its acceptable values and effect:
| File | Controls |
|---|---|
auth.config.ts | Providers, verification, tenancy model, rate limiting |
plans.config.ts | Billing plans (Stripe IDs, seats, trials) |
credits.config.ts | Credit pack definitions |
payment.config.ts | Payment provider + default currency |
email.config.ts | Email provider and sender identity |
storage.config.ts | S3/R2 provider and bucket |
docs.config.ts | This documentation section |
Features are off until configured
Optional integrations activate only when their credentials are present. For example, a social provider is included only if both its client ID and secret are set:
env.AUTH_GOOGLE_ENABLED && env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET
? { id: "google", clientId: env.GOOGLE_CLIENT_ID, ... }
: null
The same pattern applies to Stripe plans (no price ID → not billed), credit packs (no price ID → not purchasable), and Sentry (no DSN → monitoring off). You can develop the whole app with just a database and an auth secret.
Adding a new setting
To add a new toggle:
- Add the variable to
.env.examplewith a comment and example value. - Add it to the Zod schema in
src/env.ts(there's abool(default)helper for booleans andz.enum([...]).default(...)for choices). - Surface it in the relevant
*.config.tsfile with a one-line comment. - Import the config value where you need it — never read
process.env.
Docs visibility
As an example of a config-driven toggle: set DOCS_VISIBILITY to public or
authenticated to control who can read this section, and DOCS_ENABLED=false
to remove it entirely.