Vishesh 'ironeagle' Bangotra 7671e9b2cc feat: add draw-state support using game_over flag and update UI handling
Updated match data callback to interpret { game_over: true, winner: -1 } as a draw.

Added winner = "draw" UI state for display and disabling board interactions.

Updated status text in Board component to show “Draw!” when applicable.

Adjusted winner highlighting logic to avoid highlighting any symbol during draw.

Ensured ongoing games always set winner = null for consistent behavior.
2025-12-01 18:16:46 +05:30
2025-11-29 18:49:40 +05:30
2025-11-30 01:23:51 +05:30
2025-11-27 16:26:51 +05:30
2025-11-29 04:21:34 +05:30
2025-11-30 01:23:51 +05:30
2025-12-01 08:30:29 +00:00
2025-11-27 16:26:51 +05:30
2025-11-27 16:26:51 +05:30

tic-tac-toe-ui — Multiplayer Game Client (React + TypeScript + Vite)

A fully functional multiplayer Tic-Tac-Toe game client built using React + TypeScript, powered by Nakama WebSocket real-time networking, and delivered as a tiny production-optimized Vite build (served via BusyBox/Docker).

This UI communicates with the authoritative backend (tic-tac-toe) to deliver a secure, synced, cheat-proof multiplayer experience.


🎮 Overview

This repository contains the front-end implementation of the Tic-Tac-Toe multiplayer platform.

The client supports:

  • Device-based authentication
  • Full matchmaking lifecycle
  • Real-time gameplay with WebSockets
  • Authoritative state rendering
  • Leaderboard browsing
  • Game result screens
  • A Vite-powered environment system for dynamic host/SSL selection

This UI is production-ready and deployable to any server or container environment.


Features

  • React + TypeScript UI
  • WebSocket real-time gameplay using Nakama JS
  • Matchmaking flow: queue → ticket → match → gameplay
  • Authoritative state updates (OpCode 2)
  • Secure device authentication (device UUID → session)
  • Leaderboard view over Nakama's leaderboard API
  • Production Docker image: Node → Vite → BusyBox
  • Environment-based configuration for host/SSL

🧩 Architecture

Frontend System Diagram

flowchart LR
    User[Browser] --> UI[React + TS + Vite]
    UI -->|WebSocket| Nakama
    UI -->|HTTP| Nakama
    UI --> Leaderboard[Leaderboard API]
    UI --> Matchmaking[Matchmaker API]

🛠 Tech Stack

  • React 18 (TypeScript)
  • Vite.js (build system)
  • Nakama JavaScript Client
  • Plain CSS for styling
  • WebSockets (SSL / non-SSL selectable)
  • Docker (multi-stage build)

🔧 Environment Variables (Vite)

These are injected at build time:

VITE_WS_HOST=nakama.aetoskia.com
VITE_WS_PORT=443
VITE_WS_SKEY=secret
VITE_WS_SSL=true

Meaning:

  • VITE_WS_HOST → Nakama host (domain or IP)
  • VITE_WS_PORT → Port for WebSocket/API
  • VITE_WS_SKEY → Nakama server key
  • VITE_WS_SSLtrue for wss://, false for ws://

🔌 Runtime Flow

Authentication

  • UI generates a device UUID
  • Calls client.authenticateDevice()
  • Stores session in React state

Matchmaking

  1. User selects mode (classic / blitz)
  2. joins the matchmaking queue
  3. Waits for matchmaker ticket
  4. Auto-joins the match when assigned

Gameplay

  • User sends moves via OpCode 1
  • Server validates + broadcasts authoritative board via OpCode 2
  • UI re-renders board state from server packets

End of Game

  • Player sees win/lose/draw
  • Can return to home or matchmaking

🎨 Styling

Styling uses plain CSS via a single styles.css file. Simple, responsive layout using Flexbox.


🐳 Docker (Production Build)

Dockerfile Overview

# Stage 1: Build
FROM node:20-alpine AS builder

# Set working directory
WORKDIR /app

# Copy package.json and package-lock.json (or yarn.lock)
COPY package*.json ./

# Install dependencies
RUN npm ci

# Copy the rest of the app
COPY . .

# Build arguments
ARG VITE_WS_HOST
ARG VITE_WS_PORT
ARG VITE_WS_SKEY
ARG VITE_WS_SSL

# Export them as actual environment variables (Vite needs ENV)
ENV VITE_WS_HOST=${VITE_WS_HOST}
ENV VITE_WS_PORT=${VITE_WS_PORT}
ENV VITE_WS_SSL=${VITE_WS_SSL}

# Build
RUN npm run build

# Stage 2: Static file server (BusyBox)
FROM busybox:latest

WORKDIR /app

# Copy only build frontend files
COPY --from=builder /app/dist /app

# Expose port
EXPOSE 3000

# Default command
CMD ["busybox", "httpd", "-f", "-p", "3000"]

Produces an extremely lightweight production image.


🧪 Testing

Manual testing validated:

  • Full matchmaking loop
  • Game state sync
  • Invalid move handling (server rejections)
  • Disconnect behaviour
  • Leaderboard retrieval

Pending:

  • Stress tests
  • Mobile responsiveness
  • Reconnect logic

📈 Deployment

Supported:

  • Docker on any Linux host
  • Raspberry Pi (ARM)
  • Google Cloud Run / Compute Engine
  • Traefik reverse proxy via games.aetoskia.com

Example Deployment via Docker

docker run -d \
  -p 3003:3003 \
  --restart always \
  tic-tac-toe-ui:latest

Traefik HTTPS routes:

  • games.aetoskia.com → UI

🗺️ Roadmap

  • Rematch flow
  • Reconnect/resume after refresh
  • Improved animations
  • Mobile UI redesign
  • Centralized error handling

Description
No description provided
Readme 401 KiB
Languages
TypeScript 89.5%
CSS 5.6%
Dockerfile 1.9%
HTML 1.5%
JavaScript 1.5%