A browser-based 4-player Commander (EDH) table for playing with friends.
Authoritative rules engine on the server, MTGA-style board in the client, plus auth, lobby, and a deck builder over a growing card pool. One player hosts a table; everyone else claims a seat with their own deck. Eliminated players stay as spectators.
Early and incomplete on purpose. The north star is to support any card faithfully — grown from real cards, with gaps flagged rather than faked. Today that means ~618 deckable card scripts (crates/cards/data/) and an engine that is not rules-complete. The five Secrets of Strixhaven (soc) Commander decks (~389 unique cards) are the first proving ground, not the end of the roadmap.
The public origin ships robots.txt that disallows crawlers; this is a friends table, not a content site.
| Layer | Tech |
|---|---|
| Engine | Pure Rust, deterministic stack/priority state machine |
| Cards | Data-driven TOML scripts (crates/cards/data/) |
| Wire | .proto → tonic gRPC (API) + Effect RPC (browser → Nitro BFF) |
| API | tonic gRPC (game / auth / decks / catalog / seed) + Axum /health/* only |
| BFF / client | Foldkit SPA on Nitro (Vite); lobby + table_routes on Postgres mtgfr_web (Drizzle); canvas + Mount bitmap board + thin HTML overlays |
| Durable data | Postgres mtgfr (users, sessions, decks); mtgfr_web (lobbies, table→pod routes) |
| Deploy | k3s + Cloudflare Tunnel; Argo-owned API/web rolls with SIGTERM drain |
Live games stay in memory per API process. Concurrent pods pin each table via BFF table_routes → pod DNS. Hands and libraries are filtered server-side — private info never leaves for the wrong seat.
docker compose up -d # Postgres on :5432 (`mtgfr` + `mtgfr_web`)
just migrate # Toasty → mtgfr
just client-migrate # Drizzle → mtgfr_web (defaults WEB_DATABASE_URL to local compose)
just dev # tmux: bacon server (:8080) + Foldkit/Vite client (default :3000)WEB_DATABASE_URL defaults to postgresql://mtgfr:mtgfr@127.0.0.1:5432/mtgfr_web (same pattern as the API’s config/mtgfr.toml). Override when pointing at a remote DB.
Useful checks:
just check # format, lint, typecheck, test (server + client)
just test
just --listCONTEXT.md— Magic / domain glossary used in the codePRODUCT.md/DESIGN.md— product intent and design systemdocs/superpowers/specs/— feature specs for existing modules (source of truth)docs/fidelity/— per-deck fidelity reports and increments backlogs (created byfidelity-grind)docs/WIRE_COMPAT.md— expand-only proto rules across drain rollsdocs/README.md— full docs index
Agent-oriented working notes live in AGENTS.md. Releases are cut by semantic-release on main (PRs are squash-merged — the PR title is the release signal).