31 Commits

Author SHA1 Message Date
70669fc856 Update README.md 2025-12-01 08:33:28 +00:00
1752bfaed4 Update README.md 2025-12-01 08:33:01 +00:00
74e75de577 Update README.md 2025-12-01 08:32:29 +00:00
7983be56e4 Update README.md 2025-12-01 08:27:57 +00:00
e9eb37f665 fixes 2025-11-30 02:06:50 +05:30
7a7c6adc47 updated report 2025-11-30 02:04:41 +05:30
ae5628f370 proper pipeline
All checks were successful
continuous-integration/drone/tag Build is passing
2025-11-30 01:26:56 +05:30
e8e2419537 proper pipeline
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2025-11-30 01:20:02 +05:30
4ee6027612 fixes
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 23:58:52 +05:30
389e77e2ae fixes
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 23:54:51 +05:30
7ce860db96 copy local.yml
Some checks failed
continuous-integration/drone/push Build is failing
2025-11-29 23:51:50 +05:30
92f307d33d copy local.yml
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 23:47:57 +05:30
6e7d2d9f14 fixes
All checks were successful
continuous-integration/drone Build is passing
2025-11-29 22:32:59 +05:30
c91dba475c fixes 2025-11-29 22:23:43 +05:30
04d988c584 fixes 2025-11-29 22:23:37 +05:30
27abc56a00 fixes
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 22:23:23 +05:30
333b48ad60 fixes
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 22:16:25 +05:30
4dee0bfb0a fixes
Some checks failed
continuous-integration/drone/push Build is failing
2025-11-29 22:12:52 +05:30
1e91825808 buildx no push and use arm64 everywhere
Some checks failed
continuous-integration/drone/push Build is failing
2025-11-29 22:10:33 +05:30
c5cb1047ae buildx no push and use
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 21:59:49 +05:30
18f9eed71d no buildx and push
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-29 21:45:50 +05:30
02de328bcd fixes
Some checks reported errors
continuous-integration/drone/push Build is failing
continuous-integration/drone Build was killed
2025-11-29 21:35:36 +05:30
31f1a66fed arm64 images
Some checks failed
continuous-integration/drone/push Build is failing
2025-11-29 21:28:26 +05:30
5065145c6f direct deploy
Some checks reported errors
continuous-integration/drone/push Build was killed
2025-11-29 21:27:09 +05:30
8e0475c8a7 build arm64 image
Some checks failed
continuous-integration/drone/tag Build is failing
2025-11-29 21:18:54 +05:30
1359a75214 allow games.aetoskia.com
All checks were successful
continuous-integration/drone/tag Build is passing
2025-11-29 19:41:33 +05:30
6786547950 enabled tag based deployment
All checks were successful
continuous-integration/drone/tag Build is passing
2025-11-29 19:06:11 +05:30
17a2caea49 fixes
Some checks failed
continuous-integration/drone Build is failing
2025-11-29 19:02:01 +05:30
8ff199ca10 fixes
Some checks failed
continuous-integration/drone Build is failing
2025-11-29 18:59:02 +05:30
62c1f3920b fixes
Some checks failed
continuous-integration/drone/tag Build is failing
2025-11-29 18:42:41 +05:30
73e3f0a7ac fixes
Some checks failed
continuous-integration/drone/tag Build is failing
2025-11-29 18:38:13 +05:30
3 changed files with 240 additions and 251 deletions

View File

