Skip to main content
Mohamed Amine MIDENI
All projects

Bulls & Cows — Online PvP

Real-time 1v1 number-guessing game with server-authoritative scoring

React 18ViteTailwind CSSZustandSocket.IO client
Bulls & Cows — Online PvP

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

architecture.diagram
Players
React PWA
Mobile-firstSocket.IO clientZustand state
Realtime server
Fastify + Socket.IO
One HTTP listenerZod-validated events
Game engine
Server-side scoring
Pure logic in shared pkgNo client trust
State & history
Redis
Live match stateFast reads/writes
PostgreSQL
Completed matchesDrizzle ORM
Real-time 1v1 over Socket.IOServer-authoritative scoring (no client trust)Redis as the hot store during a matchPostgreSQL + Drizzle for match historyShared package: Zod schemas + pure game logicpnpm monorepo, mobile-first PWA

Tech stack

Technologies used

Frontend

React 18ViteTailwind CSSZustandSocket.IO clientPWA (mobile-first)

Backend

Fastify 5Socket.IO 4Single shared HTTP listenerNode.js ≥ 20

Data

Redis (authoritative live state)PostgreSQL (match history)Drizzle ORM

Shared package

Zod schemasPure game logicShared event-name constantsTypeScript monorepo (pnpm)

Want to know more about Bulls & Cows — Online PvP?

The complete source code is available on GitHub, along with the history and deployment configuration.