env-configuration
GitHub规范应用环境变量配置,强制使用LAT_前缀,维护.env.example及文档、Helm Chart同步,并通过parseEnv库安全解析配置。
Trigger Scenarios
Install
npx skills add latitude-dev/latitude-llm --skill env-configuration -g -y
SKILL.md
Frontmatter
{
"name": "env-configuration",
"description": "Adding or reading env vars, updating .env.example, or validating config at startup with parseEnv \/ parseEnvOptional."
}
Environment configuration
When to use: Adding or reading env vars, updating .env.example, or validating config at startup with parseEnv / parseEnvOptional.
LAT_ prefix convention
All application environment variables must be prefixed with LAT_ so they do not collide with third-party services, Docker, or common names.
Use LAT_ for:
- Database URLs and pool settings (
LAT_DATABASE_URL,LAT_PG_POOL_MAX, …) - Service endpoints the app reads (
LAT_CLICKHOUSE_URL,LAT_REDIS_HOST, …) - App ports (
LAT_API_PORT,LAT_WEB_PORT,LAT_INGEST_PORT) - Auth, email, OAuth, billing, CORS (
LAT_BETTER_AUTH_SECRET,LAT_MAILPIT_HOST, …) - Any new variable consumed by Latitude application code
Do not use LAT_ for:
NODE_ENV- Docker-only init variables (
POSTGRES_USER,CLICKHOUSE_USER, …) - Config read only by container images (Weaviate, Redis in compose, etc.)
- Browser-exposed Vite vars: use
VITE_LAT_*(Vite requires theVITE_prefix)
Reference: .env.example lists Docker “Services” vs “Latitude Application” (LAT_*) variables.
.env.example maintenance
Every new variable must appear in .env.example:
- Required: uncommented with a sensible local default (e.g.
LAT_API_PORT=3001) - Optional: commented with a placeholder (e.g.
# LAT_STRIPE_SECRET_KEY=sk_test_xxx)
Keep the self-host surfaces in sync
Self-hosters configure Latitude through these env vars, so adding, renaming, or removing one means updating more than .env.example. Whenever you touch a LAT_* var, also reflect it in:
- The configuration reference
docs/deployment/configuration.mdx— so operators know what the var does — unless it is specific to Latitude's own cloud deployment, which stays out of the self-host docs: payments/Stripe, marketing/lifecycle email (Loops), support chat (Intercom), and internal analytics/observability vendors (PostHog, Datadog/OTEL export, GTM, Framer, ipinfo). General app/infra/auth/AI/email-transport vars all belong in the reference. - The Helm chart
charts/latitude/— decide where the var belongs:- non-secret →
templates/configmap.yaml(and avalues.yamlknob if it's a first-class setting); - secret →
templates/secret.yamland the chart README'sexistingSecretkey list; - optional/rare → no template change needed; the documented
config.extraEnv/secrets.extrapass-through already covers it.
- non-secret →
docker-stack.yml needs no per-var change (it consumes the whole .env.production), but a new required var must land in .env.example's production guidance. The Railway template is dashboard-authored — no repo change. See dev-docs/self-hosting.md for the tier/contract overview.
Parsing in code
Always use parseEnv or parseEnvOptional from @platform/env — never process.env.FOO ad hoc or unprefixed names for app config.
// ❌ Bad - unprefixed or direct access
const port = Number(process.env.PORT)
// ✅ Good - pass the variable name string (parseEnv reads process.env internally)
import { parseEnv, parseEnvOptional } from "@platform/env"
import { Effect } from "effect"
const port = Effect.runSync(parseEnv("LAT_API_PORT", "number", 3001))
const dbUrl = Effect.runSync(parseEnv("LAT_DATABASE_URL", "string"))
For where configuration is wired in apps (clients, routes), see architecture-boundaries.
Version History
- 2479822 Current 2026-08-20 10:36


