Skip to content

About

Real-time multiplayer Uno web game with authoritative server-side state machine, AI bot simulation, competitive Elo rankings, and animated card physics.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Uno Online

CI License: MIT Next.js React Socket.io Prisma

A real-time multiplayer Uno Web Game engineered with an authoritative game engine, intelligent AI bot fallback, Elo rating leaderboards, and animated card physics powered by Framer Motion and Next.js 16.


🏗️ System Architecture

flowchart TB
    subgraph Clients["Browser Clients (Players & Spectators)"]
        PlayerA["Player 1\n(React 19 + Framer Motion)"]
        PlayerB["Player 2 / Mobile\n(Touch-friendly UI)"]
        Audio["Web Audio Sound Manager\n(Synthesized FX)"]
    end

    subgraph Server["Authoritative Game Server (server.js)"]
        SocketServer["Socket.io Gateway\n(Room Subscriptions)"]
        
        subgraph Engine["Game Engine Core (lib/UnoEngine.js)"]
            StateMachine["State Machine\n(Turn Order, Direction, Current Color)"]
            RuleValidator["Action & Stacking Rule Validator\n(+2 / +4 Stacking Chaining)"]
            BotRunner["AI Bot Simulation\n(1.2s Human Delay & Heuristics)"]
            RoomManager["Room Lifecycle Manager\n(Auto-Destroy Inactivity Timers)"]
        end
    end

    subgraph Persistence["Persistence & Ranking"]
        Prisma["Prisma ORM\n(@prisma/client)"]
        Database[("SQLite Database\n(Elo Ratings, Match History, Replays)")]
    end

    PlayerA <-->|"WebSocket Events (join_room, card:play)"| SocketServer
    PlayerB <-->|"WebSocket Events (card:draw, call_uno)"| SocketServer

    SocketServer <--> StateMachine
    StateMachine --> RuleValidator
    StateMachine --> BotRunner
    StateMachine --> RoomManager

    SocketServer -->|"update_game_state (Private hand + Public state)"| PlayerA
    SocketServer -->|"update_game_state"| PlayerB
    StateMachine -.->|"play audio cue"| Audio

    SocketServer -->|"Match Finished (handleGameOver)"| Prisma
    Prisma <--> Database
Loading

✨ Features

  • 🎮 Authoritative Game Engine (lib/UnoEngine.js): All card validity, turn rotation, card drawing, and penalty resolutions occur on the server, eliminating desync and client-side tampering.
  • ⚡ Real-Time Room Synchronization: Instant turn notifications, card flip animations, and public discard pile synchronization using Socket.io.
  • 🤖 Intelligent AI Bots: Fill empty seats with autonomous AI players. Bots evaluate color matching, action card utility, and respond with a natural human-like 1.2s thinking delay.
  • 🔥 Competitive Stacking Rules: Support for chain penalties — players can stack +2 on top of +2, or +4 on top of +2/+4 to pass accumulated card draw penalties to the next player.
  • 🏆 Elo Rating & Leaderboards: Integrated competitive rating system (+25 Elo on win, -10 Elo on loss) with player match records saved in SQLite via Prisma ORM.
  • 📢 UNO Shout & Catch Penalty: Real-time "UNO!" button with penalty mechanics if an opponent calls out a player with one card who forgot to call UNO.
  • 🔊 Synthesized Web Audio FX: Card shuffle, flip, color change, draw, reverse, and victory fanfare sound effects.
  • 📱 Fully Responsive: Fluid animations across mobile phones, tablets, and wide desktop screens.

📡 WebSocket Event Reference

Event Name Direction Payload Description
get_rooms Client → Server — Fetch list of active public rooms in the lobby
create_room Client → Server { roomCode, username, maxPlayers, config } Initialize a new multiplayer room
join_room Client → Server { roomCode, username } Connect player to room and assign seat
start_game Client → Server { roomCode } Host triggers game start; deck is dealt
card:play Client → Server { roomCode, cardId, chosenColor } Submit a card move to the engine
card:draw Client → Server { roomCode } Draw card(s) from deck or accept stacked penalty
call_uno Client → Server { roomCode } Call UNO or challenge opponent's single-card status
add_bot Client → Server { roomCode } Spawn an AI bot player into an empty room seat
update_game_state Server → Client GameState (sanitized per player) Broadcasts updated table, turn index, and player's private hand
game_over Server → Client { winner } Displays winner screen and updates Elo ratings in DB

🚀 Quick Start

Prerequisites

  • Node.js 20.x or 22.x
  • npm 9.x or newer

1. Clone & Install

git clone https://github.com/stenlysayd/uno-online.git
cd uno-online
npm install

2. Environment Setup

cp .env.example .env

3. Initialize Database

Generate Prisma client artifacts and create local SQLite schema tables:

npm run db:generate
npm run db:push

4. Run Development Server

npm run dev

Open http://localhost:3000 in your browser.

Tip

Testing Multiplayer Locally: Open two separate browser windows (or an incognito window) at http://localhost:3000. Enter a player name in each window and join the same room code!


🛠️ Production Build & Deployment

Because Uno Online utilizes custom WebSocket handling via server.js, it runs as a dedicated Node process:

# Build Next.js client and SSR bundles
npm run build

# Launch the production HTTP + WebSocket server
npm start

Deployable to any container or VPS platform (Docker, Railway, Render, Fly.io, DigitalOcean, or AWS EC2).


🤝 Contributing

Contributions are welcome! Please review CONTRIBUTING.md for contribution guidelines and architectural overview.


🔒 Security

For responsible disclosure guidelines, please see SECURITY.md.


📄 License

This project is licensed under the MIT License © 2026 Stenly Sayd.

About

Real-time multiplayer Uno web game with authoritative server-side state machine, AI bot simulation, competitive Elo rankings, and animated card physics.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages