Tech
Self-hosting and deployment
Run Animr locally or deploy it to Vercel: environment variables, Redis, crons and the external pulse.
Run it locally
npm install
cp .env.example .env.local # every value is optional
npm run dev # http://localhost:3000With no keys at all, everything except the LLM works: the League, Time Machine, Versus, Bell (genome calls) and heist (template defender). State goes to .data/ as JSON files.
Environment variables
Names and purpose only. NEXT_PUBLIC_* values are inlined at build time, so changing one needs a rebuild. Never give a secret a NEXT_PUBLIC_ prefix.
| Variable | Type | Purpose |
|---|---|---|
| CRON_SECRET | Secret | Protects /api/bell/cron and /api/agent/tick. Required in production, where the external pulse sends it as a Bearer header. |
| UPSTASH_REDIS_REST_URL / _TOKEN, or KV_REST_API_URL / _TOKEN | Secret | Shared state: Bells, rides, fan cards, the heist's counters and budget, agents. Required in production: without it state is per instance and lost on cold starts, and the heist fails closed (the House Chog naps). On Vercel, connect Upstash from the Marketplace. |
| ZG_API_KEY | Secret | 0G Compute Router key. Without it, rules and templates decide. |
| ZG_MODEL, ZG_BASE_URL, ZG_JSON_MODE, ZG_THINKING, ZG_VERIFY_TEE | Config | Optional 0G settings (server-only) |
| OPERATOR_PRIVATE_KEY | Secret | The AI operator key for on-chain mode and trophy mints. A fresh hot wallet with gas only. |
| OPERATOR_ADDRESS | Config | The operator's public address, for the heist proof and the deploy script |
| NEXT_PUBLIC_TRADE_GUARD_ADDRESS | Config | The guard. Unset on mainnet means the live guard; empty means paper only. |
| NEXT_PUBLIC_TROPHIES_ADDRESS | Config | AnimrTrophies. Unset turns the cabinet and awards off. |
| HOUSE_CHOG_TOKEN_ID | Config | The House Chog's token ID (1399), never its CHOG # number |
| ORACLE_PURSE_CHOG | Config | Whole $CHOG per Oracle Purse; unset or 0 means none. The Daily Bell page shows this deployment's value. Set the same value where the purse job runs. |
| HEIST_DAILY_USD_CAP | Config | 0G spend per UTC day on heist replies (default 3) |
| HEIST_ADMIN_SECRET | Secret | Bearer token for Hall of Fame moderation |
| HEIST_IP_SALT | Secret | Key for hashing visitors' IPs (default: derived from CRON_SECRET) |
| CHOG_CHAT_DAILY_CALLS | Config | Ask this Chog's 0G calls per UTC day (default 1500) |
| ANIMR_MANUAL_RUNS_PER_DAY | Config | Global Think now cap (default 400) |
| NEXT_PUBLIC_PRIVY_APP_ID, NEXT_PUBLIC_PRIVY_CLIENT_ID | Config | Privy login. Unset means the plain wallet menu. |
| NEXT_PUBLIC_SITE_URL | Config | Origin for share-card URLs (optional on Vercel) |
| NEXT_PUBLIC_RPC_URL, NEXT_PUBLIC_IPFS_GATEWAY | Config | Optional overrides; they ship to every browser |
| OPENSEA_API_KEY | Secret | Optional; without it the app requests a short-lived key for /market |
| FARCASTER_HEADER, FARCASTER_PAYLOAD, FARCASTER_SIGNATURE | Config | Mini App account association (server-only) |
| ANIMR_ENV, ANIMR_DATA_DIR | Config | Redis namespace and local file store; leave unset on Vercel |
| HOUSE_PRIVATE_KEY, HOUSE_ADDRESS, ADMIN_ADDRESS | Secret | Scripts only. Never on Vercel. |
Never change the Chog NFT, $CHOG, account implementation or salt variables: that would move every wallet address.
Deploy on Vercel
- Import the repo with the Next.js preset and no overrides; keep Fluid Compute on (the Bell routes use a 300-second max duration).
- Connect Upstash Redis from the Vercel Marketplace (it adds
KV_REST_API_URLandKV_REST_API_TOKEN; theUPSTASH_REDIS_REST_*pair works too), then add the variables above (secrets as Secret, production only) and redeploy. Redis is required: without it the Bell, rides and the heist don't persist, and the House Chog naps. vercel.jsonalready calls/api/bell/cronat 15:00 and 16:00 UTC, but Vercel Hobby only allows daily crons and fires them anywhere within the hour. Add two jobs on an external scheduler (for example cron-job.org), each a GET withAuthorization: Bearer <CRON_SECRET>:/api/bell/cronat minutes 1 and 11 of every hour (1,11 * * * *) and/api/agent/tickat minute 30 (30 * * * *). On-chain agents decide only on that tick and at the Bell.- Only the production deployment sends guarded trades and trophy mints (
VERCEL_ENV=production, orANIMR_ENVelsewhere). Previews with the same variables stay paper-only. - The Oracle Purse is a scheduled job the team runs outside Vercel:
scripts/send-oracle-purse.mts --broadcastwithANIMR_ENV=production, the production Redis pair,HOUSE_PRIVATE_KEYand the sameORACLE_PURSE_CHOG. The app never reads the House key. - Redeploy after any variable change.
/guard, the landing page and the docs are prerendered, so House Chog and purse changes show after a rebuild.
Contracts
forge test --fork-url https://rpc.monad.xyz -vv
OPERATOR_ADDRESS=0x... ADMIN_ADDRESS=0x... forge script script/DeployAnimrTradeGuard.s.sol --rpc-url monad # dry runDetails: AnimrTradeGuard.
