Environment variables
The repo-root .env.example lists every env var with a comment explaining its purpose and whether it is server-only. This page groups them by domain.
Security tiers
The NEXT_PUBLIC_* prefix means the value is injected into the client bundle. Never put a secret in a public variable.
Core
NEXT_PUBLIC_SITE_URL is the canonical URL; data/site.ts falls back to https://arsvine.com if unset.
Public
Content (external GitHub repo)
When all four are unset:
- Blog posts fall back to
content/blog/init/(built-in 6-locale fallback) - Tweets fall back to an empty state (unless dev
TWEETS_STRESS_TEST=1) - Protected posts are naturally unavailable
Security
ACCESS_GRANT_SECRET signs the HttpOnly access-grant cookie. TOTP_GROUPS_JSON is a group → TOTP secret map. REVALIDATE_SECRET guards /api/revalidate*. TRUST_PROXY=1|true|yes lets a trusted proxy pass X-Forwarded-For; otherwise rate limits use req.socket.remoteAddress.
Infra
UPSTASH_* is auto-injected when Upstash is provisioned through the Vercel Marketplace. When configured, lib/content/rate-limit.ts uses Redis for cross-instance rate limiting; otherwise it falls back to a process-local Map.
COS_* is only used by scripts/assets-publish.mjs; dev does not need it. Credentials are injected at runtime through node --env-file=.env.local. Never write them into a coscli config file.
Tweets Dev (dev only)
Synthetic data lets the tweets page show pagination and components even without the external repo. Never enable in production.
Advanced
Checklist for adding a new env var
- Add a fully commented line to
.env.example - Run
pnpm env:syncif you let the sync script manage that file - Any server-only env must be read via
process.env.<NAME>; public envs require theNEXT_PUBLIC_prefix - Any dev-only env must have a
process.env.NODE_ENV !== 'production'guard in production code - In docs, write the variable name and purpose only; never the real value