Skip to content

Ultimate Imposter - A fast, mobile‑friendly social deduction game built in Rust with Dioxus and WASM. One player is the imposter — spot them before they blend in;

Notifications You must be signed in to change notification settings

jaliph/ultimate-imposter

Repository files navigation

Ultimate Imposter: Social Deduction Game

A fun social deduction game built with Dioxus 0.7 where players try to find the imposter among them!

🎮 Game Overview

Ultimate Imposter is a mobile-friendly web game for 3+ players. One player is randomly assigned as the imposter with a different word, while all other players receive the same word. Through discussion and voting, players try to identify the imposter before they blend in successfully.

🚀 Quick Start

Prerequisites

  • Rust installed on your system
  • Dioxus CLI

Installation

  1. Install Dioxus CLI:
curl -sSL http://dioxus.dev/install.sh | sh
  1. Run the game locally:
dx serve --platform web

The game will be available at http://localhost:8080

📱 Running on Mobile (Same Network)

To access the game from your mobile phone on the same WiFi network:

  1. The app is already configured to bind to all network interfaces (0.0.0.0:8080)
  2. Find your computer's local IP address:
    • macOS/Linux: ifconfig | grep "inet " | grep -v 127.0.0.1
    • Windows: ipconfig
  3. On your mobile device, open the browser and navigate to:
    http://YOUR_COMPUTER_IP:8080
    
    Example: http://192.168.1.100:8080

This allows all players to use the same device or different devices on the network!

📱 How to Play

  1. Setup: Enter the number of players (3+) and their names
  2. Category Selection: Players choose a category for the round (e.g., "Food & Drinks 🍕", "Animals 🦁", etc.)
  3. Category Reveal: Everyone sees the chosen category
  4. Card View: Each player reveals their card privately (pass the device around)
  5. Discussion: Players discuss to find who has the odd word
  6. Voting: Group decides who to eliminate
  7. Scoring:
    • If imposter found: Civilians get 10 points each
    • If imposter not found: Imposter gets 20 points

📝 Word Categories

The game includes 20 categories with over 400+ challenging word pairs:

  • 🍕 Food & Drinks (30 pairs)
  • 🦁 Animals (30 pairs)
  • 🌳 Nature (44 pairs)
  • ⛅ Seasons & Weather (15 pairs)
  • 🎵 Music & Arts (16 pairs)
  • ⚽ Sports & Activities (18 pairs)
  • 💻 Technology (22 pairs)
  • 🚗 Transportation (19 pairs)
  • 🎬 Entertainment (14 pairs)
  • 🎥 Movies & Cinema (22 pairs) ✨ NEW
  • 🏛️ Places (30 pairs)
  • 👨‍⚕️ Professions (20 pairs)
  • 👕 Clothing & Accessories (28 pairs)
  • ✏️ Stationery & Office (16 pairs)
  • 💎 Precious Items (14 pairs)
  • 💡 Light Sources (8 pairs)
  • ⚔️ Fantasy & Adventure (28 pairs)
  • 👻 Mystical (15 pairs)
  • 📖 Stories & Tales (14 pairs)
  • 🚀 Science Fiction (18 pairs)

✨ Word pairs are carefully crafted to be challenging! Similar words make it harder to identify the imposter, creating more engaging discussions.

Want to customize? Edit the words.yaml file in the project root to add your own categories and word pairs!

📂 Project Structure

ultimate-imposter/
├─ words.yaml          # Word categories and pairs (easily editable!)
├─ assets/
│  ├─ favicon.ico
│  └─ styling/
│     └─ game.css      # Game styling
├─ src/
│  ├─ main.rs          # App entry point and routing
│  └─ views/
│     ├─ mod.rs        # Views module
│     └─ game/         # Game module (refactored)
│        ├─ mod.rs     # Main game orchestration
│        ├─ types.rs   # Data structures
│        ├─ utils.rs   # Helper functions (word loading)
│        ├─ persistence.rs  # Session management
│        └─ components/     # UI components
│           ├─ mod.rs
│           ├─ setup.rs
│           ├─ category_selection.rs
│           ├─ category_reveal.rs
│           ├─ card_view.rs
│           ├─ voting.rs
│           ├─ elimination.rs
│           ├─ round_end.rs
│           └─ score.rs
└─ Cargo.toml

