Environment variables

You need: a scaffolded project.

The line

Secrets is where a value goes when it must not be a var, the config directory is where dev copies live, pithy env reports what resolved, and rotating a secret is the maintenance.

A var is a value you would put in a screenshot. A secret is one you would not.

Where
BASE_URL, ENVIRONMENT, PROJECT, WORKERVars, in wrangler.jsonc
A public sitekeyA var — the front end renders with it
An API key, a signing key, an OAuth client secretSecrets

.dev.vars is generated, not authored

It is generated from your machine-local secrets file, which lives at <config>/<project>/secrets.jsonc — outside every checkout, mode 0600.

Nothing to gitignore. Nothing git add -A can reach. Delete the whole clone and the values are still there.

pithy secrets edit      opens it
pithy doctor            tells you the path

Generation is idempotent by content, so a run that changes nothing writes no bytes.

Four vars the kit stamps and reads

VarRead by
PROJECTThe audit recorder
ENVIRONMENTThe audit recorder, and the Turnstile test-key exception
WORKERThe audit recorder — the only thing that tells two Workers’ events apart
BASE_URLWritten by pithy worker sync from your domains block

An emitter cannot set the first three. Origin is a property of the writer, not of the action — and a route that could claim to be another environment would make the column worth nothing precisely when it mattered.

All three are nullable, permanently. A Worker scaffolded before they existed carries none, a CLI action came from no Worker, and no historical row can be back-filled. null means not recorded.

Per-environment values

Every var lives in its environment’s stanza. pithy worker sync writes the ones derived from your config — the route and the BASE_URL a domains block implies — for every environment it declares.

That is the only non-interactive way to get the route written. A domains block added by hand and never synced declares an address nothing serves.

Do not build a URL from a literal

// wrong
const successUrl = "https://acme.com/thanks";

An origin written down is production’s origin written into staging — which lands a staging payer in production on an account that has bought nothing.

Build it from BASE_URL, or from the constant the scaffolded config derives from domains.

Reading a var

c.env.MY_VAR

Validate it if anything depends on its shape. A var is a string somebody typed into a JSON file, and a Worker that assumes otherwise fails at the first request rather than at boot.

What never goes in a var

No secret. No credential. No token.

If it is in wrangler.jsonc it is in your repository, in every clone, in every CI log that echoes a config, and in the deploy output.

And no secret value is ever printed by any pithy command — not by provision, not by rotate, not by doctor. That is a property of the kit worth not undermining with a var.

ESC