@@ -17,7 +17,7 @@ volumes:
steps: steps:
# ----------------------------------------------------- # -----------------------------------------------------
# 1. Fetch latest Git tag # 1. Fetch latest Tags
# ----------------------------------------------------- # -----------------------------------------------------
- name: fetch-tags - name: fetch-tags
image: docker:24 image: docker:24
@@ -28,34 +28,43 @@ steps:
- apk add --no-cache git - apk add --no-cache git
- git fetch --tags - git fetch --tags
- | - |
# Get latest Git tag and trim newline
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null | tr -d '\n') LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null | tr -d '\n')
echo "Latest Git tag: $LATEST_TAG" echo "Latest Git tag fetched: $LATEST_TAG"
# Save to file for downstream steps
echo "$LATEST_TAG" > /drone/src/LATEST_TAG.txt echo "$LATEST_TAG" > /drone/src/LATEST_TAG.txt
if [ -z "$LATEST_TAG" ]; then
echo "❌ No git tags found. Cannot continue." # Read back for verification
IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
echo "Image tag read from file: $IMAGE_TAG"
# Validate
if [ -z "$IMAGE_TAG" ]; then
echo "❌ No git tags found! Cannot continue."
exit 1 exit 1
fi fi
# ----------------------------------------------------- # -----------------------------------------------------
# 2. Check if remote image already exists # 2. Check existing Nakama Docker image
# ----------------------------------------------------- # -----------------------------------------------------
- name: check-remote-image - name: check-remote-image
image: docker:24 image: docker:24
volumes: volumes:
- name: dockersock - name: dockersock
path: /var/run/docker.sock path: /var/run/docker.sock
environment:
REGISTRY_HOST:
from_secret: REGISTRY_HOST
commands: commands:
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
- echo "Checking if $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG exists..."
- echo "Checking if lila-games/nakama-server:$IMAGE_TAG exists on remote Docker..."
- echo "Existing Docker tags for lila-games/nakama-server:"
- docker images --format "{{.Repository}}:{{.Tag}}" | grep "^lila-games/nakama-server" || echo "(none)"
- | - |
if docker pull $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG > /dev/null 2>&1; then if docker image inspect lila-games/nakama-server:$IMAGE_TAG > /dev/null 2>&1; then
echo "✅ Image already exists: $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG" echo "✅ Docker image lila-games/nakama-server:$IMAGE_TAG already exists — skipping build"
exit 78 exit 78
else else
echo "⚙️ Image does not exist. Will build." echo "⚙️ Docker image lila-games/nakama-server:$IMAGE_TAG not found — proceeding to build..."
fi fi
# ----------------------------------------------------- # -----------------------------------------------------
@@ -68,22 +77,19 @@ steps:
path: /var/run/docker.sock path: /var/run/docker.sock
commands: commands:
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
- echo "🔨 Building Nakama image lila-games/nakama-server:$IMAGE_TAG"
- echo "🔨 Building Nakama image lila-games/nakama-server:latest"
- | - |
docker build \ docker build --network=host \
--network=host \
-t lila-games/nakama-server:$IMAGE_TAG \ -t lila-games/nakama-server:$IMAGE_TAG \
-t lila-games/nakama-server:latest \ -t lila-games/nakama-server:latest \
/drone/src /drone/src
# ----------------------------------------------------- # -----------------------------------------------------
# 4. Push Nakama image to registry # 4. Push Nakama Image
# ----------------------------------------------------- # -----------------------------------------------------
- name: push-image - name: push-image
image: docker:24 image: docker:24
volumes:
- name: dockersock
path: /var/run/docker.sock
environment: environment:
REGISTRY_HOST: REGISTRY_HOST:
from_secret: REGISTRY_HOST from_secret: REGISTRY_HOST
@@ -91,15 +97,20 @@ steps:
from_secret: REGISTRY_USER from_secret: REGISTRY_USER
REGISTRY_PASS: REGISTRY_PASS:
from_secret: REGISTRY_PASS from_secret: REGISTRY_PASS
volumes:
- name: dockersock
path: /var/run/docker.sock
commands: commands:
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
- echo "🔑 Logging into registry..."
- echo "🔑 Logging into registry $REGISTRY_HOST ..."
- echo "$REGISTRY_PASS" | docker login $REGISTRY_HOST -u "$REGISTRY_USER" --password-stdin - echo "$REGISTRY_PASS" | docker login $REGISTRY_HOST -u "$REGISTRY_USER" --password-stdin
- echo "🏷️ Tagging images..." - echo "🏷️ Tagging images with registry prefix..."
- docker tag lila-games/nakama-server:$IMAGE_TAG $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG - docker tag lila-games/nakama-server:$IMAGE_TAG $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG
- docker tag lila-games/nakama-server:$IMAGE_TAG $REGISTRY_HOST/lila-games/nakama-server:latest - docker tag lila-games/nakama-server:$IMAGE_TAG $REGISTRY_HOST/lila-games/nakama-server:latest
- echo "📤 Pushing images..." - echo "📤 Pushing lila-games/nakama-server:$IMAGE_TAG ..."
- docker push $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG - docker push $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG
- echo "📤 Pushing lila-games/nakama-server:latest ..."
- docker push $REGISTRY_HOST/lila-games/nakama-server:latest - docker push $REGISTRY_HOST/lila-games/nakama-server:latest
# ----------------------------------------------------- # -----------------------------------------------------
@@ -142,9 +153,7 @@ steps:
--add-host private-pi:192.168.1.111 \ --add-host private-pi:192.168.1.111 \
-e DB_ADDR="$DB_ADDR" \ -e DB_ADDR="$DB_ADDR" \
-e SERVER_KEY="$SERVER_KEY" \ -e SERVER_KEY="$SERVER_KEY" \
-v /mnt/omnissiah-vault/data/nakama/modules:/nakama/data/modules \ lila-games/nakama-server:latest
-v /mnt/omnissiah-vault/data/nakama/storage:/nakama/data \
$REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG
# ----------------------------------------------------- # -----------------------------------------------------
# Pipeline trigger # Pipeline trigger

