Skip to content

Environments

Production Beta
Branch main beta
Web tcgkl.com beta.tcgkl.com
API api.tcgkl.com api-staging.tcgkl.com
Docs docs.tcgkl.com
R2 bucket tcgkl tcgkl-beta
Env file .env .env.local / .env.beta

.env.example is the source of truth for the full list. What follows is only the parts that cause incidents.

  • DATABASE_URL — the pooled Neon endpoint (-pooler), with sslmode=require&channel_binding=require. postgres.js runs prepare: false because of PgBouncer.
  • DATABASE_URL_DIRECT — the non-pooler endpoint, used for migrations only. The migrate script refuses to run against a -pooler host.

ECONNREFUSED or CONNECT_TIMEOUT locally is nearly always one of those two being wrong, or a dev server that needs a restart.

  • BETTER_AUTH_TRUSTED_ORIGINS is comma-separated. A domain missing from it cannot sign in.
  • CLOUDFLARE_R2_PUBLIC_URL has no trailing slash.
  • API_INTERNAL_URL set → the web app proxies /api/trpc, /api/auth, webhooks, cron and uploads to apps/api. Unset → the local thin routes serve. That switch is the rollback path.
  • REDIS_URL exists on the API only. Every web-side Redis consumer needs a null or database fallback.
  • APP_VARIANTproduction makes the OTP 666666. Production always sends a real one.

Which database is this script about to write to?

Section titled “Which database is this script about to write to?”

Scripts run by a bare bun run load .env.local, which points at beta. For production, pin the env file and read the host the script prints:

Terminal window
bunx env-cmd -f .env -- bun run apps/web/scripts/<script>.ts