Bulls & Cows — Online PvP
Real-time 1v1 number-guessing game with server-authoritative scoring

About
Context, problem & solution
Bulls & Cows Online is a real-time, two-player version of the classic code-breaking game, rebuilt as a mobile-first PWA where every result is decided by the server — never the client.
Context and problem. Turning a turn-based guessing game into a live 1v1 experience raises the two classic hard problems of multiplayer: trust and state. If the client computes its own score, players can cheat; if match state lives only in a database, real-time play feels sluggish. The design had to keep scoring authoritative on the server while staying fast enough to feel instant on a phone.
Solution. The project is a pnpm monorepo split into three parts. The server app runs Fastify 5 and Socket.IO 4 on a single shared HTTP listener, so REST and WebSocket traffic coexist cleanly. The web app is a React + Vite PWA with Zustand for state and the Socket.IO client for live updates. A shared package holds the pieces both sides must agree on — Zod schemas, event-name constants, and the pure game logic — so scoring rules can't drift between client and server. During a match, Redis is the authoritative hot store (fast, ephemeral state); when a match completes, it's written to PostgreSQL through Drizzle ORM for permanent history.
Engineering and quality focus. Putting the game logic in a shared, pure module makes it directly unit-testable in isolation and guarantees the client and server score identically. Validating every inbound event with Zod means malformed or malicious messages are rejected at the boundary. The repository ships a CLAUDE.md documenting architecture invariants and a layered MVP plan under docs/plans/ — a codebase built to be understood and extended, not just to run.
Architecture
How the system is built
Tech stack
Technologies used
Frontend
Backend
Data
Shared package
Want to know more about Bulls & Cows — Online PvP?
The complete source code is available on GitHub, along with the history and deployment configuration.