projects

2026liveprivate repo

Trading card game suite

TCG Suite: from an offline life counter to live tournaments and leagues

It started as an offline Magic life counter and now runs tournaments and leagues in the cloud, live and up to 2,048 players, with decks, a priced collection and card search. Magic, Riftbound and Lorcana; the game itself still works with no connection.

Adding a new game is one entry in a registry, not a code branch: the format declares starting life — or points, when you win by adding up — its own counters and the table layout, and the interface derives from that. That is how Riftbound and Lorcana slotted in without touching the views.

Behind it sits a single Cloudflare Worker, and every stateful room is a Durable Object: the online game, each tournament, each league and each user’s data. A tournament lives in its own object and is broadcast over WebSocket to judges, scorekeepers and players, with Swiss rounds, pools, cuts, tiebreakers, penalties and round clocks. Card search runs against an FTS5 index in D1 reloaded daily and atomically — all or nothing — after a half-finished load once left the production index broken for half a day.

The most instructive bug was a service worker one. Fixing the CSP reached nobody who already had the app open: the SW precaches `index.html` with the headers it was downloaded with, and since headers are not part of the bundle, no hash changed, `sw.js` stayed byte-for-byte identical, and the browser saw no update. The fix was to stamp a hash of the headers into the HTML as a `<meta>` at build time, so changing the policy changes the document and with it the precache revision.