Skip to content

Repository files navigation

This project has been created as part of the 42 curriculum by jmondon, hgamiz-g, chanin and mjeannin.


ft_transcendence

Description

ft_transcendence is a full-stack multiplayer RPG centered on progression at 42: your academic progress drives character customization and power. The social web layer is intentionally minimal, focused on identity, friends, and lightweight communication to support the game experience. Players authenticate with their 42 Intra accounts and use their project progress to build and personalize characters across two game modes.

Key Features

  • 42 OAuth2 + Local Authentication — Log in via 42 Intra OAuth2; once validated, a local email/password can also be set. Protected with JWT (HttpOnly cookies), CSRF tokens, rate limiting, and account lockout.
  • User Profiles & Accounts — Lightweight profile management linked to 42 Intra data (login, avatar, cursus level, coalition, approved projects).
  • Friends System — Core social layer for connecting players.
  • Real-time Chat — WebSocket-powered messaging for basic coordination.
  • Multiplayer RPG Core — Turn-based RPG with five character classes (Fighter, Ranger, Rogue, Mage, Barbarian), stat system (STR/DEX/CON/INT), skill system (Melee/Ranged/Magic), a talent tree, spell casting with cooldowns and buffs, and a weapon system.
  • Three Game Modes — Local PvE (player vs AI), plus multiplayer in two variants: free-for-all and team-based.
  • Progress-Driven Customization — 42 project scores become customization points, making school progress the engine of character growth.
  • Real-time Monitoring Dashboard — Live event stream (SSE) visualizing system activity across all microservices.
  • Microservices Architecture — Fully containerized, each domain in its own service with an isolated database.
  • Nginx Reverse Proxy — SSL/TLS termination on port 8443, routing HTTP and WebSocket traffic.

Team Information

Login Full Name Role(s) Responsibilities
hgamiz-g Héctor Gámiz PO / Developer Game desing, backend micro-services and game-logic developer, task distribution
mjeannin Matteo Jeannin Tech Lead / Developer Architecture design, tech stack, infrastructure, front-end development
jmondon Juan Mondón PM / Developer Project management, OAuth2 flow, database schema
chanin Chris Hanin Developer 3D renderer, front-end developer

Project Management

  • Task Distribution: Core project tasks, micro-services and frontend/backend
  • Meetings: weekly meetings for project priorities, daily stand-ups. Depending on team members availability they were held physically and sometimes via Discord.
  • Project Management Tool: Jira for tasks and feature priorities.
  • Communication: Discord server with dedicated channels for different aspects of the project (Frontend, backend, api, git, game-dev).
  • Version Control Strategy: Feature branches, small commits, pull requests and code reviews.

Technical Stack

Frontend

Technology Version Purpose
React 18.3.1 UI framework
TypeScript 5.6 Type safety
Vite 5.4 Build system & hot-reload
React Router v7 Client-side routing
Tailwind CSS 3.4 Utility-first styling
Three.js + @react-three/fiber 0.182 3D game rendering
@react-three/drei 9.117 Three.js helpers
Framer Motion 11 UI animations
Socket.io-client 4.7 WebSocket client
Recharts 2.15 Monitoring charts

Backend

Technology Version Purpose
Node.js 20 LTS Runtime
NestJS 10 Framework for Auth, Users, Player, Chat, Friends, Health, Game services
TypeORM 0.3 ORM for PostgreSQL
Socket.io 4 WebSocket server (Chat, Game)
Express 4 Lightweight services (Monitor)
Nginx Alpine Reverse proxy + SSL termination

API Gateway — Custom NestJS HTTP+WebSocket proxy that routes all client traffic to the appropriate microservice.

Database

Service Database Rationale
Accounts (users) PostgreSQL 16 Relational data, JSONB for flexible 42 profile data, UNIQUE constraints
Player PostgreSQL 16 Relational structure for character stats, JSONB for talents/inventory/spells
Friends PostgreSQL 16 Relational join tables for friendship graph
Chat PostgreSQL 16 Message history and channel management

