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).
Download the example [or clone the repo](https://github.com/mui/material-ui):
This UI communicates with the authoritative backend (`tic-tac-toe`) to deliver a secure, synced, cheat-proof multiplayer experience.
<!-- #target-branch-reference -->
---
```bash
curl https://codeload.github.com/mui/material-ui/tar.gz/master | tar -xz --strip=2 material-ui-master/examples/material-ui-react-router-ts
cd material-ui-react-router-ts
## 🎮 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
* **Leaderboard view** over Nakama's leaderboard API
* **Production Docker image:** Node → Vite → BusyBox
* **Environment-based configuration** for host/SSL
---
## 🧩 Architecture
### Frontend System Diagram
```mermaid
flowchart LR
User[Browser] --> UI[React + TS + Vite]
UI -->|WebSocket| Nakama
UI -->|HTTP| Nakama
UI --> Leaderboard[Leaderboard API]
UI --> Matchmaking[Matchmaker API]
```
Install it and run:
---
```bash
npm install
npm run dev
## 🛠 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
```
or:
Meaning:
<!-- #target-branch-reference -->
* **VITE_WS_HOST** → Nakama host (domain or IP)
* **VITE_WS_PORT** → Port for WebSocket/API
* **VITE_WS_SKEY** → Nakama server key
* **VITE_WS_SSL** → `true` for wss://, `false` for ws://
[](https://codesandbox.io/p/sandbox/github/mui/material-ui/tree/master/examples/material-ui-react-router-ts)
---
[](https://stackblitz.com/github/mui/material-ui/tree/master/examples/material-ui-react-router-ts)
## 🔌 Runtime Flow
## The idea behind the example
### Authentication
<!-- #host-reference -->
* UI generates a device UUID
* Calls `client.authenticateDevice()`
* Stores session in React state
This example demonstrates how you can use MaterialUI with [React Router](https://reactrouter.com/) in [TypeScript](https://github.com/Microsoft/TypeScript).
It includes `@mui/material` and its peer dependencies, including [Emotion](https://emotion.sh/docs/introduction), the default style engine in MaterialUI.
### Matchmaking
## What's next?
1. User selects mode (classic / blitz)
2. joins the matchmaking queue
3. Waits for matchmaker ticket
4. Auto-joins the match when assigned
<!-- #host-reference -->
### Gameplay
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.
* 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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.