Tanveer

Undercover

A word-based social deduction game of clues, discussion and votes. Play online in a private room or pass one phone around. The server assigns secret roles, tracks votes and resolves the round, while room chat gives players a place to discuss their suspicions.

PROJECT
Social deduction game
ROLE
Full-stack development
CLIENT
React, TypeScript, Vite
SERVER
Express, Socket.IO, Prisma, PostgreSQL

Overview

Undercover is a word-based party game. Most players receive one word, an undercover player receives a related word, and Mr. White receives no word. Players give clues, discuss suspicions and vote on who should leave the round.

I built both online rooms and a pass-and-play mode for groups sharing one device. The backend coordinates role assignment, votes and round outcomes, while the React client handles the game screens and room conversation.

Undercover overview
Undercover product overview.

Why I built it

I wanted friends to be able to start a word game without cards or a dedicated installation. Some groups would be together with one phone; others would join remotely. Those situations called for two ways to play the same basic game.

The word pairs are part of the product design. They need enough similarity for an undercover player to participate and enough difference for a careful clue to reveal something. The library groups pairs by difficulty.

The problem

In online play, one person's vote changes the state for everyone. The server has to know who has voted, whether the round is complete, and which players remain before it decides what happens next.

A player's own word and the shared room state have different visibility requirements. The interface separates those views; per-player network payload filtering still needs tightening to enforce the same boundary beyond the screen.

The solution

Players create or join a private room, and the host selects the mix of roles. The server assigns roles and words, records the game state and sends events as players join, leave or vote.

Voting updates the round until the elimination logic runs. The server evaluates the remaining roles to decide whether play continues or the game ends. Room chat supports discussion, and the project includes voice-chat integration for remote play.

Undercover player and role configuration
Undercover player and role configuration.

One round of the game

  1. Room and roles

    Players join and the server assigns words and roles.

  2. Clues and discussion

    Players describe their words and discuss suspicions.

  3. Voting

    The game handler records votes and resolves elimination.

  4. Round outcome

    Remaining roles determine whether another round begins or the game ends.

State and events

Express handles HTTP routes and authentication, while Socket.IO carries room and game events. Prisma records users, game data and messages in PostgreSQL so those objects have a persistent representation.

The game handler tracks whether each player has voted and resets round counters when play continues. A separate local-play flow supports a group using one device. That keeps the basic game available without requiring a networked room for every session.

A player's private word screen before voting
A player's private word screen before voting.

Outcome and next direction

The project implements the playable loop and the room experience around it. It is a useful setting for testing event-driven state because stale or contradictory updates are immediately visible to players.

A next direction would be custom word packs, letting hosts build rounds around a group's interests or preferred language. Packs could be selected during room setup and reused across sessions.

VISUAL ARTIFACTS

Undercover gallery

A closer look at the product and its workflows.

Other projects

VIEW ALL WORK ↗