Why PostgreSQL? Chosen for ACID compliance, excellent JSONB support (used for flexible 42 API data and game item arrays), mature TypeORM integration, and the fact that all services follow the Database-per-Service pattern — each service owns and exclusively accesses its own database instance, ensuring domain isolation and independent scalability.

Infrastructure

  • Docker & Docker Compose — Every service is containerized. Three isolated Docker networks (frontend-net, backend-net, service-net) enforce strict communication boundaries.
  • Nginx — SSL/TLS termination, HTTP and WebSocket reverse proxy on port 8443.
  • Makefile — Top-level task runner for building, starting, and cleaning the stack.

Justification for Major Technical Choices

  • Microservices over monolith — Design choice. Enables teams to develop, deploy, and scale each domain (auth, game, chat, friends) independently.
  • NestJS — Provides a structured, opinionated framework with built-in support for WebSockets, guards, pipes, interceptors, and DI, reducing boilerplate in each service.
  • Database-per-Service — Prevents tight coupling between domains; a schema migration in Player does not affect the Chat service.
  • JSONB columnsprofile_data (accounts) and talents/inventory/spells (player) use JSONB so game data can evolve without SQL migrations, while still being queryable via PostgreSQL's GIN indexes.
  • JWT in HttpOnly cookies + CSRF — Prevents XSS token theft while CSRF tokens guard against cross-site request forgery.

Database Schema

accounts_dbuser_accounts table

Column Type Constraints Description
id uuid PK Internal universal identifier
ft_id int UNIQUE, NOT NULL 42 Intra user ID
login varchar(50) UNIQUE, NOT NULL 42 login (e.g. jdoe)
email varchar(255) UNIQUE, NOT NULL Institutional email
image_url varchar(500) NULLABLE Avatar URL from 42 API
profile_data jsonb NOT NULL, default {} Flexible 42 API data (name, level, coalition, projects, scores…)
password varchar(255) NULLABLE, hidden bcrypt hash — set after OAuth2 first login; excluded from normal queries
registration_complete boolean NOT NULL, default false True once local password is set
failed_login_attempts int NOT NULL, default 0, hidden Consecutive failed local-auth attempts (brute-force protection)
locked_until timestamptz NULLABLE, hidden Account lockout expiry timestamp
customization_points int NOT NULL, default 0 Total accumulated customization points
status_message varchar(280) NULLABLE User-set status message
custom_avatar text NULLABLE Base64 or URL of user-uploaded avatar
privacy_settings jsonb NOT NULL Visibility toggles: showLevel, showProjects, showStats, showFriends, showStatus
last_seen_at timestamptz NULLABLE, INDEX Last activity timestamp
created_at timestamptz NOT NULL Auto-generated
updated_at timestamptz NOT NULL Auto-updated
last_login_at timestamptz NULLABLE Last successful login timestamp

player_dbcharacters table

Column Type Constraints Description
id uuid PK Character UUID
user_id uuid NOT NULL, INDEX Logical ref to user_accounts.id (no FK — separate DB)
name varchar(50) NOT NULL, INDEX Character name
class_name enum NOT NULL, INDEX fighter | mage | rogue | ranger | barbarian
str int NOT NULL, default 5 Strength (1–10)
dex int NOT NULL, default 5 Dexterity (1–10)
int int NOT NULL, default 5 Intelligence (1–10)
con int NOT NULL, default 5 Constitution (1–10)
melee int NOT NULL, default 0 Melee skill (0–5)
ranged int NOT NULL, default 0 Ranged skill (0–5)
magic int NOT NULL, default 0 Magic skill (0–5)
max_hp int NOT NULL, default 25 15 + con × 2
current_hp int NOT NULL, default 25 Current HP
movement int NOT NULL, default 10 6 + DEX_mod
magic_points int NOT NULL, default 10 Current MP pool
talent_points int NOT NULL, default 10 Available talent points
max_customization_points int NOT NULL, default 20 Max customization points ever earned
current_customization_points int NOT NULL, default 20 Remaining customization points to spend
talents jsonb NOT NULL, default [] Array of unlocked talent IDs
inventory jsonb NOT NULL, default [] Array of owned item IDs
spells jsonb NOT NULL, default [] Array of known spell IDs
equipped_talents jsonb NOT NULL, default [] Active equipped talent IDs
equipped_spells jsonb NOT NULL, default [] Active equipped spell IDs
equipped_weapons jsonb NOT NULL, default [] Active equipped weapon IDs
equipped_items jsonb NOT NULL, default [] Active equipped item IDs
equipped_potion varchar NULLABLE Equipped potion ID
created_at timestamptz NOT NULL Auto-generated
updated_at timestamptz NOT NULL Auto-updated

