Environment variables
This page covers build-time environment variables: adding them, when they apply, and — most importantly — why you must not put secrets in them.
Prerequisite: a project.
Prompt for your agent
Copy this into Claude Code, Cursor or any agent that can run shell commands. The variables are encrypted to your keys, so the agent cannot read or set them; it tells you what to enter, then checks the redeployed site.
Read https://docs.stasho.xyz/guides/environment-variables.md. I need these build-time
variables on my Stasho project <project>: <NAME=value, ...>. Check each name against the
page's rules first, then tell me exactly what to enter in the Environment tab and when to
redeploy. Never ask me to paste a secret into chat; if a value is a secret, say the page's
reason it does not belong here. After I say the redeploy is live, fetch <site url> and
confirm the public value shows up.Not for secrets
Environment variables are baked into your build and may appear in your published site. Anyone who views your site's source can potentially read them. Don't put API keys, tokens, or anything sensitive here. Stasho has no secret store yet — if your build genuinely needs a secret, keep it in your repo's GitHub Actions secrets and reference it from the workflow file yourself.
What they're for
Build-time configuration that your framework reads during build — public API endpoints, feature flags, analytics IDs, NEXT_PUBLIC_* / VITE_* style values. Exactly the class of variable that ends up in your shipped JavaScript anyway.
Add, edit, remove
Open your project's Environment tab (/projects/<id>/environment):
- Click Add variable
- Fill in Name and Value — names are validated as you type
- Remove a row with the trash icon
- Click Save
Changes apply on the next deploy — push a commit or hit Redeploy to pick them up. Saving here never touches your repo (no PR, unlike build settings).
How they reach your build
Your deploy workflow has a Fetch build env step (included automatically — you don't add it). At build time it fetches your variables from the backend over the same authenticated channel the deploy itself uses, and exposes them to the build step as ordinary process.env.* values.
If that fetch fails, the deploy fails loudly rather than building with missing configuration — a half-configured build never ships silently.
Like your build config, the values are stored encrypted on-chain (see Your data on-chain); "not secret" refers to where they end up — your published build — not how they're stored.
Rules and limits
| Rule | Value |
|---|---|
| Name format | Letter or _ first, then letters, digits, _ |
| Reserved names | BACKEND_URL, AUDIENCE, TOKEN, anything starting with GITHUB_ or ACTIONS_ |
| Duplicates | Not allowed |
| Count | Max 50 per project |
| Value size | Max 4 KB each, 16 KB total |
The panel shows an inline error under any row that breaks a rule. Rows left completely blank are dropped on save.
Verification
After saving and redeploying:
- The new deployment's build sees your variables (e.g. a
NEXT_PUBLIC_*value renders in the page) - The Fetch build env step in the GitHub Actions run log shows a successful fetch
What can go wrong
| Symptom | Cause | Fix |
|---|---|---|
| Variable doesn't show up in the site | The deploy that's live predates your save | Redeploy; check you're looking at the new build, not a cached or pre-FINALIZING domain |
| Save rejected with a name error | Reserved or malformed name | Rename it — see the rules table |
| Deploy fails at the Fetch build env step | Backend was unreachable at build time | Redeploy; if it persists, report it |
Working with an agent
An agent cannot read or change your environment variables, by design: they are encrypted to your wallet and your browser's key only (see Who can decrypt), and no agent API call reaches them. The agent's part is to check the names against the rules above and hand you the exact rows.
What the agent hands you, in these words:
Open the project's Environment tab (/projects/<id>/environment; repo-imported projects only,
an uploaded site has no Environment tab), click Add variable for
each of these rows, fill in Name and Value, then click Save:
<NAME> = <value>
Then click Redeploy on the project Overview. Tell me when the new deployment reads live.How the agent verifies it afterwards. There is no read for the stored values, and there should not be one. What an agent can check is the effect: the variable is public in the shipped build. A NEXT_PUBLIC_* or VITE_* value lands in the JavaScript bundles, not necessarily in the HTML, so check the page and the scripts it loads:
H=https://<your-host>
curl -s "$H/" | grep -c '<the public value>'
curl -s "$H/" | grep -o 'src="[^"]*\.js"' | sed 's/src="//;s/"$//' \
| sed "s|^/|$H/|" | xargs -n1 curl -s | grep -c '<the public value>'A 0 from the first line alone is not a miss. A match in either confirms both the save and the redeploy. A miss in both with the deploy reported live usually means the domain is still FINALIZING on the previous build; run the same check against the deployment's own https://<cid>.ipfs.aleph.sh URL, which serves the new build at once.