003CASE STUDY

Duo Chess

ROLE
Full-stack — solo build
STACK
TypeScript · Cloudflare Durable Objects · React · WebSockets · zod
YEAR
2026
LINK
duo-chess.vercel.app

I wanted to build a real-time multiplayer game from scratch, and 2v2 chess seemed like a good way to make the sync problem harder than usual. Instead of one shared view broadcast to everyone, each player needs to see something slightly different: their own team's pending move and chat, but not the other team's. I settled on one function that takes the server's full room state and produces a per-viewer version of it, so every screen, including up to 20 spectators, is a filtered view of the same underlying state instead of its own separate code path.

For infrastructure I used Cloudflare Durable Objects instead of a normal server plus database, with one Durable Object per game room. That's a good fit since each room is small, short-lived, and only needs strong consistency within itself, but it meant designing around eviction and hibernation instead of a process that just stays running. I also had to decide how much to trust the client: pieces move optimistically in the UI for responsiveness, but the server re-validates every move with chess.js before committing it, so the client can render ahead but never actually decide legality. Team play adds its own edge cases too, like a solo team (in a 3-player game) moving directly with no confirmation step, or a team whose teammate is currently disconnected being treated as solo. Both cases route through the same move-commit logic as a normal 2v2 turn instead of a separate path.

SCREENSHOTS

GAME BOARD
GAME BOARD
LOBBY
LOBBY
TEAM SELECT
TEAM SELECT
TEAMMATE ANNOTATIONS
TEAMMATE ANNOTATIONS
TEAM CHAT
TEAM CHAT
MOBILE LAYOUT
MOBILE LAYOUT

NEXT PROJECT

001LearnGraph