This is a game. Every token balance, invoice, tier and rate limit in this app is simulated play money. Nothing here reflects real API usage or real cost.
A prediction game dressed as an AI API billing console. Confidence is metered: the surer you claim to be, the more tokens the call costs — and the less it pays back when you turn out to be right. Run out of tokens and your account is rate limited.
Stack: Next.js (app router) · MongoDB Atlas + Atlas Vector Search · Voyage AI
(voyage-3) embeddings · Claude (claude-opus-5).
cp .env.local.example .env.local # fill in the values
npm install
npm run seed # 6 accounts, ~90 calls, embedded + priced
npm run devnpm run seed prints the Atlas Vector Search index definition and tries to
create it. If it can't, paste the printed JSON into Atlas → Atlas Search →
Create Search Index → JSON Editor → Vector Search on the predictions
collection, named prediction_vectors. Check status with npm run index:create.
Until it's queryable the app falls back to in-memory cosine similarity and
labels which path it used, so the demo never hard-fails.
Every account is provisioned with 10,000 simulated tokens.
| Stake (charged on open) | round((100 + confidence × 8) / 10) × 10 |
| Payout (correct) | round(stake ÷ (confidence / 100)) |
| Payout (wrong) | 0 |
| Balance | 10,000 − Σ staked + Σ returned, floored at 0 |
So a 95%-confidence call costs 860 and returns 905 — 45 tokens of upside for maximum swagger. A 30%-confidence call costs 340 and returns 1,133. Conviction is expensive, long shots pay, and being loudly wrong is the fastest way to zero.
Tiers are derived from balance, not stored: Enterprise ≥ 13,000, Pro ≥
8,000, Free ≥ 500, Deprecated below 500. Deprecated accounts are rate
limited — the new-call form is replaced by a 429 panel and the API rejects
writes with HTTP 402.
Brier score and calibration gap survive as secondary accuracy stats:
brier = (confidence/100 − outcome)², calibrationGap = |mean confidence − accuracy|. Behavioural titles (Oracle, Serial Reoffender, Coward, Doomer,
Broken Clock) are still computed from the record.
Seeded standings land as: two Enterprise, one Pro, two Free, and Dev Kapoor bankrupt at 0 and rate limited — he promised to start waking up at 5am four times, reworded each time, at 88–95% confidence, and was wrong every time.
Separate from the money. XP rewards calibration, not volume: the largest term is a calibration bonus that decays cubically with the gap, multiplied by a reliability ramp so one lucky call can't fake it. Eight ranks, from Talking Out Loud to Group Chat Prophet.
The result is a deliberate tension the leaderboard makes visible: Marcus Lin has the most tokens (14,282) by never committing above 55% confidence, but Priya Raman outranks him on XP (1,260, rank 7) with 4,700 fewer tokens and a 3% calibration gap. The bank rewards timidity; the rank rewards being right about how right you are.
Fourteen achievements, all derived from the record rather than stored — Long Shot, Loud And Wrong, Same Take Again, Untouchable. Locked ones stay visible on the shelf so there's something to chase.
Pull the receipts — Atlas Vector Search over one player's own history using the current call's embedding, then Claude roasts them citing specific past calls with dates and confidences. The roast is deliberately short and punchy — it builds to one specific date and number as the punchline.
Forecast the forecaster — submitting a new call runs vector search over that player's settled history first. Accuracy and average confidence on similar calls are computed in code (never by the model), handed to Claude, and returned as a pre-authorisation risk note with an estimated real probability. Nothing is billed until you confirm. Editing the text or the slider invalidates the review.
Settlement desk (/demo) — operator panel. Force any pending call correct or
wrong, see the payout, and watch balances, tiers and rate limits recompute in a
live standings rail.
- Landing page is the money shot — balances, tiers, sparklines, and Dev
Kapoor at the bottom flagged
429 RATE LIMITED. - Open Dev Kapoor. Four wrong 5am promises, each reworded, each ~90% confident. Balance zero, rank 2, new-call form replaced by the 429 panel.
- Open a solvent account, type a call on a topic they have history with, hit Review risk before billing — the risk desk quotes their own record back.
- Pull the receipts on any call — vector search, roast, voice.
/demo→ settle a pending call on stage (Ccorrect,Wwrong, arrows to select). The payout floats off the row, the balance rolls, the tier changes and the standings reorder in place.
| Route | Body | Does |
|---|---|---|
POST /api/predictions |
{playerId, text, confidence, category, deadline} |
Bills the stake, embeds, stores, recomputes score + balance. 402 if rate limited |
POST /api/predictions/:id/resolve |
{status: "correct"|"wrong"|"open", note?} |
Settles, pays out, recomputes score + balance |
POST /api/receipts |
{playerId, predictionId} or {playerId, text, confidence} |
Vector search → Claude roast |
POST /api/forecast |
{playerId, text, confidence} |
Vector search over settled calls → Claude risk note |