Note: The relationship between user_accounts and characters is logical, not a foreign key — the two tables live in separate databases. Referential integrity is enforced at the application layer. A user may have multiple characters of any class.

friends_dbfriendships table

Column Type Constraints Description
id uuid PK Friendship record UUID
requester_id uuid NOT NULL, INDEX User who sent the friend request
addressee_id uuid NOT NULL, INDEX User who received the request
status enum NOT NULL, default pending pending | accepted | rejected | blocked
created_at timestamptz NOT NULL Auto-generated
updated_at timestamptz NOT NULL Auto-updated

Constraint: UQ_friendship_pair — unique on (requester_id, addressee_id) prevents duplicate rows. Composite index on (addressee_id, status) for efficient inbox queries.

chat_dbconversations + messages tables

conversations

Column Type Constraints Description
id uuid PK Conversation UUID
user1_id uuid NOT NULL, INDEX Participant with lower UUID (enforced for uniqueness)
user2_id uuid NOT NULL, INDEX Participant with higher UUID
created_at timestamptz NOT NULL Auto-generated
updated_at timestamptz NOT NULL Auto-updated

Constraint: UQ_conversation_pair — unique on (user1_id, user2_id). The pair is always stored with user1_id < user2_id to guarantee a single row per pair regardless of who initiates.

messages

Column Type Constraints Description
id uuid PK Message UUID
conversation_id uuid NOT NULL, INDEX, FK → conversations.id CASCADE Parent conversation
sender_id uuid NOT NULL Sending user's ID
content text NOT NULL Message body
is_read boolean NOT NULL, default false Read receipt flag
created_at timestamptz NOT NULL Auto-generated (send timestamp)

Features List

# Feature Owner(s) Description
1 OAuth2 Login (42 Intra) jmondon Full OAuth2 code-exchange flow with 42 API, sets HttpOnly JWT cookie
2 Local email/password auth jmondon Post-OAuth2 password registration, bcrypt hashing, rate limiting, account lockout
3 CSRF protection jmondon HMAC-SHA256 CSRF tokens validated on all state-changing requests
4 JWT refresh flow jmondon Sliding-window refresh tokens with cookie rotation
5 User profiles jmondon Avatar, display name, 42 profile data (level, coalition, projects)
6 Friends system jmondon Send/accept/reject friend requests, block users
7 Real-time chat jmondon / chanin WebSocket messaging, private channels, friend-gated rooms
8 Character creation mjeannin / hgamiz-g Choose from 5 RPG classes; stats auto-set from class template
9 Character stats & derived values hgamiz-g AC = 10 + DEX_mod; MaxHP = 15 + CON×2; attack bonuses by skill
10 Turn-based combat engine hgamiz-g 1d20 attack rolls, damage (1d6 + stat mod), initiative (DEX_mod), crits/fumbles
11 Spell casting / Special abilities system hgamiz-g MP cost validation, target resolution, cooldowns, area effects
12 Buff/debuff system hgamiz-g Duration tracking, stat recomputation on expiry, periodic effects
13 Talent tree hgamiz-g Class-specific talents unlocked via 42 project score points
14 Weapon system hgamiz-g Weapon types mapped to class skills, equip/unequip logic
15 42-progress → game progression hgamiz-g Project scores converted to customization points (2 + floor((mark−80)/10))
16 API Gateway mjeannin HTTP + WebSocket proxy, service registry, CORS, security headers
17 Real-time monitor dashboard mjeannin SSE event stream, event creation, statistics charts, type filtering
18 Service health checks mjeannin Health endpoint across all services, exposed through gateway
19 Nginx SSL reverse proxy mjeannin TLS termination on :8443, HTTP and WS routing, self-signed cert for dev
20 Inter-service authentication hgamiz-g Shared HMAC secret (x-service-secret header) on all internal calls
21 Docker containerisation mjeannin Per-service Dockerfiles, multi-stage builds, hot-reload in dev
22 3D frontend rendering chanin Three.js scene via @react-three/fiber for the game viewport
23 Animated UI mjeannin Firefly particle background, Framer Motion transitions
24 AI Opponents chanin Local game mode (player vs IA)

