Where the games features ended up:
- A "daily" mode where everyone gets the same 12 tiles each day, and the scoring goal randomly changes (most words, longest word, most crossings, rarest words) tracking streaks and leaderboards.
- Real-time multiplayer
- 1v1, or drop an invite link into a group chat and up to 10 people race the same roll live, one Durable Object per match room. If no other human's are queueing to play, you can play bots instead of waiting. There's also Arena, where up to 10 players take a shared roll for a spot on a 24h heat leaderboard.
- No ads, no IAP, no sign-up. Guest play is anonymous auth that upgrades in place if you choose to sign in.
Things I learned:
- Powered by one shared ts core (engine, scoring, word table, match protocol) with a react PWA and react-native for ios/android. The core makes it so the rules can't drift between web and native and so prelim scoring and offline play can be client-side while all ranked and multiplayer scoring is server-side
- Each match room is one Durable Object and since a DO is single-threaded and globally a single-nstance, it's the authoritative in-memory source of truth for the match. that way no external lock or DB round-trip need on the hot path. everyone in the room (up to 10 players) has a websocket to that one object. when players make moves, the DO broadcasts progress delta (tiles used, word count, %) to the other players and streams the board itself for a "watch everyone" view. there are also emojireactions on the same channel
- For timed modes there's a server side match clock. so the DO stamps a start time plus duration when the match goes live, and clients render the countdown from that deadline instead of using a local timer (tried that at first and there was drift). end of match board lock-in fires from a DO timer alarm at 0:00 instead of a client message. I learned the hard way not to let match finalization depend on a client being online or on time so now there's a flush window for in-flight board submissions.
- One real gotcha was the DO lifecycle. learned that Durable Objects can be evicted seemingly randomly and recycled mid-match, so the room has to rehydrate its state instead of assuming it stayed resident, and the streamed game boards needed to survive that. Supporting a max of 10 players per room meant a modest fan-out not requiring anything exotic and the DO's single-threaded consistency kept it all pretty simple and then partyserver handling all the socket plumbing was a breeze
PWA: https://rollsolver.com iOS: https://apps.apple.com/app/id6788792065