Jeu multijoueur mobile-first, construit avec Next.js (App Router), API HTTP + SSE, et état de partie en mémoire serveur.
- Création/rejoindre un salon par code (
4lettres) - Reconnexion par session locale (
playerId+sessionToken) - Flux temps réel via Server-Sent Events
- Manches avec mot/définition correcte générés par IA
- Normalisation des définitions joueurs en batch (orthographe/ponctuation) avec garde-fous anti-paraphrase
- Next.js
16+ React19 - État des salons en RAM (process Node unique)
- SSE sur
GET /api/rooms/[code]/events - Vercel AI Gateway (modèle par défaut :
openai/gpt-5.2) - Vitest pour la logique de jeu serveur
- Installer les dépendances.
npm install- Configurer l'environnement.
cp .env.example .env.localVariables :
VERCEL_AI_GATEWAY_API_KEY(requis)LLM_MODEL(optionnel, défaut :openai/gpt-5.2)
- Lancer en local.
npm run devApplication disponible sur http://localhost:3000.
npm run devdémarre le serveur de devnpm run buildbuild de productionnpm run startdémarre le build de productionnpm run lintlance ESLintnpm testlance Vitest en mode CInpm run test:watchlance Vitest en mode watch
- 5 manches par partie
- 2 joueurs minimum, 8 maximum
- Phase écriture :
60s - Phase vote :
30s +2points pour un vote sur la vraie définition+1point par vote reçu sur sa définition- Auto-vote interdit
- Si un joueur ne soumet rien : fausse définition auto-générée
- Si un joueur ne vote pas : aucun point
- Le passage à la manche suivante est déclenché par l'hôte (
next-round)
Toutes les réponses API utilisent le format :
- succès :
{ "ok": true, "data": ... } - erreur :
{ "ok": false, "error": "..." }
Endpoints :
POST /api/rooms- body :
{ "playerName": string }
- body :
POST /api/rooms/[code]/join- body :
{ "playerName": string, "playerId"?: string, "sessionToken"?: string }
- body :
GET /api/rooms/[code]/snapshot?playerId=...GET /api/rooms/[code]/events?playerId=...POST /api/rooms/[code]/start- body :
{ "playerId": string, "sessionToken": string }
- body :
POST /api/rooms/[code]/submit- body :
{ "playerId": string, "sessionToken": string, "definition": string }
- body :
POST /api/rooms/[code]/vote- body :
{ "playerId": string, "sessionToken": string, "optionId": string }
- body :
POST /api/rooms/[code]/next-round- body :
{ "playerId": string, "sessionToken": string }
- body :
POST /api/rooms/[code]/play-again- body :
{ "playerId": string, "sessionToken": string }
- body :
POST /api/rooms/[code]/leave- body :
{ "playerId": string, "sessionToken": string }
- body :
- État en mémoire uniquement : redémarrage serveur = salons perdus
- Aucune persistance en base de données
- Conçu pour une seule instance serveur (pas de scaling horizontal sans store partagé)