Modules

The ft_transcendence subject scores modules as: Major = 2 pts, Minor = 1 pt. Total required: 14 pts minimum.

# Module Type Points Owner(s) Implementation Notes
1 Use a framework for both the frontend and backend (React + NestJS) Major 2 mjeannin / hgamiz-g All stateful microservices (Auth, Users, Player, Chat, Friends, Health) built with NestJS 10. Frontend design using React.
2 Implement real-time features using WebSockets or similar technology (Websockets) Major 2 jmondon / chanin Chat across the platform and in-game
3 Allow users to interact with other users Major 2 jmondon / chanin Chat system, profile system and friends system
4 Use an ORM for the database (PostgreSQL) Minor 1 jmondon / hgamiz-g Database-per-Service pattern; 4 independent PostgreSQL 16 instances managed via TypeORM
5 Standard user management, authentication Major 2 jmondon Users can update their profile information, upload an avatar, add other users as friends and see their online status. Users have a profile page displaying their information
6 Implementing a remote authentication (42 OAuth2) Minor 1 jmondon 42 Intra API OAuth2 code-exchange, token validation, auto user creation
7 AI Opponent for games Major 2 chanin Users can play local games against an AI
8 Implement a complete web-based game where users can play against each other Major 2 whole team The core of the project. Turn based rpg with focus on team strategy
9 Remote players — Enable two players on separate computers to play the same game in real-time Major 2 whole team Disconnection/Reconnection handlers, smooth user experience from different computers
10 Multiplayer game (more than two players) Major 2 whole team Multiple concurrent independent game rooms, each supporting up to 6 players each by design for game mechanics flow, but can be extended if needed. Finished rooms are cleaned up automatically after 30 s.
11 Implement advanced 3D graphics (Three.js) Major 2 chanin 3D environment, characters and animations. Camera movement system.
12 Game customization options Minor 1 hgamiz-g / mjeannin Character customization based on 42 progress, character customization shop and in-game special abilities
13 Spectator mode Minor 1 chanin Users can join any game as spectators, watch it in real-time and use the game chat
14 Backend as microservices Major 2 team Separated responsabilities among different services, each can run on its own. REST APIs for communication.
15 Music and sound effects Major 2 chanin Music and sound effects during game, volume controls on the interface
16 Custom-made design system Minor 1 mjeannin Reusable components, including a proper color palette, typography, and icons

Total: 27 pts


Individual Contributions

hgamiz-g — Product Owner

  • Designed and implemented the full game mechanics layer in JavaScript/TypeScript: character classes, TurnManager, d20 combat system, spell casting with cooldowns and area effects, buff/debuff system, and talent tree
  • Built and maintained five backend microservices (lobby, game, character, coalition, customization) with their full REST API surface
  • Integrated backend services with PostgreSQL (via TypeORM) and with the frontend (game state polling, action dispatch, combat log)
  • Designed the multi-game, multi-player infrastructure to support concurrent game rooms with independent state
  • Defined the 42-progress → customization-points conversion system, linking academic scores to in-game character growth
  • Challenges: The game logic went through several major refactoring cycles as new features (team modes, spectators, spell system, talent tree) were added mid-development. The main difficulty was keeping the combat engine consistent and reliable while being consumed simultaneously by the game frontend, the lobby service, the character service, and the database layer — each with different data contracts and timing requirements.

