Environment and bindings
Cloudflare runtime configuration for the Clay backend lives inapps/backend/wrangler.toml. This page is the canonical reference for what is currently declared, the rules for adding new variables or bindings, and the secret-handling guardrails that apply to all Cloudflare surfaces.
The backend has not yet adopted a typed environment module such as
src/env.ts. When one is
added, it should be described here and referenced from the Worker entry point. The wrangler
TypeScript types can be regenerated with pnpm --filter @clay/backend types:wrangler, which
writes worker-configuration.d.ts for editor IntelliSense.Current state
apps/backend/wrangler.toml declares the Worker identity, the entry point, the compatibility date, and a single variable. No Hyperdrive, KV, R2, AI, D1, Durable Object, or Queues bindings are configured today.
Variables
Variables declared under[vars] are read from env inside the Worker and are committed to source control. They are the right place for non-sensitive configuration that needs to be consistent across local development, preview, and production.
| Name | Type | Default | Purpose |
|---|---|---|---|
APP_ENV | string | "development" | Application environment tag, surfaced through the runtime so handlers can branch on local vs deployed behavior. |
Bindings
The Worker currently declares no bindings. Concretely, none of the following sections appear inapps/backend/wrangler.toml:
[[hyperdrive]]— Hyperdrive (Cloudflare’s database connection pooler for the Worker runtime)[[kv_namespaces]]— Workers KV[[r2_buckets]]— R2 object storage[ai]— Workers AI[[d1_databases]]— D1 (SQLite on the edge)[[durable_objects.bindings]]— Durable Object namespaces[[queues.producers]]/[[queues.consumers]]— Queues producers and consumers[[services]]— service bindings to other Workers[[analytics_engine_datasets]]— Workers Analytics Engine datasets
Adding a binding
Cloudflare runtime config must remain explicit and live in the owning app directory. Backends configure their Workers inapps/backend/wrangler.toml; Pages sites configure themselves in their own wrangler.toml.
Pick the binding kind and binding name
Match the binding kind to the runtime need (Hyperdrive for database access, KV for low-latency
reads, R2 for blob storage, AI for inference). Pick an explicit, multi-word binding name such as
HYPERDRIVE or OPPORTUNITY_CACHE, not DB or CACHE.Declare it in apps/backend/wrangler.toml
Add the binding block under the top-level table. Keep all binding declarations in a single file
rather than scattering them across env-specific overrides unless the override is required.
Consume it from src/index.ts
Read the binding through the typed Cloudflare
env interface. Validate the binding name exists
at module load so a missing binding fails fast on deploy rather than in production traffic.Regenerate the wrangler types
Run
pnpm --filter @clay/backend types:wrangler so worker-configuration.d.ts reflects the new
binding. Without this, downstream consumers see the binding as unknown.Prefer Wrangler’s environment-specific overrides (
[env.staging], [env.production]) only when
the binding’s identifier or region genuinely differs by environment. Avoid them when the binding
name and target are stable across all envs.Secret handling
Secrets belong to Cloudflare’s secret store, never towrangler.toml and never to source control. The backend Worker, the landing Pages project, and the specs Pages project each have their own secret namespace.
Set secrets through Wrangler
Use
wrangler secret put NAME per environment. The secret is encrypted at rest and is not
visible in the dashboard without explicit retrieval.Read them through env
Inside the Worker, access secrets via the typed
env argument. Treat the value as a plain
string and validate it at the boundary with Zod before passing it to a downstream client.Never commit a secret
Do not paste real connection strings, API keys, OAuth client secrets, or webhook signing keys
into files under
apps/, packages/, docs/, or anywhere tracked by Git. Do not rely on
.gitignore alone — assume anything typed into a tracked file will eventually be published.Future bindings
The backend team has identified Hyperdrive, KV, R2, and AI as the binding kinds the platform is likely to need. Treat these as intended only — they become implemented once both thewrangler.toml block and the Worker code exist.
| Binding kind | Intended purpose | Status |
|---|---|---|
| Hyperdrive | The Worker runtime connection boundary for the primary relational database. Replaces raw database URLs at the edge. | Intended. Not declared. Becomes authoritative once [[hyperdrive]] appears in wrangler.toml and a route reads from env.HYPERDRIVE. |
| KV | Low-latency reads for opportunity metadata, personality caches, or rate-limit buckets. | Intended. Not declared. Becomes authoritative once [[kv_namespaces]] appears and a route reads from it. |
| R2 | Object storage for generated 3D assets, large media, and long-lived archives. | Intended. Not declared. Becomes authoritative once [[r2_buckets]] appears and a route reads from it. |
| AI | Workers AI binding for inference-backed features that should not pay the round-trip cost of an external model API. | Intended. Not declared. Becomes authoritative once [ai] appears and a route calls env.AI. |
“Intended” bindings must not be pre-stubbed in the codebase. Adding a placeholder binding without
a consumer produces dead config; adding a consumer without a binding produces runtime failures.
Land the wrangler block and the consumer in the same change.
Related
Backend overview
The Hono + OpenAPI contract that runs on top of these bindings.
Deploy
How
wrangler deploy and the per-surface pnpm cf:deploy scripts publish these bindings.Architecture
The Turborepo surface layout the backend Worker lives inside.
API reference
The implemented HTTP routes and Zod schemas exposed through this Worker.

