A real‑time multiplayer guessing game where one player (Game Master) creates a session, builds a question bank, and starts rounds. Other players join, guess answers (3 attempts, 60 seconds), earn points, and the winner becomes the next Game Master.
🚀 Live Demo
Frontend: https://guessing-game-three-tau.vercel.app
Backend: https://guessing-game-backend-45sc.onrender.com
- 🎲 Guessing Game – Real-Time Multiplayer Quiz
- Live multiplayer – WebSocket‑powered real‑time communication.
- Game Master role – create sessions, manage question bank, start rounds.
- Question Bank – prepare multiple Q&A pairs before the game starts.
- Round logic – each round uses the next question (cycles automatically).
- 3 attempts per player – case‑insensitive answer matching.
- 60‑second timer – round ends automatically if no correct guess.
- Scoring – +10 points for the first correct answer.
- Winner becomes next Game Master – unless timeout (rotates to next player).
- Live scoreboard – all players see each other’s scores.
- Session lifecycle – auto‑deleted when last player leaves.
- Responsive UI – works on desktop and mobile.
| Layer | Technology |
|---|---|
| Backend | Node.js 20+ / Express / Socket.IO |
| Frontend | React 18 / Vite / Tailwind CSS |
| Real‑time | Socket.IO (WebSockets + HTTP polling fallback) |
| State | In‑memory Map (sessions, players, question banks) |
| Deployment | Render (backend) + Vercel (frontend) |
┌─────────────┐ WebSocket/HTTP ┌─────────────┐ │ Browser │ ◄──────────────────────► │ Render │ │ (React) │ Socket.IO │ (Node.js) │ └─────────────┘ └─────────────┘ ▲ │ │ │ └───────────── HTTP polling fallback ───────┘
- Frontend (Vercel): static React build, connects to backend via
VITE_SOCKET_URL. - Backend (Render): Express + Socket.IO server, manages game state in memory.
- No database – all state ephemeral (resets on restart). Suitable for casual play.
- Node.js 20+ (download)
- npm 9+ (comes with Node)
- Git
# Clone the repository
git clone https://github.com/devGeorgeOwi/guessing-game.git
cd guessing-game
# Install backend dependencies
cd server
npm install
# Install frontend dependencies
cd ../client
npm installcd server
npm run dev # uses node --watch for auto-restart
# Backend runs on http://localhost:3001cd client
npm run dev # Vite dev server
# Frontend runs on `http://localhost:5173`
# Open http://localhost:5173 in multiple browser windows to simulate multiple players.
| Variable | Description | Default |
|---|---|---|
PORT |
HTTP port | 3001 |
FRONTEND_URL |
Your live frontend URL (no trailing slash) | http://localhost:5173 |
| Variable | Description | Default |
|---|---|---|
VITE_SOCKET_URL |
Backend WebSocket URL | http://localhost:3001 |
For production (Vercel), set VITE_SOCKET_URL in the Vercel dashboard.
| Event | Payload | Description |
|---|---|---|
session:create |
{ playerName } |
Create a new session (becomes Game Master) |
session:join |
{ sessionId, playerName } |
Join an existing session |
session:leave |
{ sessionId } |
Leave current session |
game:setQuestions |
{ sessionId, questions } |
Save question bank (Game Master only) |
game:start |
{ sessionId } |
Start the game (Game Master only) |
game:guess |
{ sessionId, guess } |
Submit a guess for current question |
| Event | Payload | Description |
|---|---|---|
players:update |
[{ id, name, score, isGameMaster }] |
Refresh player list & scores |
game:started |
{ question, timeLimit, startedAt } |
Round started, display question & timer |
game:expired |
{ answer, message } |
Timeout – no winner |
game:winner |
{ winnerId, winnerName, answer, pointsAwarded } |
Someone guessed correctly |
game:ended |
{ nextGameMaster, winner } |
Round finished, return to lobby |
game:newGameMaster |
{ gameMasterId } |
Role transferred to another player |
guess:result |
{ playerId, playerName, attemptsLeft } |
Wrong guess (broadcast) |
-
Create Session – first player becomes Game Master (GM), receives a 6‑character session code.
-
Others Join – using the code (must be before game starts).
-
GM Builds Question Bank – adds multiple Q&A pairs in the lobby.
-
GM Starts Game – requires ≥2 players and ≥1 question.
-
Round Begins – all players see the first question, a 60‑second timer, and have 3 attempts.
-
Correct Guess – winner gets +10 points; round ends immediately; answer revealed.
-
Timeout – if timer reaches 0, round ends with no winner; answer revealed.
-
Round Ends – players return to lobby; winner (or next player) becomes new GM.
-
Next Round – new GM clicks "Start Game" – the next question from the bank is used.
-
Leaving – any player can leave; session auto‑deletes when empty.
- Push code to GitHub.
- On Render, create a New Web Service.
- Connect your GitHub repo, set:
- Root Directory:
server - Build Command:
npm install - Start Command:
node index.js
- Root Directory:
- Add environment variable:
FRONTEND_URL= your Vercel frontend URL (e.g.,https://guessing-game-three-tau.vercel.app)
- Click Create Web Service.
Your backend will be available at https://your-backend.onrender.com.
- On Vercel, import the same GitHub repo.
- Configure:
- Root Directory:
client - Framework Preset:
Vite - Build Command:
npm run build - Output Directory:
dist
- Root Directory:
- Add environment variable:
VITE_SOCKET_URL= your Render backend URL (e.g.,https://guessing-game-backend.onrender.com)
- Click Deploy.
Your frontend will be available at https://your-project.vercel.app.
| Issue | Solution |
|---|---|
| CORS errors | Ensure FRONTEND_URL on Render matches exactly (no trailing slash). Also check Socket.IO cors.origin function. |
| WebSocket connection fails | Force HTTP polling fallback in frontend: transports: ['polling', 'websocket']. Render free tier may have WebSocket timeouts. |
| "Session not found" | Verify the session code is correct (6 uppercase chars). Session may have been deleted if all players left. |
| Game won't start | Need at least 2 players AND at least 1 question in the bank. |
| Timer not working | Check backend logs – timer uses setTimeout; ensure no errors in game:start handler. |
| Players can't join during game | Intended behaviour – join only allowed in lobby. |
| Render logs show "Cannot find module" | Ensure "type": "module" in server/package.json and use import syntax. |
- Persistent storage – use PostgreSQL (Render) to save scores and question banks across restarts.
- User authentication – login with Google/GitHub to keep profiles.
- Custom time limit – let GM choose 30/60/90 seconds.
- Random question order – instead of sequential cycling.
- Chat – allow players to chat during lobby and between rounds.
- Spectator mode – non‑players can watch without guessing.
Built as a production‑grade real‑time multiplayer game demonstration.
Follows modern JavaScript (ES Modules), React Hooks, Socket.IO best practices, and clean separation of concerns.
Enjoy the game! 🎲
Questions or issues? Open an issue or reach out to @devGeorgeOwi.