jmondon — Project Manager

  • Architected and deployed a multi-database infrastructure using PostgreSQL and TypeORM, ensuring strict data isolation between microservices (Accounts, Player, Chat, and Auth).
  • Developed a Hybrid Authentication System: Integrated a full OAuth2 code-exchange flow with the 42 API, complemented by a mandatory Bcrypt-hashed email/password registration to meet security standards.
  • Engineered Advanced Security Layers: Implemented HttpOnly JWT cookie rotation, sliding-window refresh tokens, and HMAC-SHA256 CSRF protection for all state-changing requests.
  • Built Real-time Communication Infrastructure: Developed a platform-wide WebSocket system supporting private messaging and friend-gated rooms.
  • User & Social Ecosystem: Designed and implemented the full-stack logic for User Profiles (syncing 42 API data like levels and coalitions) and a comprehensive Friends System (requests, blocking, and real-time status).
  • Challenges: The primary difficulty was orchestrating the "Post-OAuth" registration flow. Balancing the requirement for local password security (hashing/salting) with the exclusivity of 42 Intra students required a complex middleware logic to validate identity before allowing credential creation. Additionally, maintaining real-time consistency across multiple isolated database instances required a rigorous synchronization strategy between the Gateway and the backend microservices.

mjeannin — Tech Lead / Developer

  • Led the frontend implementation and overall visual direction of the site, defining the design system (color palette, typography, icons) and reusable UI components.
  • Built the character-creation frontend flow, including class selection and the customization UI tied to 42 progress.
  • Implemented the API Gateway (HTTP + WebSocket proxy), service registry, and security headers; wired health checks for all services.
  • Delivered the infrastructure glue: Dockerfiles and Compose wiring, Nginx SSL reverse proxy on :8443, and animated UI polish (Framer Motion, background effects).
  • Responsible for maintaining codebase consistency across the project, defining and sustaining the technical stack, and managing the organization of the GitHub repository.
  • Participated on game design.
  • Challenges: The main difficulty was keeping the frontend experience cohesive while integrating multiple backend services through the gateway, and ensuring the customization/creation flow remained responsive and consistent with backend constraints (auth state, profile sync, and character data) without breaking the site's overall visual coherence.

chanin — Developer

  • Built the entire 3D game frontend using React Three Fiber and Three.js: game scene with configurable camera, shadow-mapped lighting, OrbitControls, and WebGL crash recovery
  • Implemented 3D character rendering with KayKit Adventurers models, 10 animation states (idle, walk, attack, death, etc.) with transitions, and weapon attachment to hand bones
  • Created the medieval arena environment (castle walls, towers, torches with animated flame, banners, props, trees) and the game board with multi-layer cell highlighting (movement, attack, team)
  • Developed the full AI opponent system for local mode
  • Designed and implemented the sound system mapping 18 game events to audio files, random variant selection, master volume control, and SFX mute toggle
  • Built the spectator mode with dedicated join/leave lifecycle
  • Implemented front-end-side game engine for local play: d20 combat, Manhattan distance movement, buff tick-down, talent passives, AP system, and spell casting
  • Created all in-game UI components: HUD (action bar, turn banner), initiative roll animation, class selection, lobby screen, game overlays, combat log, sidebars, player stats panel, and action panel
  • Challenges: The main difficulty was keeping the 3D rendering layer synchronized with both the local game engine and the remote server state. Animation timing had to be carefully sequenced (walk → pause → attack → hit reaction) so that AI turns were visually readable, while multiplayer state polling required a versioning system to prevent stale server responses from overwriting the results of the player's own actions. Additionally, skeleton retargeting across different model rigs (Medium vs Large for Barbarian) and reliable hand-bone detection for weapon attachment (10+ bone-naming conventions across asset packs) demanded extensive trial-and-error.

