Environment Variables
This page is the source of truth for environment variables used by the Coaching App.
Scope
backend/.env controls the Hono API, storage, mail, auth, and security behavior.
frontend/.env controls Expo build-time and runtime flags.
- Environment-specific frontend files are supported for OTA/EAS workflows:
frontend/.env.staging
frontend/.env.production
Backend Variables
Required in all environments
| Variable |
Required |
Default |
Description |
DATABASE_URL |
Yes |
None |
PostgreSQL connection string used by Drizzle. |
REDIS_URL |
Yes |
None |
Redis connection URL for cache/queues/events. |
BETTER_AUTH_SECRET |
Yes |
None |
Better Auth signing secret. |
CLIENT_API_KEY |
Yes, unless DISABLE_CLIENT_AUTH=true |
None |
Shared client key expected in X-Client-Key. |
Required in deployed environments (NODE_ENV=production or APP_ENV=staging)
| Variable |
Required |
Default |
Description |
FRONTEND_URL |
Yes |
None |
Public frontend base URL used for redirects and callback URLs. |
BETTER_AUTH_URL |
Yes |
None |
Public backend base URL for Better Auth route generation. |
CORS_ORIGIN |
Yes |
None |
Comma-separated allowlist of web origins. |
SMTP_HOST |
Yes |
None |
SMTP server hostname. |
SMTP_USER |
Yes |
None |
SMTP username. |
SMTP_PASS |
Yes |
None |
SMTP password (note: SMTP_PASS, not SMTP_PASSWORD). |
EMAIL_FROM |
Yes |
None |
Sender identity, for example Coaching App <noreply@domain.com>. |
AGORA_APP_ID |
Yes |
None |
Agora App ID for video/chat token minting. |
AGORA_APP_CERTIFICATE |
Yes |
None |
Agora App Certificate used to sign tokens. |
Storage configuration (required in deployed environments)
You must configure one complete storage mode.
Option A: S3-compatible endpoint
| Variable |
STORAGE_ENDPOINT |
STORAGE_ACCESS_KEY_ID |
STORAGE_SECRET_ACCESS_KEY |
Option B: Cloudflare R2
| Variable |
R2_ACCOUNT_ID |
R2_ACCESS_KEY_ID |
R2_SECRET_ACCESS_KEY |
If neither option is complete, health reports missing required storage configuration.
Optional backend variables
| Variable |
Default |
Description |
PORT |
3001 |
Backend server port. |
NODE_ENV |
development |
Runtime mode. |
APP_ENV |
unset |
Additional environment selector (for example staging). |
DISABLE_CLIENT_AUTH |
false |
Set true only for local development. |
RESEND_ACTIVATION_COOLDOWN_SECONDS |
60 |
Per-email cooldown for activation resend endpoint. |
SMTP_PORT |
587 |
SMTP port. |
SMTP_SECURE |
false |
Set true for implicit TLS SMTP. |
STORAGE_BUCKET_NAME |
coaching-app-files |
Bucket name for S3-compatible storage. |
STORAGE_REGION |
us-east-1 |
Region for S3-compatible endpoint mode. |
STORAGE_PUBLIC_URL |
unset |
Public URL rewrite for storage access (dev or CDN cases). |
R2_BUCKET_NAME |
coaching-app-files |
Bucket name for R2 mode. |
R2_PUBLIC_URL |
unset |
Public R2 CDN/custom-domain URL. |
TRUSTED_ORIGINS |
unset |
Additional Better Auth trusted origins (comma-separated). |
EMAIL_VERIFICATION_EXPIRES_HOURS |
24 |
Better Auth verification token expiry (hours). |
TURNSTILE_SECRET_KEY |
unset |
Enables Turnstile verification when set. |
Frontend Variables
Required
| Variable |
Required |
Default |
Description |
EXPO_PUBLIC_API_URL |
Yes |
None |
Backend base URL used by the app client. |
EXPO_PUBLIC_CLIENT_KEY |
Yes |
None |
Must match backend CLIENT_API_KEY. |
Optional
| Variable |
Default |
Description |
EXPO_PUBLIC_API_TIMEOUT |
30000 |
API timeout in milliseconds. |
EXPO_PUBLIC_ENV |
development |
Frontend runtime environment label. |
EXPO_PUBLIC_APP_ENV |
development |
Additional environment label for app logic. |
EXPO_PUBLIC_ENABLE_ANALYTICS |
false |
Enables analytics features. |
EXPO_PUBLIC_ENABLE_ERROR_REPORTING |
false |
Enables error reporting integration. |
EXPO_PUBLIC_SENTRY_DSN |
unset |
Sentry DSN when error reporting is enabled. |
SENTRY_ORG |
unset |
Sentry org used by build/upload scripts. |
SENTRY_PROJECT |
unset |
Sentry project used by build/upload scripts. |
SENTRY_AUTH_TOKEN |
unset |
Sentry auth token for source map upload. |
EXPO_PUBLIC_TURNSTILE_SITE_KEY |
unset |
Web CAPTCHA site key. |
EXPO_PUBLIC_APPLE_AUTH_ENABLED |
false |
Shows Apple login button on welcome screen. |
EXPO_PUBLIC_APPLE_CLIENT_ID |
unset |
Apple auth client identifier. |
EXPO_PUBLIC_GOOGLE_AUTH_ENABLED |
false |
Shows Google login button on welcome screen. |
EXPO_PUBLIC_GOOGLE_CLIENT_ID |
unset |
Google auth client identifier. |
EXPO_DEVTOOLS_LISTEN_ADDRESS |
0.0.0.0 |
Expo dev tools host binding. |
REACT_NATIVE_PACKAGER_HOSTNAME |
localhost |
Metro hostname used in local workflows. |
Health Endpoint and Missing Required Env Variables
GET /api/health now includes explicit environment validation details.
Response fields:
checks.env: ok or error
env.environment: development or deployed
env.missingRequired: list of missing required variable names
env.missingGroups: list of failing requirement groups (for example mail, storage)
Example degraded response:
{
"status": "degraded",
"checks": {
"postgres": "ok",
"redis": "ok",
"s3": "error",
"mail": "error",
"agora": "error",
"env": "error"
},
"env": {
"environment": "deployed",
"missingRequired": ["SMTP_HOST", "SMTP_USER", "SMTP_PASS", "EMAIL_FROM"],
"missingGroups": ["mail"]
}
}
Recommendations
- Keep
backend/.env.example and frontend/.env.example in sync with this page.
- In staging and production, set variables through platform config (
dokku config:set ...) instead of files.
- Treat missing variables reported by
/api/health as deployment blockers.