🎨 Features

  • Beautiful gradient UI with smooth animations
  • 🎯 Player-selected categories - Choose your theme before each round
  • 📝 Category-based word system - Words organized by themes
  • 🔧 Easily extensible - Edit words.yaml to add custom categories
  • Mobile-optimized responsive design
  • Privacy-focused card reveal system
  • Score tracking across multiple rounds
  • Supports 3-10 players
  • 💾 Auto-save game state - Resume your game after browser refresh or restart
  • 🔐 Session-based persistence - Each game gets a unique Session ID
  • 📱 Cross-device support - Share Session ID to continue on another device (with server mode)

🖼️ Screenshots

Here are a few screenshots of ultimate-imposter in action (categorized by gameplay):

Setup Phase

Setup Phase

Assignment Phase

Discussion Phase Discussion Phase Voting Phase

Discussion & Voting Phase

Voting Phase

Eviction & Scoring Phase

Scoring Phase Scoring Phase

�🛠️ Technology

  • Framework: Dioxus 0.7
  • Language: Rust
  • Styling: Custom CSS
  • Persistence: Browser localStorage + Optional server disk storage
  • Session Management: UUID-based session IDs

💾 Game Persistence & Session Management

Ultimate Imposter features automatic game state persistence that allows you to resume your game seamlessly after browser refresh, closing tabs, or even restarting your device.

✨ How It Works

Automatic Save:

  • Game state is saved to your browser's localStorage automatically on every action
  • No manual save button needed - everything happens in the background
  • Works completely offline, no server required

What Gets Saved:

  • ✅ Player names and scores
  • ✅ Current game screen (Setup, CardView, Voting, etc.)
  • ✅ Round number and card assignments
  • ✅ Elimination status and imposter identity
  • ✅ All game progress

Session ID:

  • Each game session gets a unique UUID stored in localStorage
  • Session ID persists across browser restarts
  • Session ID is used internally to save/load game state
  • Not displayed on screen to keep UI clean

🔄 Resume Game

Single Device:

  1. Simply refresh the page or close/reopen the browser
  2. The game automatically loads your last state
  3. Continue playing from exactly where you left off

Multiple Devices (Same Network):

  1. Game state is saved to each device's localStorage independently
  2. To share a game session, you would need to export/import the session manually
  3. For true cross-device sync, enable server mode (see below)

🗑️ Start Fresh Game

Option 1: Click the "New Game" button in the game (recommended)

Option 2: Clear browser data manually:

// Open browser console (F12) and run:
localStorage.clear();
// Then refresh the page

🔧 Technical Details

Browser Storage:

  • Uses browser localStorage API
  • Storage key: ultimate_imposter_game_{session-id}
  • Session key: ultimate_imposter_session_id
  • Data format: JSON serialized game state

Data Structure:

{
  session_id: String,
  game_screen: GameScreen,
  players: Vec<Player>,
  round_number: i32,
  cards: Vec<GameCard>,
  imposter_index: usize,
  // ... and more
}

Privacy:

  • All data stays in your browser
  • No data sent to external servers
  • No tracking or analytics
  • Completely offline-capable

🖥️ Server Disk Persistence (Optional)

For advanced users, server-side persistence can be enabled:

Enable Server Mode:

# Build with server feature
cargo build --features server

# Run fullstack mode
dx serve --features server

Server Storage:

  • Game saves stored in game_saves/ directory
  • One JSON file per session: {session-id}.json
  • Allows true cross-device synchronization
  • Survives server restarts