Project in GitHub for commit history

Repository

Insights

Instructions

Prerequisites

Requirement Minimum Version Notes
Docker 24.x docker --version
Docker Compose v2 (plugin) docker compose version
GNU Make 4.x make --version
42 OAuth2 app credentials Register at profile.intra.42.fr/oauth/applications
OpenSSL any For generating secrets

Node.js is not required on the host — all builds happen inside Docker. Install it locally only if you want IntelliSense (make install-local).


1. Clone the repository

git clone https://github.com/<org>/ft_transcendence.git
cd ft_transcendence

2. Create the environment file

cp env_example .env

Open .env and fill in every value:

IMPORTANT: for all the features to work, use your IP and NOT localhost

# 42 OAuth2 — obtain from https://profile.intra.42.fr/oauth/applications
FT_CLIENT_ID=<your_client_id>
FT_CLIENT_SECRET=<your_client_secret>

FT_REDIRECT_URI=https://<YOUR_IP_OR_HOSTNAME>:8443/api/auth/callback

# JWT — generate with:  openssl rand -base64 128
JWT_SECRET=<long_random_secret>
JWT_EXPIRATION=7d

# App URL
FRONTEND_URL=https://<YOUR_IP_OR_HOSTNAME>:8443

# Inter-service secret — generate with:  openssl rand -hex 32
INTERNAL_SERVICE_SECRET=<32_hex_chars>

# CSRF secret — generate with:  openssl rand -hex 32
CSRF_SECRET=<32_hex_chars>

# Cookie settings (keep defaults for local dev)
COOKIE_SECURE=true
COOKIE_SAMESITE=lax

Self-signed certificate: Nginx ships a self-signed cert for local development. Your browser will show a security warning — click "Advanced → Proceed" (or add the cert to your trust store).

42 OAuth2 redirect URI: The application registered in 42 Intra must have https://<YOUR_IP_OR_HOSTNAME>:8443/api/auth/callback listed as an allowed redirect URI.


3. Build and start all services

make all

This runs docker compose up --build -d for every service and then installs local Node.js dependencies for editor IntelliSense.

The stack takes ~60–90 seconds on first build (downloading base images + installing npm packages inside containers). Subsequent starts are faster.


4. Verify the stack is running

docker compose ps          # all containers should show "Up"
curl -k https://localhost:8443/api/health   # should return {"status":"ok"}

Open https://localhost:8443 in your browser.


5. Useful commands

Command Description
make all Build images and start all containers (background)
make restart Stop and restart without rebuilding
make clean Stop all containers (docker compose down)
make fclean Full teardown: containers, images, volumes, node_modules
make install-local Install node_modules locally (for VS Code IntelliSense)
docker compose logs -f <service> Tail logs for a specific service
docker compose exec <service> sh Open a shell in a running container

Known Limitations

  • Game state via REST polling — The game service is REST-only for game state; the frontend polls every 500 ms. Real-time chat, however, is fully WebSocket-based (Socket.io) across the whole platform.
  • Game room player cap — Each game room supports up to 6 players (MAX_PLAYERS = 6 in game.instance.ts), but can be modified.
  • Self-signed TLS — Browser trust warning on first visit; acceptable for local dev/evaluation.

Resources

The visual assets for the game created by Kay Lousberg used in this project are distributed under the Creative Commons CC0 1.0 Universal license. These assets are part of the public domain and may be used, modified, and redistributed without restriction or attribution. They have been included in this project in accordance with the terms of the CC0 license.

Documentation

Articles & Tutorials

AI Usage

AI assistance was used throughout the project for the following purposes:

Task Tool used Parts of the project
Test scripts Copilot Game-logic
Drafting technical documentation Copilot Use guides for API endpoints to share across the team
Code checks Copilot Backend
Generating game balance numbers ChatGPT Game design

AI was not used as a black box: all generated code was reviewed, tested, and integrated by team members who understand it fully.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages