Roadmap
Sequenced by what blocks what.
The north star: be the competition layer small teams reach for — not by outspending anyone, but through care for detail, closeness to the people using it, and pricing nobody can undercut without losing money.
Everything in the first block is built and tested. Everything after it is not, and the order is honest about dependencies rather than about what would be fun to build.
Built
- Identity across apps
- Four aggregations
- Qualifications
- Regional leaderboards
- Async challenges
- Head-to-head + Glicko-2
- Geographic titles
- Badge rule engine
- Collections
- Daily seeds
- Event stream
- Profiles
- Rivals and friend boards
- Blocks
- Reports and moderation
- Invites
- Self-opening waitlists
- GDPR export and deletion
- Retention limits
- Sign in with GitHub or email link
- Key rotation, expiry, revocation
- Self-service apps
- Audit trail
- 220 tests at 97 % coverage
Phase 1
Actually online
Nothing below matters until this is done.
Done when the live smoke test passes against the public URL.
Remote D1 in the EU, worker deployed, custom domain, admin key as a secret
A real migration runner instead of hand-applied files
Cron triggers: retention sweep daily, season close on schedule
Static site and dashboard on Cloudflare Pages
Phase 1b
The rest of the key story
Sign-in and key lifecycle are built. Three pieces need somebody outside us.
Done when a key pushed to a public repository is dead before anyone reads it.
Register chapi_sk_ with GitHub secret scanning, so a leaked key is revoked before anyone reads it
Scoped keys — allowed to submit entries but not to create disciplines
Phase 2
SDKs, so integrating takes five minutes
The whole thesis is that nobody should build this twice. That only holds if integration is trivial in the languages small teams actually use.
Done when somebody who is not us integrates without asking a question.
JavaScript/TypeScript package, typed, browser and worker
Godot plugin in the Asset Library — the most underserved channel
Flutter/Dart package on pub.dev
A drop-in leaderboard widget: one script tag, claim the account later
Two of our own games wired end to end, in public, as the reference
Phase 3
An identity that survives a lost phone
Today, losing the device without an open link code loses the account. Acceptable for a pilot, unacceptable for titles people care about.
Done when a player can move to a new phone with no support contact.
Passkey and email upgrade on top of the anonymous account
Session listing and revocation
Recovery that does not require storing more than we do now
Phase 4
A read path that survives a real population
Ranks are computed in memory from the full standing. Correct, tested, fine for thousands — not for hundreds of thousands.
Done when a district with 100,000 entries answers as fast as one with ten.
Materialised standings per competition key, rebuildable from the ledger
Rank and neighbourhood without loading the whole board
Pagination and cursors on every list endpoint
A load test that is part of the suite, not a one-off
Phase 5
Live
Everything so far works asynchronously on purpose. This is where simultaneity arrives.
Done when two strangers in one city get matched and play without either client claiming a result.
SSE on the event stream, replacing polling
Presence and a matchmaking queue with parties and region hints
Server-issued join tickets so a match server can trust who joined
Signed webhooks with retries
Phase 6
Verification — the part nobody copies in a weekend
The moat is not the code, the code is CC0. It is that a title from here is believable. That needs a machine which can check a claim.
Done when a tier-1 discipline can prove a run instead of trusting it.
Developers upload a deterministic simulation core as a WASM module
We re-run the submitted input trace in a sandbox and compare the state hash
Metered per verified run, because it is real CPU
Verified results carry a mark; unverified ones say so
Phase 7
Ceremony, because a title needs a moment
A season that simply ends is a season nobody remembers.
Done when winning a district title produces something a person wants to post.
Tournaments: brackets, swiss, scheduled finals
Replays and ghosts — race the district champion while they sleep
Season ceremony, permanent title archive, shareable images per title
City clubs and team standings aggregated from individual results
Phase 8
Community surface
We do not win on budget. We win on care and closeness.
Done when the first city final happens with real humans in one room.
OpenAPI specification and generated typed clients
Docs with a live console against a sandbox app
Public changelog, status page, and a place to talk that we actually read
A city-by-city rollout, starting with Hamburg
Phase 9
Billing, and not a day earlier
Metering, invoicing and quotas get built when an outside developer actually needs them — not to have a pricing page.
Done when somebody outside pays for verification or a world-level title.
Usage metering per app
Payment and invoices
Quotas and honest overage behaviour
Out of scope, permanently
What will never be built here.
Every one of these is a place where the big platforms became large, expensive and slow. Staying out of them is the plan, not an oversight.
Inventory and in-game currency
Cloud saves and player storage
Remote config and feature flags
Analytics
Push delivery
Chat
Chat deserves its own sentence: it is where a small competition layer turns into a moderation company. What exists here is challenges, rivals and reports. Conversations belong in your app.