All environment variables for both backend and frontend services.
Variable
Required
Default
Description
PORT
No
3000
HTTP server port. Railway sets this automatically.
NODE_ENV
No
—
production or development. Affects logging and error detail.
Variable
Required
Description
SUPABASE_URL
Yes
Project URL from Supabase → Settings → API. e.g. https://abc123.supabase.co
SUPABASE_PUBLISHABLE_KEY
Preferred
Publishable key used for RLS-enforced client operations.
SUPABASE_ANON_KEY
Fallback
Legacy public anon key, used when no publishable key is configured.
SUPABASE_SERVICE_ROLE_KEY
Yes
Service role key (bypasses RLS). Never expose to frontend.
SUPABASE_DB_URL
Yes
PostgreSQL connection string for direct DB access / migrations. URL-encode password special characters, e.g. # as %23.
Variable
Required
Description
REDIS_URL
Yes
Redis connection string. Provided by Railway Redis plugin or local instance. Format: rediss://default:[pw]@[host]:[port]
Variable
Required
Default
Description
JWT_PRIVATE_KEY
Yes
—
Private P-256 signing key as one-line JWK JSON. Backend secret only.
JWT_PUBLIC_KEY
Yes
—
Matching public P-256 verification key as one-line JWK JSON.
JWT_KEY_ID
Yes
—
Supabase signing-key kid; must match both JWKs.
JWT_ISSUER
Yes
—
Token issuer, normally https://<project-ref>.supabase.co/auth/v1.
JWT_AUDIENCE
Yes
authenticated
Must be exactly authenticated.
JWT_SECRET
Yes
—
Symmetric secret used only for QR check-in tokens. Minimum 32 characters.
Variable
Required
Description
WHATSAPP_APP_SECRET
Yes
Meta App secret. Used to verify HMAC-SHA256 webhook signatures. Found in Meta App → App Settings → Basic → App Secret.
WHATSAPP_WEBHOOK_VERIFY_TOKEN
Yes
A random string you create. Must match the “Verify token” field in Meta App → WhatsApp → Configuration → Webhook.
META_GRAPH_API_VERSION
No
Meta Graph API version. e.g. v22.0
Variable
Required
Description
ENCRYPTION_KEY
Yes
AES-256 key. Must be exactly 32 characters . Used to encrypt WhatsApp tokens and patient DUI numbers. Generate with openssl rand -hex 16 (gives 32 hex chars).
Variable
Required
Description
FRONTEND_URL
Yes
Frontend origin for CORS. e.g. https://app.clinicflow.lat. No trailing slash.
BACKEND_URL
No
Backend URL used in internal references.
BACKEND_PUBLIC_URL
Yes
Public backend URL used in ICS calendar feed URLs. e.g. https://api.clinicflow.lat
Variable
Required
Default
Description
QUEUES_ADMIN_USER
No
admin
Username for Bull Board dashboard at /admin/queues
QUEUES_ADMIN_PASS
Yes
—
Password for Bull Board. Use a strong random string.
Variable
Required
Description
LEMONSQUEEZY_SIGNING_SECRET
Yes
Webhook signing secret from LemonSqueezy → Store → Webhooks. Used to verify order_created events.
LS_VARIANT_BASIC
Yes
LemonSqueezy variant ID for the Basic plan. Found in the product variant settings.
LS_VARIANT_PRO
Yes
LemonSqueezy variant ID for the Pro plan.
LS_VARIANT_CLINICA
Yes
LemonSqueezy variant ID for the Clínica plan.
Variable
Required
Description
SENTRY_DSN
No
Sentry DSN for error tracking. Leave blank to disable.
Variable
Required
Description
SUPER_ADMIN_KEY
Yes
Secret key for the superadmin API. Sent as X-Admin-Key header. Minimum 16 characters. Generate with openssl rand -hex 24
OWNER_WHATSAPP_NUMBER
No
Owner’s WhatsApp number in E.164 format. Used for demo system notifications.
Variable
Required
Description
ANTHROPIC_API_KEY
Yes
Anthropic API key for Claude Haiku chatbot. Get from console.anthropic.com
GROQ_API_KEY
No
Groq key for Whisper (whisper-large-v3-turbo) transcription of WhatsApp voice notes — preferred provider (cheaper + newer). If unset, voice notes degrade gracefully (the bot asks the patient to type). Get from console.groq.com
OPENAI_API_KEY
No
Fallback transcription provider (whisper-1) used only when GROQ_API_KEY is absent. Get from platform.openai.com
TRANSCRIPTION_URL / TRANSCRIPTION_MODEL
No
Override the transcription endpoint/model for any other OpenAI-compatible Whisper host. Defaults to Groq when GROQ_API_KEY is set.
All Vite env vars must be prefixed with VITE_. They are embedded in the build at compile time — do not put secrets here.
Variable
Required
Description
VITE_API_URL
Yes
Backend API base URL. e.g. https://api.clinicflow.lat/api for production, http://localhost:3001/api for local dev.
VITE_LS_URL_BASIC
No
LemonSqueezy checkout URL for the Basic plan.
VITE_LS_URL_PRO
No
LemonSqueezy checkout URL for the Pro plan.
VITE_LS_URL_CLINICA
No
LemonSqueezy checkout URL for the Clínica plan.
VITE_SENTRY_DSN
No
Sentry DSN for frontend error tracking. Leave blank to disable.
VITE_ANALYTICS_ID
No
Analytics tracking ID. Leave blank to disable.
Used when running npm test. Separate from .env so tests never touch the production database.
Required keys: Same as .env but pointing to a test Supabase project (or the same project with test data).
The test runner loads this file automatically:
node --env-file=.env.test ./node_modules/.bin/vitest run
# JWT_SECRET (64 hex chars)
# ENCRYPTION_KEY (exactly 32 chars)