A site
| Variable | Purpose |
|---|---|
STAGE_DB_URL | Database URL. SUPABASE_URL is accepted as a legacy alias |
STAGE_PUBLIC_KEY | The public database key, safe to ship. SUPABASE_ANON_KEY is the legacy alias |
ORG_ID | This site’s org |
SITE_URL | Canonical domain |
API_URL | The shared API base, no trailing slash |
ISR_BYPASS_TOKEN, REVALIDATE_SECRET | On-demand refresh mode only |
ADMIN_LOGO_URL, ADMIN_BRAND_NAME, ADMIN_LOGO_FONT, ADMIN_FONT_STYLESHEET_URL | Optional sign-in branding |
A site never holds a service-role key, a signing key, a storage credential, or a social token. If a value would let a leaked site env write across orgs, it belongs in the API.
The shared API
Names only. Values live in the secrets system and are never in a repository.| Group | Variables |
|---|---|
| Database | SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY |
| Media | R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET, CDN_HOST, MUX_TOKEN_ID, MUX_TOKEN_SECRET |
| AI generation | GEMINI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY (optional; the feature returns 503 unset) |
| Tracking | IP_KEY_SECRET, IP_SALT. There is no rotation procedure for IP_KEY_SECRET: rows store one key derived from it and raw addresses are never kept, so changing it splits every returning visitor’s history in two |
| Forms and mail | FORM_TOKEN_SECRET, RESEND_API_KEY |
| Access | ACCESS_KEY_PRIVATE_JWK |
| Campaigns | SOCIAL_TOKEN_SECRET, X_CLIENT_ID, X_CLIENT_SECRET, IG_APP_ID, IG_APP_SECRET, LI_CLIENT_ID, LI_CLIENT_SECRET, SOCIAL_PUBLIC_BASE, CRON_SECRET |
| Requests | LINEAR_CLIENT_ID, LINEAR_CLIENT_SECRET, LINEAR_TEAM_ID |
| Publishing | VERCEL_TOKEN |
SHORT_LINK_BASE overrides the link base for local testing through a tunnel. Local only, never in production.