Environment setup¶
How the Website resolves configuration across local development, preview, and production. Only variable names are listed here — never commit secret values.
Where configuration comes from¶
The Website reads configuration from three places, depending on whether the code runs at build time or at runtime inside the Worker:
| Source | When | What it provides |
|---|---|---|
wrangler.toml [vars] |
Worker runtime | Per-environment runtime variables and the Service Binding |
vite.config.ts define |
Build time | __*__ global constants baked into the client bundle |
.dev.vars (local only) |
Build time (dev) | Local-only build-time secrets, loaded into process.env |
.env / .env.example exist for local convenience; scripts/build-static.ts
also reads .env when present.
Runtime variables (wrangler.toml)¶
These are available on the Worker env object at runtime and differ per
environment ([vars] = production, [env.preview.vars], [env.dev.vars]).
| Variable | Purpose |
|---|---|
NODE_ENV |
Environment name (production / development) |
BASE_URL |
Canonical origin of the site (used for canonical/redirect logic, sitemap, robots) |
API_URL |
Platform Worker URL — HTTP fallback when the Service Binding is absent |
GTM_ID |
Google Tag Manager container ID |
GTAG_ID |
Google Ads / gtag.js ID |
SUBSCRIPTIONS_API_URL |
App URL (app.swapps.com) for subscription/checkout calls (set in the dev env) |
Note
API_URL is the fallback path. In production and preview the Website
talks to the Platform Worker through the API_WORKER Service Binding
(zero-latency Worker-to-Worker), not over HTTP. See
Service bindings.
Service Binding¶
[[services]]
binding = "API_WORKER"
service = "swapps-worker"
The binding is declared in the default, preview, and dev environments so the
Worker-to-Worker path is exercised in each.
Worker secrets (wrangler secret)¶
These are not in wrangler.toml [vars]; they are set with
wrangler secret put and consumed by src/worker.ts (mainly for the blog
edge-cache purge webhook):
| Secret | Purpose |
|---|---|
CACHE_API_SECRET |
Shared secret authenticating the WordPress blog-cache purge webhook |
CF_ZONE_ID |
swapps.com zone id, target of the global cache purge |
CF_PURGE_TOKEN |
Scoped Cloudflare API token (Zone → Cache Purge) for global eviction |
Build-time constants (vite.config.ts)¶
These are substituted into the bundle at build time via Vite define and read
from process.env (or fall back to a default). They are exposed in code as
global __*__ constants.
| Constant | Sourced from process.env |
|---|---|
__BASE_URL__ |
BASE_URL |
__API_URL__ |
API_URL |
__GTM_ID__ |
GTM_ID |
__GTAG_ID__ |
GTAG_ID |
__NODE_ENV__ |
NODE_ENV |
__SUBSCRIPTIONS_API_URL__ |
SUBSCRIPTIONS_API_URL |
__SUBSCRIPTIONS_API_URL_INTERNAL__ |
SUBSCRIPTIONS_API_URL_INTERNAL (falls back to SUBSCRIPTIONS_API_URL) |
__RECAPTCHA_SITE_KEY__ |
RECAPTCHA_SITE_KEY |
__CHAT_API_KEY__ |
CHAT_API_KEY |
__SENTRY_DSN__ |
SENTRY_DSN |
Warning
Empty strings are treated as "not set" and fall back to the default. This is
why vite.config.ts uses || (not ??) for these defines: an empty
API_URL= in .env must fall through to the default rather than producing a
broken URL.
Local-only build-time secrets (.dev.vars)¶
vite.config.ts loads .dev.vars into process.env only if the file exists,
so values like RECAPTCHA_SITE_KEY get baked into the client bundle during local
builds. In CI/production there is no .dev.vars file, and the build uses the
environment as-is. dotenv does not override already-set variables, so shell/CI
env always wins.
Environments at a glance¶
NODE_ENV |
BASE_URL |
API_URL |
|
|---|---|---|---|
Production ([vars]) |
production |
https://swapps.com |
https://swapps-worker.swapps.workers.dev |
Preview ([env.preview.vars]) |
production |
https://{alias}-swapps-client.swapps.workers.dev |
https://swapps-worker.swapps.workers.dev |
Development ([env.dev.vars]) |
development |
http://localhost:3000 |
http://localhost:8787 |
Local API setup¶
For full local development, run the Platform Worker so API_URL resolves:
cd ../swapps-worker
npm run dev # wrangler dev on port 8787
If the Platform Worker is not running, blog and lead endpoints will fail over the HTTP fallback — expected behavior locally.