Server Functions Available:

  • save_game_to_disk() - Save game state to server
  • load_game_from_disk() - Load game state from server
  • list_saved_games() - List all saved sessions
  • delete_saved_game() - Remove a saved session

Note: Server persistence requires uncommenting server functions in src/views/game.rs (lines marked with comments)

🔒 Security & Privacy

  • localStorage Only: By default, all data stays in your browser
  • No External Calls: No analytics, tracking, or external API calls
  • Random Session IDs: Cryptographically secure UUID generation
  • Local-First: Works 100% offline without any server

💡 Best Practices

  1. Regular Play: Just play normally - saving is automatic
  2. New Session: Always use "New Game" button for clean state
  3. Browser Compatibility: Ensure localStorage is enabled (default in all modern browsers)
  4. Privacy: All data stays in your browser, nothing is sent to external servers

🐳 Docker Deployment

Deploy ultimate-imposter using Docker for easy hosting and portability.

Quick Start

Build the Docker image:

docker build -t ultimate-imposter .

Run the container:

docker run -d -p 8080:80 --name ultimate-imposter-app ultimate-imposter

The app will be available at http://localhost:8080

Docker Commands

Build the image:

docker build -t ultimate-imposter:latest .

Run in background:

docker run -d -p 8080:80 --name ultimate-imposter-app ultimate-imposter:latest

Run with custom port:

docker run -d -p 3000:80 --name ultimate-imposter-app ultimate-imposter:latest

View logs:

docker logs ultimate-imposter-app

Stop the container:

docker stop ultimate-imposter-app

Remove the container:

docker rm ultimate-imposter-app

Rebuild after changes:

docker stop ultimate-imposter-app
docker rm ultimate-imposter-app
docker build -t ultimate-imposter:latest .
docker run -d -p 8080:80 --name ultimate-imposter-app ultimate-imposter:latest

Docker Compose (Optional)

Create a docker-compose.yml file:

version: '3.8'

services:
  ultimate-imposter:
    build: .
    container_name: ultimate-imposter-app
    ports:
      - "8080:80"
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 5s

Run with Docker Compose:

docker-compose up -d

Stop with Docker Compose:

docker-compose down

Production Deployment

For production deployment on cloud platforms:

Deploy to DigitalOcean, AWS, or any VPS:

  1. SSH into your server
  2. Install Docker: curl -fsSL https://get.docker.com -o get-docker.sh && sh get.docker.sh
  3. Clone your repository: git clone https://github.com/yourusername/ultimate-imposter.git
  4. Build and run: cd ultimate-imposter && docker build -t ultimate-imposter . && docker run -d -p 80:80 ultimate-imposter

Deploy to Fly.io:

# Install Fly CLI
curl -L https://fly.io/install.sh | sh

# Login to Fly
fly auth login

# Launch app (first time)
fly launch

# Deploy updates
fly deploy

Deploy to Railway:

  1. Connect your GitHub repository to Railway
  2. Railway will auto-detect the Dockerfile
  3. Deploy automatically on git push

Dockerfile Architecture

The Dockerfile uses a multi-stage build for optimal size and performance:

  1. Builder Stage: Uses Rust image to compile the Dioxus app
  2. Production Stage: Uses nginx:alpine to serve static files (only ~50MB!)

Benefits:

  • ✅ Small final image (~50MB vs ~2GB)
  • ✅ Fast startup and low resource usage
  • ✅ Production-ready nginx configuration
  • ✅ Gzip compression enabled
  • ✅ Health checks included
  • ✅ Optimized for web serving

Customizing nginx

To customize the nginx configuration, create an nginx.conf file and modify the Dockerfile:

# Add this line before the EXPOSE command
COPY nginx.conf /etc/nginx/conf.d/default.conf

📄 License

MIT License

About

Ultimate Imposter - A fast, mobile‑friendly social deduction game built in Rust with Dioxus and WASM. One player is the imposter — spot them before they blend in;

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •