How this site was built

spec → tests → capture → verify · July 10–12, 2026

Three apps, one Worker each, one repo: this hub, a model arena, and a daily guessing game. The default everywhere is replay. Recorded model output ships as fixtures checked into the repo, live calls are the exception, and the gate below decides who gets one. Every cost figure on the site comes from the provider’s reported usage on a recording; when a number renders, a capture log backs it.

The pipeline

Spec first, then tests, then one capture pass, then verification. The tooling is part of the product:

Fixtures are captured once and never hand-edited. The game’s 18 candidate prompts were cut to 15 by rules written down before the capture ran; the kill log ships in the repo.

The live-run gate

A live run on the arena walks this list, in order. Any failed check lands on replay.

LIVE-RUN GATEchecks, in order

kill switchfail-closed
bot check (Turnstile)single-use token
per-IP quota3 live runs/day
session quota5 per session
shared pool, all visitors$0.50/day
gateway cap, all models$2.00/day
gateway cap, frontier model$1.00/day
downgrade laddercheaper model → replay

replay fallbackalways on
the order of checks in the budget middleware. The kill switch wants the exact string “true”. Unset, misspelled, half-deployed? All replay. Replay itself never touches this list.

What the build cost

The thesis, applied to the site itself. Two capture passes on July 12 recorded every fixture served here, and this receipt is the entire model-API bill for the content you can see.

BUILD COST · MODEL API2026-07-12

Model Arena — 10 challenges
36 streamed requests$0.0215
of which kept in fixtures$0.0174
Guess Which AI — 18 prompts, 15 sets kept
54 requests, first take kept$0.0079

TOTAL BILLED$0.0294
summed cost_usd from the committed capture logs: provider usage × July 2026 list prices. Arena includes one $0.0041 take a retry superseded — billed is billed, so it stays in the total. One unlogged 8-token sampling probe adds about $0.0001: an estimate, and the only one on this page.

Three recordings worth naming

[fact pending]

How the work split between me and the models is on the about page.

Check the receipts yourself

The token counts on this site are the providers’ own — lifted from each response stream, not re-counted here. The dollar figures are those counts times the per-million prices OpenAI and Anthropic publish, divided out in one small function; a drift alarm recomputes every recorded cost from raw usage at each build and fails if a figure moved. Estimates are labeled as estimates. Below is the code that does the counting, then the tally it produces.

The functions that read tokens and price them

The same interpreters run in the capture harness and on the live path. Token counts come off the provider’s own stream; the dollar line is arithmetic on the published price. These blocks are quoted from the repo, and a build-time check fails if any of them drifts from the source.

packages/fixtures/src/capture/stream.ts · L100–105 — OpenAI token counts, read straight off the stream's final chunk
  // Arrives on the final chunk when stream_options.include_usage is set.
  const usage = o["usage"] as Record<string, unknown> | null | undefined;
  if (usage && typeof usage === "object") {
    if (typeof usage["prompt_tokens"] === "number") update.usageIn = usage["prompt_tokens"];
    if (typeof usage["completion_tokens"] === "number") update.usageOut = usage["completion_tokens"];
  }
packages/fixtures/src/capture/stream.ts · L120–126 — Anthropic input tokens, read from the message_start event
    case "message_start": {
      const usage = ((o["message"] as Record<string, unknown> | undefined)?.["usage"] ?? null) as
        | Record<string, unknown>
        | null;
      if (usage && typeof usage["input_tokens"] === "number") update.usageIn = usage["input_tokens"];
      break;
    }
packages/fixtures/src/capture/stream.ts · L134–138 — Anthropic output tokens, read from the message_delta event
    case "message_delta": {
      const delta = (o["delta"] ?? null) as Record<string, unknown> | null;
      if (delta && typeof delta["stop_reason"] === "string") update.stopReason = delta["stop_reason"];
      const usage = (o["usage"] ?? null) as Record<string, unknown> | null;
      if (usage && typeof usage["output_tokens"] === "number") update.usageOut = usage["output_tokens"];
apps/arena/src/live.ts · L194–197 — Dollars = tokens × the published per-million price, and nothing else
const laneCost = (code: ModelCode, inTok: number, outTok: number): number => {
  const m = MODELS_JSON.models[code];
  return (inTok * m.in_per_mtok + outTok * m.out_per_mtok) / 1_000_000;
};

All ten races, from the committed recordings

This table is built at render time from the same fixture files the arena replays — the numbers are computed from the recordings, not typed in. Across the ten, the cheapest lane won 7 of 10, with cost spreads from 13× to 648×. For ordinary tasks, cheaper usually suffices; the premium lane earns its price on the hard ones. The letter-count race is that case — the priciest lane was the one that returned the right answer — and sort-second is the null, where every lane failed alike and the winner reads nobody.

challengewinnerwinner costspreadverdicts
numbers-1-50 GPT-4.1 nano $0.000056 74× 3 correct · 1 wrong
letter-count Claude Sonnet 5 $0.002276 421× 1 correct · 3 wrong
haiku-cell GPT-4.1 nano $0.000011 38× 4 correct · 0 wrong
receipt-json GPT-4.1 nano $0.000054 17× 3 correct · 0 wrong
email-hunt GPT-5.4 nano $0.000063 113× 3 correct · 1 wrong
twelve-words GPT-4.1 nano $0.000016 14× 2 correct · 1 wrong
sort-second nobody 14× 0 correct · 3 wrong
replace-a4 GPT-4.1 nano $0.000013 14× 2 correct · 1 wrong
third-wednesday GPT-4.1 nano $0.000006 648× 4 correct · 0 wrong
fortune-cookie GPT-4.1 nano $0.000008 13× 3 correct · 0 wrong

Winner recomputed from each recording by the arithmetic rule (correct → cheapest → fastest); spread is the priciest lane’s cost over the cheapest; verdict counts are the recorded pass/fail per lane. Full timelines and prompts: the arena.