View File

@@ -1,21 +1,19 @@
# ----------------------------------------------------- # -----------------------------------------------------
# 1. Build the Nakama plugin (ARM64) # 1. Build the Nakama plugin
# ----------------------------------------------------- # -----------------------------------------------------
FROM golang:1.22-alpine AS plugin_builder FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
# Install dependencies needed for CGO plugin build RUN apt-get update && apt-get install -y \
RUN apk add --no-cache git build-base build-essential \
git
WORKDIR /workspace WORKDIR /workspace
# Download module deps first (better caching)
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN go mod download
# Copy source code
COPY . . COPY . .
# Build plugin
RUN mkdir -p build && \ RUN mkdir -p build && \
CGO_ENABLED=1 go build \ CGO_ENABLED=1 go build \
--trimpath \ --trimpath \
@@ -25,16 +23,13 @@ RUN mkdir -p build && \
# ----------------------------------------------------- # -----------------------------------------------------
# 2. Build final Nakama image (ARM64) # 2. Build final Nakama image
# ----------------------------------------------------- # -----------------------------------------------------
FROM --platform=linux/arm64 heroiclabs/nakama:3.21.0 AS nakama FROM heroiclabs/nakama:3.21.0-arm
# Copy plugin from builder stage # Copy plugin from builder stage
COPY --from=plugin_builder /workspace/build/main.so /nakama/data/modules/main.so COPY --from=plugin_builder /workspace/build/main.so /nakama/data/modules/main.so
#COPY --from=plugin_builder local.yml /nakama/data/config.yml
# Default Nakama startup (runs migrations + server) # Default Nakama startup (runs migrations + server)
ENTRYPOINT [ ENTRYPOINT exec /bin/sh -ecx "/nakama/nakama migrate up --database.address \"$DB_ADDR\" && exec /nakama/nakama --database.address \"$DB_ADDR\" --socket.server_key=\"$SERVER_KEY\""
"/bin/sh", "-ecx", "\
/nakama/nakama migrate up --database.address \"$DB_ADDR\" && \
exec /nakama/nakama --database.address \"$DB_ADDR\" --socket.server_key=\"$SERVER_KEY\""
]

403
README.md
View File

