You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A full-stack multiplayer Pong web application built as part of the 42 curriculum. Players can compete in real-time matches or tournaments, chat with other users, and have their tournament results permanently recorded on the Ethereum blockchain. The app supports GitHub OAuth authentication, user profiles with friends/blocked lists, and is available in three languages.
Technologies
Layer
Technology
Justification
Backend
Fastify + TypeScript
Lightweight, high-performance Node.js framework with first-class WebSocket support for real-time game state streaming
Frontend
Vite + TypeScript
Fast HMR development, native ES modules, and minimal config for single-page application
Database
SQLite (better-sqlite3)
Embedded database with zero setup, perfect for single-server deployment; synchronous API simplifies game state management
Real-time multiplayer over WebSocket with server-authoritative game state
Live Chat
Major
2
Direct messaging, game invites, online status
Database
Minor
1
SQLite with better-sqlite3 for persistent storage
Browser Compatibility
Minor
1
Tested and compatible with latest Firefox and Chrome
Multiple Languages
Minor
1
i18n support for English, German, and French
User and Game Stats Dashboards
Minor
1
Detailed dashboard for user statistics and match history
Points Summary
Category
Points
Major Modules (6 × 2)
12
Minor Modules (4 × 1)
4
Total
16
Requirement
14
Bonus
+2
Controls
Left paddle: W (up) / S (down)
Right paddle: ↑ (up) / ↓ (down)
Run with Docker + Makefile
Prerequisites
Docker Desktop (or Docker Engine) with Compose v2 (uses docker compose, not docker-compose).
Quick start
# From repo root
make up # build (if needed) and start backend + frontend in the background
make logs # follow logs for both services# Open the app# Frontend: http://localhost:5173# Backend: http://localhost:4000 (health: /api/health)
Hot reload
Source folders are bind-mounted into containers, so Vite and the Fastify dev server reload on file changes.
On macOS, file watching is enabled via CHOKIDAR_USEPOLLING=1 in Compose.
What each Make target does (under the hood)
make up
Runs: docker compose up -d
Builds images if missing and starts both services detached.
make down
Runs: docker compose down
Stops and removes containers and the default network (keeps volumes).
make stop
Runs: docker compose stop
Gracefully stops containers without removing them.
make build
Runs: docker compose build
Rebuilds images using cache.
make rebuild
Runs: docker compose build --no-cache
Full rebuild without cache (use after changing Dockerfiles or lockfiles).
make restart
Runs: docker compose restart
Restarts running containers.
make logs
Runs: docker compose logs -f
Tails logs for all services.
make ps
Runs: docker compose ps
Shows container status.
make clean
Runs: docker compose down -v
Stops and removes containers, network, and volumes (resets container node_modules).
./frontend:/app and ./backend:/app for live reload.
/app/node_modules as an anonymous volume so container installs don’t pollute the host.
Commands
Backend runs npm run dev (watch mode).
Frontend runs Vite dev server bound to 0.0.0.0:5173.
If dependencies get out of sync, use make clean && make up or make rebuild.
Running the backend and frontend directly (no Docker)
# Frontend (Vite)
npm install
npm run dev
# Backend (Fastify + websockets)cd backend
npm install
npm run dev
Open http://localhost:5173 in the browser once both servers are running. The frontend connects to the backend WebSocket at ws://localhost:4000/api/rooms/default/ws by default.
Architecture Overview
Fastify drives the authoritative Pong simulation and exposes REST + WebSocket APIs.
Vite-powered frontend renders the game canvas and relays paddle inputs to the backend via WebSocket commands.
Game state (paddles, ball, score, winner) is streamed from backend → frontend ~60 FPS.
Backend Endpoints
All backend endpoints return JSON format. All POST request expect the data to be sent in the body.
Method
Path
Description
Returns
GET
/api/health
Service heartbeat
GET
/api/config
(env override supported)
Returns { winningScore }
POST
/api/control
Optional HTTP paddle control { roomId, paddle, direction }