Complete configuration inventory, ownership, defaults, secrets, and deployment requirements.
Environment Variables
This is the canonical configuration catalog. Each deployable owns a safe local template and runtime validator so applications and services remain independently deployable.
Configuration Model
| Kind | Rule |
|---|---|
| public browser value | may enter client bundles; must never contain a secret |
| server value or secret | available only to server or Worker code |
| Cloudflare binding | configured by Wrangler and passed on the request/runtime env |
| deployment adapter | consumed by the hosting platform rather than application code |
Next.js applications use @t3-oss/env-nextjs, and Bun services use
@t3-oss/env-core. Cloudflare bindings are request-scoped; do not copy them
into process.env.
Workspace Index
| Workspace | Local template | Validation source | Deployment source |
|---|---|---|---|
| Web | apps/web/.env.example | apps/web/src/config/*.env.config.ts | app hosting environment |
| Docs | apps/docs/.env.example | apps/docs/src/config/public.env.config.ts | app hosting environment |
| People | apps/people/.env.example | apps/people/src/config/public.env.config.ts | app hosting environment |
| Projects | apps/projects/.env.example | apps/projects/src/config/public.env.config.ts | app hosting environment |
| Portal | apps/portal/.env.example | apps/portal/src/config/*.env.config.ts | app hosting environment |
| API | services/api/.dev.vars.example | services/api/src/types/env.ts and runtime modules | Wrangler config, bindings, and secrets |
| GitHub App | services/github-app/.env.example | services/github-app/src/config/runtime.config.ts | Wrangler config and secrets |
| Mailer | services/mailer/.env.example | services/mailer/src/config/env.ts | service hosting environment |
Audited Configuration Matrix
Each row records the supported name, exposure kind, source, runtime status,
and owner. runtime means application or adapter code reads the value;
binding means Cloudflare injects and consumes the resource; and
deployment-only means the hosting adapter owns it. No listed value is known
to be unused.
Docs
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
NEXT_PUBLIC_DOCS_SITE_URL | browser | template | runtime | canonical URL and generated routes |
Web
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
NEXT_PUBLIC_SITE_URL | browser | template | runtime | canonical URL and metadata |
NEXT_PUBLIC_PEOPLE_SITE_URL | browser | template | runtime | People app destinations |
NEXT_PUBLIC_PROJECTS_SITE_URL | browser | template | runtime | Projects app destinations |
NEXT_PUBLIC_ELEARNING_SITE_URL | browser | template | runtime | e-learning destinations |
BASE_DOMAIN | server | template | runtime | application domain construction |
MOODLE_URL | server | template | runtime | Moodle redirect fallback |
WORKER_URL | server | template | runtime | proxy Worker requests |
CF_SECRET | secret | template | runtime | proxy Worker authentication |
People
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
NEXT_PUBLIC_SITE_URL | browser | template | runtime | canonical URL and metadata |
NEXT_PUBLIC_PEOPLE_DATA_BASE_URL | browser | template | runtime | people records |
NEXT_PUBLIC_PROJECTS_DATA_BASE_URL | browser | template | runtime | related project records |
NEXT_PUBLIC_PROJECTS_SITE_URL | browser | template | runtime | Projects app destinations |
Projects
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
NEXT_PUBLIC_SITE_URL | browser | template | runtime | canonical URL and metadata |
NEXT_PUBLIC_PROJECTS_DATA_BASE_URL | browser | template | runtime | project records |
NEXT_PUBLIC_PEOPLE_SITE_URL | browser | template | runtime | People app destinations |
NEXT_PUBLIC_DEPARTMENT_SITE_URL | browser | template | runtime | department course indexes |
Portal
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
NEXT_PUBLIC_SITE_URL | browser | template | runtime | canonical URL and metadata |
NEXT_PUBLIC_BASE_API_URL | browser | template | runtime | browser API client |
NEXT_PUBLIC_PEOPLE_DATA_BASE_URL | browser | template | runtime | public profile data |
NEXT_PUBLIC_VERIFICATION_CODE_MAX_LENGTH | browser | template | runtime | verification input constraints |
NEXT_PUBLIC_API_CLIENT_ID | browser | template | runtime | API client identification |
COOKIE_DOMAIN | server | template | runtime | authentication cookie scope |
API Worker
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
BETTER_AUTH_SECRET | secret | template | runtime | Better Auth signing |
BETTER_AUTH_URL | server | wrangler | runtime | Better Auth base URL |
GOOGLE_CLIENT_ID | server | wrangler | runtime | Google OAuth |
GOOGLE_CLIENT_SECRET | secret | template | runtime | Google OAuth |
GITHUB_CLIENT_ID | server | wrangler | runtime | GitHub OAuth |
GITHUB_CLIENT_SECRET | secret | template | runtime | GitHub OAuth |
MAILER_API_URL | server | wrangler | runtime | Mailer service endpoint |
MAILER_API_KEY | secret | template | runtime | Mailer service authentication |
GITHUB_APP_API_URL | server | wrangler | runtime | GitHub App HTTP fallback |
GITHUB_APP_INTERNAL_SECRET | secret | template | runtime | GitHub App HTTP authentication |
DATA_PUBLIC_BASE_URL | server | wrangler | runtime | public data URL construction |
AUTH_DB | binding | wrangler | binding | D1 auth and settings store |
GITHUB_APP | binding | wrangler | binding | private GitHub App service transport |
GitHub App
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
GITHUB_APP_ID | server | template | runtime | GitHub App authentication |
GITHUB_PRIVATE_KEY | secret | template | runtime | GitHub App authentication |
GITHUB_INSTALLATION_ID | server | template | runtime | installation selection |
GITHUB_OWNER | server | template | runtime | repository owner |
GITHUB_PEOPLE_DATA_REPOSITORY | server | template | runtime | people data repository |
GITHUB_PROJECTS_DATA_REPOSITORY | server | template | runtime | projects data repository |
X_INTERNAL_SECRET | secret | template | runtime | internal request authentication |
PORT | adapter | template | runtime | local Bun listener |
OPERATION_STATE | binding | wrangler | binding | durable operation state |
MUTATION_COORDINATOR | binding | wrangler | binding | per-resource mutation serialization |
OPERATION_QUEUE | binding | wrangler | binding | durable operation dispatch |
Mailer
| Name | Kind | Supply | Status | Purpose |
|---|---|---|---|---|
MAILER_API_KEY | secret | template | runtime | bearer authentication |
SMTP_HOST | server | template | runtime | SMTP connection |
SMTP_SECURE | server | template | runtime | SMTP transport and port selection |
SMTP_USER | secret | template | runtime | SMTP authentication |
SMTP_PASS | secret | template | runtime | SMTP authentication |
SMTP_FROM | server | template | runtime | sender address |
PORT | adapter | template | runtime | Bun listener |
VERCEL_EXPERIMENTAL_BACKENDS | adapter | provider | deployment-only | Vercel backend routing during deploy |
Local Setup
Copy only the templates needed for the workspaces you will run. Next.js apps
use .env.local; Wrangler uses .dev.vars; Bun services use .env.
Copy-Item apps/web/.env.example apps/web/.env.local
Copy-Item apps/docs/.env.example apps/docs/.env.local
Copy-Item apps/people/.env.example apps/people/.env.local
Copy-Item apps/projects/.env.example apps/projects/.env.local
Copy-Item apps/portal/.env.example apps/portal/.env.local
Copy-Item services/api/.dev.vars.example services/api/.dev.vars
Copy-Item services/github-app/.env.example services/github-app/.env
Copy-Item services/mailer/.env.example services/mailer/.envThese destinations are ignored. Never reuse production secrets locally or commit populated files. Empty strings are treated as missing by typed config. Defaults and safe local examples live in the validator and template; avoid duplicating them in another guide.
The Portal and API origins must agree with Better Auth trusted origins, CORS, passkey relying-party settings, and cookie-domain behavior. The API and GitHub App internal secrets must also match.
Production Configuration
Non-secret API and GitHub App values, resource bindings, and required secret
names are declared in their wrangler.jsonc files. Store values in the
provider, never in Wrangler configuration:
Set-Location services/api
bunx wrangler secret put BETTER_AUTH_SECRET
bunx wrangler secret put GOOGLE_CLIENT_SECRET
bunx wrangler secret put GITHUB_CLIENT_SECRET
bunx wrangler secret put MAILER_API_KEY
bunx wrangler secret put GITHUB_APP_INTERNAL_SECRET
Set-Location ../github-app
bunx wrangler secret put GITHUB_PRIVATE_KEY
bunx wrangler secret put X_INTERNAL_SECRETAUTH_DB and GITHUB_APP belong to the API Worker. OPERATION_STATE,
MUTATION_COORDINATOR, and OPERATION_QUEUE belong to the GitHub App Worker.
Durable Object state is independent of API D1 migrations.
The GitHub private key may contain escaped newlines but must never be stored as
a tracked PEM file. The Mailer refuses to start without MAILER_API_KEY; verify
its SMTP sender and delivery in a non-production mailbox. Vercel owns
VERCEL_EXPERIMENTAL_BACKENDS; application code does not read it.
Adding or Changing Configuration
Update all affected layers in one change:
- typed schema or Worker environment type;
- runtime config module;
- safe example file;
- Wrangler or hosting configuration for non-secret values;
- deployment secret store for secrets;
- repository environment-policy tests;
- this catalog and Operations when deployment changes;
- focused config tests, typecheck, and build.
Never print a secret to prove it exists. Validate presence, length, or a provider response without echoing the value.