@@ -1,287 +1,272 @@
# ✅ Project Status Report # tic-tac-toe — Authoritative Multiplayer Game Server (Nakama + Go)
## Multiplayer Tic-Tac-Toe Platform A production-grade, server-authoritative multiplayer backend built using **Nakama 3**, **Go plugins**, and **PostgreSQL**, deployed via **Drone CI/CD** and exposed securely through **Traefik**.
**To:** CTO & Technical Interview Panel
**Date:** November 28, 2025
**Version:** v0.2.0
--- ---
## **1. Objective** ## 🚀 Overview
Design and implement a lightweight, scalable, server-authoritative multiplayer game system using **Nakama + Go plugins This repository contains a fully authoritative Tic-Tac-Toe backend built on **Nakama 3.21.0 ARM**, using a custom **Go plugin** to implement game logic, matchmaking, validation, leaderboards, and session management.
**, supporting authentication, matchmaking, authoritative gameplay, leaderboards, and a functional UI — deployable to
Google Cloud for demonstration. The server ensures:
* **Zero client trust**
* **Deterministic gameplay**
* **Secure matchmaking**
* **Validated moves**
* **Authoritative outcomes**
Designed for scalability, extensibility, and cloud deployment (GCP, AWS, or ARM homelab environments).
--- ---
## **2. Current Completion Summary** ## ⭐ Key Features
| Requirement | Status | * **Authoritative Go match handler** (`tictactoe`)
|----------------------------------------------|--------------------------| * Device-ID authentication + JWT session
| Install Nakama + PostgreSQL | ✅ Completed | * Matchmaking queue support
| Custom Go server plugins | ✅ Completed | * Deterministic game validation
| Server-authoritative Tic-Tac-Toe | ✅ Completed | * Match lifecycle handling
| Real-time WebSocket communication | ✅ Completed | * Disconnect handling & forfeit detection
| Device-based authentication | ✅ Completed | * Leaderboards creation + scoring
| JWT-based session management | ✅ Completed | * Production-grade CI/CD with Drone
| Match creation & joining | ✅ Completed | * Automated ARM Docker builds
| **Matchmaking queue support** | ✅ Completed | * Full Traefik routing (HTTP + WebSocket)
| **Game state validation & turn enforcement** | ✅ Completed | * Compatible with x86/ARM/GCP
| **Leaderboard system** | ✅ Completed |
| **UI Game Client** | 🟡 Partially Implemented |
| Google Cloud deployment | 🟡 Not Started |
**Backend is fully authoritative and complete**
🟡 **UI functional but missing polish, UX, and failure handling**
--- ---
## **3. Core Technical Architecture** ## 🧩 Architecture
* **Backend Framework:** Nakama 3.x ### High-Level System Diagram
* **Business Logic:** Custom Go runtime module
* **Frontend:** React + Vite + Nakama JS ```mermaid
* **Database:** PostgreSQL 14 flowchart LR
* **Transport:** WebSockets (real-time) UI[(React + Vite)] --> Traefik
* **Authentication:** Device-ID based auth → JWT session returned Traefik --> Nakama[Nakama Server]
* **State Management:** Fully server-authoritative Nakama --> Plugin[Go Plugin]
* **Build & Deployment:** Docker-based Nakama --> Postgres[(PostgreSQL)]
Drone[Drone CI/CD] --> Registry[Private Docker Registry]
Registry --> Nakama
```
--- ---
## **4. Authentication** ## 🛠 Tech Stack
### Backend **Backend**
* Device authentication, auto-account creation * Nakama 3.21.0 ARM
* JWT returned and used for RT connections * Go 1.21.6 (plugin ABI compatible)
* PostgreSQL 16
* Docker / multi-stage builds
* Drone CI/CD
* Traefik reverse proxy
### UI **Cloud/Infra**
* Generates a device UUID and authenticates via `client.authenticateDevice()` * GCP-ready
* Stores and manages session state in React context * ARM homelab deployments
* Private registry support
--- ---
## **5. Game Server Logic (Go)** ## 📦 Repository Structure
Significant enhancements made: ```
tic-tac-toe/
### **✔ Initial State Broadcast** │── plugins/
│ ├── main.go
* When the second player joins, the server immediately sends the full authoritative state. │ ├── match.go
│ └── matchmaking.go
### **✔ Complete Turn + Move Validation**
│── Dockerfile
Rejects: │── go.mod
│── go.sum
* out-of-bounds moves │── README.md
* occupied cells ```
* wrong player's turn
* invalid payloads
### **✔ Forfeit Handling**
* When a user disconnects or leaves, match ends in `forfeit`
* Final state broadcast to remaining player
### **✔ Authoritative State Updates**
* Only broadcasts when state actually changes
* Robust structured logging
Result:
**Absolute server authority, zero trust in client.**
--- ---
## **6. Real-Time Networking** ## 🔌 Registered Server Components
Communication validated end-to-end: ### 📌 Match Handler
* `match_create` Name: **`tictactoe`**
* `match_join`
* `matchmaker_add` / `matchmaker_matched`
* `match_data_send` for moves (OpCode 1)
* Server broadcasts state (OpCode 2)
Python simulators and UI both confirm: Handles:
* move ordering * Turn validation
* correct enforcement of turn rules * State updates
* correct state sync * Win/loss/draw
* stable WebSocket behavior * Disconnect forfeit
* Broadcasting authoritative state
### 📌 RPCs
| RPC Name | Purpose |
| ----------------------- | ---------------------------------------- |
| **`leave_matchmaking`** | Allows clients to exit matchmaking queue |
### 📌 Matchmaker Hook
| Hook | Purpose |
| ----------------------- | --------------------------------------------------------- |
| **`MatchmakerMatched`** | Validates matchmaker tickets and instantiates a new match |
--- ---
## **7. Matchmaking System (Go + UI)** ## 🎮 Gameplay Protocol
### **Backend (Go)** ### OpCodes
* Implements `MatchmakerMatched` hook | OpCode | Direction | Meaning |
* Ensures both players: | ------ | --------------- | ----------------------------- |
| **1** | Client → Server | Submit move `{x, y}` |
* have valid `mode` | **2** | Server → Client | Full authoritative game state |
* match modes
* exactly two players
* Creates authoritative matches server-side
* RPC `leave_matchmaking` added
### **UI**
* Integrates matchmaking: mode selection → queue → ticket → matched → auto-join
* Uses Nakama JS `socket.addMatchmaker()`
**Status:** Fully functional end-to-end
--- ---
## **8. Leaderboard System (Go + UI)** ## 🧠 Authoritative Flow Diagram
### **Backend (Go)** ```mermaid
sequenceDiagram
participant C1 as Client 1
participant C2 as Client 2
participant S as Nakama + Go Plugin
* Leaderboard auto-created on startup C1->>S: Matchmaker Join
* On win: C2->>S: Matchmaker Join
S->>S: MatchmakerMatched()
S-->>C1: Matched
S-->>C2: Matched
* winner identified C1->>S: OpCode 1 (Move)
* username resolved S->>S: Validate Move
* score incremented (+1 win) S-->>C1: OpCode 2 (Updated State)
* metadata logged S-->>C2: OpCode 2 (Updated State)
```
### **UI**
* Implements leaderboard view using `client.listLeaderboardRecords()`
* Read-only UI display works
### **Remaining**
* UI sorting, layout, styling
* No leaderboard write actions needed from UI
--- ---
## **9. UI Implementation Status (React + Vite)** ## ⚙️ Build & Development
### **What Is Implemented** ### Build Go Plugin
- ✔ Authentication flow (device auth) ```
- ✔ WebSocket session handling CGO_ENABLED=1 go build \
- ✔ Matchmaking (classic/blitz modes) --trimpath \
- ✔ Automatic match join --buildmode=plugin \
- ✔ Move sending (OpCode 1) -o build/main.so \
- ✔ State updates (OpCode 2) ./plugins
- ✔ Board rendering and interactive cells ```
- ✔ End-of-game messaging
- ✔ Leaderboard display
### **Partially Implemented** ### Run Nakama Locally
- 🟡 Match mode UI selection wired but not visually emphasized ```
- 🟡 Context handles all RT states but missing error handling nakama migrate up --database.address "$DB_ADDR"
nakama \
### **Not Implemented / Missing** --database.address "$DB_ADDR" \
--socket.server_key="$SERVER_KEY"
- 🔴 Reconnect flow (UI does not recover session after WS drop) ```
- 🔴 No error UI for: matchmaking failure, move rejection, disconnects
- 🔴 No UI for leaving match or returning to lobby
- 🔴 No rematch button / flow
- 🔴 No transitions, animations, or mobile layout
- 🔴 No global app shell (Routing, Home Screen, etc.)
**Summary:** UI is *functional* and capable of playing full authoritative games, but lacks UX polish and failure
handling.
--- ---
## **10. Testing & Validation** ## 🐳 Docker Build (Multi-Stage)
### Backend ```dockerfile
FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
* Extensive scenario tests: draws, wins, illegal moves, disconnects RUN go mod download
* Matchmaking simulation across N clients COPY . .
RUN CGO_ENABLED=1 go build --buildmode=plugin -o build/main.so ./plugins
### UI FROM heroiclabs/nakama:3.21.0-arm
COPY --from=plugin_builder /workspace/build/main.so /nakama/data/modules/main.so
* Verified: ENTRYPOINT ...
```
* matchmaking
* game correctness
* leaderboard retrieval
* state sync
* Missing:
* stress testing
* reconnection scenarios
* mobile layout testing
--- ---
## **11. Google Cloud Deployment** ## 🤖 CI/CD — Drone Pipeline
Planned architecture remains: Drone performs:
| Component | GCP Service | 1. Fetch latest Git tag
|---------------|-------------------------------| 2. Check if Docker image already exists
| Nakama server | Compute Engine VM (Docker) | 3. Build Nakama + plugin
| PostgreSQL | Cloud SQL (shared tier) | 4. Push to private registry
| Game UI | Cloud Run or Firebase Hosting | 5. Stop old container
| Networking | Static IP + HTTPS | 6. Deploy new Nakama server automatically
| Auth secrets | Secret Manager (optional) |
Estimated setup time: **68 hours** Full pipeline included in repository (`.drone.yml`).
--- ---
## **12. Risks & Considerations** ## 🌐 Traefik Routing
| Risk | Mitigation | ### HTTPS
|--------------------------------|--------------------------------|
| UI lacks error/reconnect logic | Add retry + reconnection flows |
| No rematch or lobby UX | Add match lifecycle UI |
| No mobile layout | Add responsive CSS |
| Cloud deployment pending | Prioritize after UI polish |
| Matchmaking UX is minimal | Add feedback, loading states |
None of these affect core backend stability. ```
nakama.aetoskia.com
/ → HTTP API
/ws → WebSocket (real-time)
```
Includes:
* CORS rules
* WebSocket upgrade headers
* Certificate resolver
* Secure default middlewares
--- ---
## **13. Next Steps** ## 🔧 Environment Variables
### **UI Tasks** | Variable | Description |
| --------------- | ---------------------------- |
1. Add reconnect + error-handling UI | `DB_ADDR` | PostgreSQL connection string |
2. Create lobby → gameplay → results, flow | `SERVER_KEY` | Nakama server key |
3. Add rematch capability | `REGISTRY_HOST` | Private registry |
4. Add responsive + polished UI
5. Add loading indicators & animations
Estimated remaining effort: **6 to 8 hours**
--- ---
## **Executive Summary** ## 📊 Leaderboards
### Issues faced * Created during server start
Several unexpected integration challenges during UI setup contributed to the additional day of work. These included: * Score: `+1` on win
- Aligning the UIs matchmaking flow with the new authoritative Go-based matchmaking logic. * Metadata logged (mode, player IDs)
- Handling Nakama JS WebSocket behaviors, especially around session timing, matchmaker ticket handling, and match join events.
- Ensuring OpCode handling and server-produced state updates matched the servers authoritative model.
- Resolving environment-related issues (Vite dev server, Node version mismatches, and WebSocket URL configuration).
- Debugging cross-origin and connection-reset issues during early WebSocket initialization.
These challenges required deeper synchronization between the backend and frontend layers, resulting in an additional **+1 day** of engineering time. ---
### Project Progress ## 🧪 Testing
The system now features a fully authoritative backend with matchmaking, gameplay logic, and leaderboards implemented
completely in Go. The UI is functional and integrates correctly with all backend systems, supporting end-to-end
matchmaking and gameplay.
Key remaining work involves UI polish, recovery/error handling, and deployment setup. No major architectural risks * Win/loss/draw simulation
remain. * Invalid move rejection
* Disconnect → forfeit
* Load testing matchmaking
**The project is now fully playable, technically solid, and ready for final UI enhancements and cloud deployment.** ---
## 📈 Production Deployment
Supported on:
* ARM homelabs (Raspberry Pi)
* Google Cloud (Compute Engine + Cloud SQL)
* AWS EC2
* Kubernetes (optional)
---
## 🤝 Contributing
1. Fork repo
2. Create feature branch
3. Write tests
4. Submit PR
Coding style: Go fmt + idiomatic Go; follow Nakama plugin constraints.
---