Configuration & Environments
Environment model
APP_ENV is the master switch — production, development, or local. It selects which
domain set and external endpoints a node uses. The API asserts that its APP_DOMAIN belongs
to the allowed set for its APP_ENV at startup (assertFqdnConsistency) and exits on
mismatch, so a development image can never boot against production DNS, and vice-versa.
| Node | Production | Development |
|---|---|---|
| App (ftm-web) | app.illumera.us | devapp.illumera.us |
| API | api.illumera.us | apid.illumera.us |
| Marketing (www) | www.illumera.us | wwwd.illumera.us |
| Docs (this site) | docs.illumera.us | docd.illumera.us |
Email sender addresses are derived from APP_DOMAIN, so a development environment never
sends mail from a production address.
Environment variables
.env.example at deploy time. To change it, edit the source — not this page.The reference below is generated from the repository's .env.example. Each variable is
tagged by when it's needed:
- Runtime — required to run the full application (or the noted feature) in a real environment.
- Test — required only for a specific test suite.
- Optional — has a safe default or enhances functionality.
Core application
| Variable | Required | Example | Description |
|---|---|---|---|
APP_ENV | Optional | development | Application environment: development | staging | production Defaults to "development" when absent. |
NODE_ENV | Optional | development | Node.js environment — always set to "development" for local work. Defaults to "development". |
PORT | Optional | 3001 | Port the API server binds to. Defaults to 3001. |
APP_DOMAIN | Runtime | http://localhost:3001 | Public domain of the deployed app (used for CORS and email links). Required for invite emails and CORS in non-dev environments. |
CORS_ORIGINS | Runtime | http://localhost:5173 | Comma-separated list of allowed CORS origins. Required when frontend and API run on different origins. |
Database
| Variable | Required | Example | Description |
|---|---|---|---|
DATABASE_URL | Test | postgresql://postgres:postgres@localhost:5432/illumera_dev | PostgreSQL connection string. Required only for m4a-schema-foundation.test.ts (DB integration test). All other tests mock the database — this is NOT needed for pnpm test:unit. Required to run the API server. |
Authentication (Clerk)
| Variable | Required | Example | Description |
|---|---|---|---|
CLERK_SECRET_KEY | Runtime | sk_test_REPLACE_ME | Clerk secret key — keep this out of version control. Required — the API server validates all requests using this key. |
CLERK_PUBLISHABLE_KEY | Runtime | pk_test_REPLACE_ME | Clerk publishable key — safe to expose to the browser. Required by the web frontend. |
CLERK_WEBHOOK_SECRET | Runtime | whsec_REPLACE_ME | Clerk webhook signing secret — used to verify incoming webhook payloads. Required if you use Clerk webhooks (user sync, etc.). |
Internal secrets
| Variable | Required | Example | Description |
|---|---|---|---|
INTERNAL_API_SECRET | Runtime | REPLACE_ME_internal_api_secret | Shared secret for internal service-to-service calls (e.g. PDF worker → API). Required when PDF generation is enabled. |
BOOTSTRAP_SECRET | Optional | REPLACE_ME_bootstrap_secret | Bootstrap secret — grants temporary admin access for initial setup. Leave unset in production after initial bootstrap is complete. |
AI integrations
| Variable | Required | Example | Description |
|---|---|---|---|
AI_INTEGRATIONS_ANTHROPIC_BASE_URL | Runtime | https://api.anthropic.com | Base URL for Replit-proxied Anthropic access (used in production on Replit). Required for AI features that use the Replit AI integration proxy. |
ANTHROPIC_API_KEY | Runtime | REPLACE_ME_anthropic_api_key | Direct Anthropic API key — used when not routing through the Replit proxy. Required for AI resume parsing and capability AI features. |
OPENAI_API_KEY | Optional | REPLACE_ME_openai_api_key | OpenAI API key — used for embeddings or any OpenAI-backed features. Leave unset if no OpenAI features are active. |
Email (Resend)
| Variable | Required | Example | Description |
|---|---|---|---|
RESEND_API_KEY | Runtime | re_REPLACE_ME | Resend API key for transactional email. Required for sending invitation, welcome, and notification emails. |
RESEND_WEBHOOK_SECRET | Optional | REPLACE_ME_resend_webhook_secret | Resend webhook signing secret — validates inbound delivery event webhooks. Only needed if you process delivery/bounce webhooks. |
Object storage (S3-compatible)
| Variable | Required | Example | Description |
|---|---|---|---|
S3_BUCKET | Runtime | illumera-dev | S3 bucket name. Required for avatar uploads, resume storage, and report exports. |
S3_REGION | Optional | us-east-1 | AWS/S3 region. |
S3_ENDPOINT | Optional | — | S3-compatible endpoint URL (leave blank to use AWS default). Set this when using a non-AWS provider such as Cloudflare R2 or MinIO. |
S3_PUBLIC_URL | Optional | https://your-bucket.s3.amazonaws.com | Public base URL for serving stored objects. |
ILLUMERA_DOWNLOAD_TOKEN_SECRET | Optional | REPLACE_ME_random_hex_secret | HMAC-SHA256 secret for signing marketing capability-statement download tokens (ALN-MKTG-P3). Generate with: openssl rand -hex 32 |
AWS_ACCESS_KEY_ID | Optional | REPLACE_ME_access_key_id | AWS credentials. |
AWS_SECRET_ACCESS_KEY | Optional | REPLACE_ME_secret_access_key | — |
S3_PRESIGN_EXPIRY | Optional | 3600 | Presigned URL expiry in seconds (default: 3600 = 1 hour). |
S3_FORCE_PATH_STYLE | Optional | false | Set to "true" when using path-style S3 addressing (MinIO, localstack). |
Integration token encryption
| Variable | Required | Example | Description |
|---|---|---|---|
INTEGRATION_ENCRYPTION_KEY | Runtime | REPLACE_ME_integration_encryption_key | Platform-wide encryption key for integration tokens at rest (Align, Fireflies, GitHub, Calendly) and for signing OAuth `state`. 32 random bytes, base64-encoded: openssl rand -base64 32 Required in production once ANY integration is used (the server throws on encrypt/decrypt if unset). Required for pnpm test:align. Do not rotate once real tokens are stored — existing connections become undecryptable. Legacy name ALIGN_ENCRYPTION_KEY is still read as a fallback (ALN-153). |
Align integration
| Variable | Required | Example | Description |
|---|---|---|---|
ALIGN_BASE_URL | Test | https://app.alignsoftware.io | Base URL for the Align API. Required only for pnpm test:align. Defaults to the production Align URL when absent. |
PDF worker
| Variable | Required | Example | Description |
|---|---|---|---|
PDF_WORKER_URL | Runtime | http://localhost:3002 | URL of the PDF generation microservice. Required for report PDF export. |
PDF_WORKER_SECRET | Runtime | REPLACE_ME_pdf_worker_secret | Shared secret between the API server and the PDF worker. Required for report PDF export. |
Logging
| Variable | Required | Example | Description |
|---|---|---|---|
LOG_LEVEL | Optional | info | Pino log level: trace | debug | info | warn | error | fatal Defaults to "info". |
Never commit real values. INTEGRATION_ENCRYPTION_KEY in particular must not be rotated once
real integration tokens are stored, or existing connections become undecryptable.