Prices were already in the Scryfall bulk download, so this adds no
dependency and no new fetch: the work is deciding what a card's price
means, given that the index keeps one row per card and a card has many
printings.
It is the median of the ordinary printings. The kept printing underprices
about a third of the legal pool because it is chosen for art and identity
and is usually a cheap reprint; the maximum is worse, since premium and
bundled listings put a $870 Sol Ring in the data. The median lands where a
player recognises the number and ignores the outliers. It is a market
value, not a build cost.
Two filter decisions are deliberate and easy to undo by accident: Reserved
List printings are included, because that is where Commander's banned
Power 9 live and excluding them priced Ancestral Recall and Time Walk at
nothing, while memorabilia is excluded because a Collectors' Edition box is
not a single card. Banned cards fall back to their banned printings.
deckValue counts unpriced cards instead of treating them as free, so a
total is always labelled with what it left out.
Also implements scripts/verify-cards.mjs. package.json and the index skill
both documented `pnpm cards:verify` but the script did not exist; it now
runs in deploy and fails on a card priced at exactly zero, which is the
failure mode the missing-price guard exists to prevent.
Co-Authored-By: Claude Code <noreply@anthropic.com>
React 19 SPA + node:http/node:sqlite API in one container. Card data is
baked into the image from a Scryfall bulk build, so the runtime never calls
Scryfall. No server-side user state: decks live in the browser and travel in
the share URL, which is why there is no PVC and replicas: 1 is correct.
Adds a README covering the architecture and the reasoning behind it, and
publishes the project skills under .claude/skills/.
Co-Authored-By: Claude Code <noreply@anthropic.com>