Skip to content

Environment Variables

All environment variables across the three projects. Source of truth lives in each project’s .env.example file; this page mirrors them with descriptions.

Backend (projects/backend/.env)

App

VarDefaultDescription
NODE_ENVdevelopmentStandard Node env
PORT3000HTTP listen port
LOG_LEVELinfoReserved for future logger config
TZAsia/BangkokProcess timezone (also used in cron)
APP_BASE_URLhttp://localhost:3000Self URL for callbacks (rarely used)
LIFF_URLhttps://app.tinadiet.comLIFF URL for any deep-link generation (rarely used)

Security (REQUIRED)

VarDescription
SESSION_JWT_SECRETHS256 secret for backend session JWTs. Generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))". Rotating invalidates all sessions.

Database

VarDefaultDescription
DATABASE_URLfile:./data/app.dbSQLite file path. Production: file:/data/app.db (Railway volume)

LINE Messaging API (REQUIRED for bot)

VarDescription
LINE_CHANNEL_IDFrom LINE Developers Console
LINE_CHANNEL_SECRETUsed for webhook signature verification
LINE_CHANNEL_ACCESS_TOKENLong-lived token for Reply / Push API

LINE Login (REQUIRED for LIFF auth)

VarDescription
LINE_LOGIN_CHANNEL_IDLIFF channel’s Login Channel ID, used to validate LIFF access tokens

OpenAI (REQUIRED for AI features)

VarDefaultDescription
OPENAI_API_KEY''API key. Empty → AI features 503. Format sk-proj-...
OPENAI_MODELgpt-4o-miniText model for food parsing, coach, consultation
OPENAI_VISION_MODELgpt-4oVision model for photo food logging
OPENAI_VISION_DETAILautolow / high / autolow for cost
OPENAI_TIMEOUT_MS10000Per-request timeout
PHOTO_DAILY_LIMIT10Per-user daily photo cap (premium feature)
CONSULT_DAILY_LIMIT20Per-user daily consultation questions cap
CONSULT_HISTORY_MINUTES120Multi-turn context window
CONSULT_HISTORY_MAX_MESSAGES10Max messages in LLM prompt

Cron

VarDefaultDescription
CRON_ENABLEDtrueSet false to disable all scheduled jobs
CRON_TZAsia/BangkokTimezone for all cron schedules
DAILY_SUMMARY_CRON0 21 * * *When to fire daily push
WEEKLY_SUMMARY_CRON0 8 * * 1When to fire weekly push (Mon morning)
EXPIRE_PREMIUM_CRON0 2 * * *When to sweep expired premium users
JOBS_TRIGGER_SECRET''Required to call /internal/jobs/* endpoints

Stripe (DORMANT)

VarDefaultDescription
STRIPE_SECRET_KEY''Empty → Stripe endpoints return 503
STRIPE_WEBHOOK_SECRET''Required when STRIPE_SECRET_KEY is set
STRIPE_PRICE_ID''Recurring subscription price ID
BILLING_SUCCESS_URLhttps://app.tinadiet.com/?upgraded=1Redirect after Stripe checkout success
BILLING_CANCEL_URLhttps://app.tinadiet.com/?upgrade_canceled=1Redirect after cancellation

Omise (PRIMARY payment provider)

VarDefaultDescription
OMISE_PUBLIC_KEY''TEST: pkey_test_*, LIVE: pkey_*
OMISE_SECRET_KEY''Empty → Omise endpoints 503. TEST: skey_test_*
OMISE_API_BASE_URLhttps://api.omise.coAPI base — change only if Omise mirrors
OMISE_API_VERSION2019-05-29API version header sent on every request
OMISE_WEBHOOK_SECRET''Base64-encoded HMAC secret. Empty → webhook accept-all (DEV ONLY)
PAYMENT_AMOUNT_THB150Price per grant period
PAYMENT_GRANT_DAYS30Days of premium per successful payment
PAYMENT_RETURN_URLhttps://app.tinadiet.com/premium?omise_return=1TrueMoney redirect-back URL

LIFF (projects/liff/.env)

LIFF reads only VITE_* prefixed vars at BUILD time. Vite embeds them directly in the bundle.

VarDescription
VITE_API_BASE_URLBackend URL — https://api.tinadiet.com in prod, http://localhost:3000 in dev
VITE_LIFF_IDLIFF channel ID from LINE Developers Console

In Cloudflare Workers Builds (production builds), also set:

  • NODE_VERSION=22 — required since wrangler 4

Docs (projects/docs/)

This documentation site has no env vars currently. Astro config is static. If we later need preview-vs-prod branching, add ASTRO_* vars.

In Cloudflare Pages dashboard:

  • NODE_VERSION=22 — for Astro 5 build

Secrets file (outside repo)

The maintainer keeps an outside-repo file with all current production secrets:

c:\Users\carvi\AIchatbot\SECRETS_TINADIET_LOCAL.md

This file is NOT in any git repo by design. It includes LINE keys, OpenAI key, Omise keys, Stripe (when active), JWT secret, Cloudflare 2FA recovery codes, etc.

For collaborators, the project owner provisions a similar file with the appropriate subset of credentials.

Adding a new env var

  1. Decide which project owns it (backend / liff / docs)
  2. Add to that project’s .env.example with comment + sensible default
  3. If backend: add to config/env.ts with type + default
  4. Document on this page under the appropriate section
  5. Set the actual value in production (Railway for backend, Cloudflare build settings for liff/docs)

Don’t add env vars to multiple projects unless the value is genuinely shared (e.g. a feature flag affecting both backend and LIFF logic — even then, separate names).