Inspiration
We wanted a fast, social way to play Mahjong online with friends, without needing everyone in the same place.
What it does
A real-time multiplayer Mahjong web app where players can draw, discard, and react (chi/pong/kong) with updates synced instantly across all clients.
How we built it
Frontend in React, backend in Flask + Socket.IO. Game actions are emitted over WebSockets, the server validates the move, updates the game state, and broadcasts state updates to each player (including private hands + public table info).
Challenges we ran into
The hardest part was game logic + state correctness: Mahjong has many branching “reaction” states, priority rules, and turn ownership changes. Keeping backend state authoritative while the frontend stayed responsive was tricky—especially avoiding race conditions and accidental extra draws when turn state changed through reactions. WebSocket event timing and per-player state syncing (public vs private) added extra complexity.
Accomplishments that we're proud of
We got the core real-time loop working: draw/discard, reaction prompts to only eligible players, and consistent state sync across all screens. The structure is solid enough to extend safely.
What we learned
State machines matter. Clear separation between “public table state” and “private player state” is essential, and WebSocket apps need careful guards to prevent duplicate actions and out-of-order updates.
What's next for mahjong web app
Finish the planned power-up card system, polish the UI for revealed/point hands, add better validation + logging, and tighten the turn/reaction state machine so edge cases are handled cleanly.
Log in or sign up for Devpost to join the conversation.