A fun social deduction game built with Dioxus 0.7 where players try to find the imposter among them!
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.
- Rust installed on your system
- Dioxus CLI
- Install Dioxus CLI:
curl -sSL http://dioxus.dev/install.sh | sh- Run the game locally:
dx serve --platform webThe game will be available at http://localhost:8080
To access the game from your mobile phone on the same WiFi network:
- The app is already configured to bind to all network interfaces (
0.0.0.0:8080) - Find your computer's local IP address:
- macOS/Linux:
ifconfig | grep "inet " | grep -v 127.0.0.1 - Windows:
ipconfig
- macOS/Linux:
- On your mobile device, open the browser and navigate to:
Example:
http://YOUR_COMPUTER_IP:8080http://192.168.1.100:8080
This allows all players to use the same device or different devices on the network!
- Setup: Enter the number of players (3+) and their names
- Category Selection: Players choose a category for the round (e.g., "Food & Drinks 🍕", "Animals 🦁", etc.)
- Category Reveal: Everyone sees the chosen category
- Card View: Each player reveals their card privately (pass the device around)
- Discussion: Players discuss to find who has the odd word
- Voting: Group decides who to eliminate
- Scoring:
- If imposter found: Civilians get 10 points each
- If imposter not found: Imposter gets 20 points
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!
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
- 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.yamlto 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)
Here are a few screenshots of ultimate-imposter in action (categorized by gameplay):
- Framework: Dioxus 0.7
- Language: Rust
- Styling: Custom CSS
- Persistence: Browser localStorage + Optional server disk storage
- Session Management: UUID-based session IDs
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.
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
Single Device:
- Simply refresh the page or close/reopen the browser
- The game automatically loads your last state
- Continue playing from exactly where you left off
Multiple Devices (Same Network):
- Game state is saved to each device's localStorage independently
- To share a game session, you would need to export/import the session manually
- For true cross-device sync, enable server mode (see below)
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 pageBrowser 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
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 serverServer 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 serverload_game_from_disk()- Load game state from serverlist_saved_games()- List all saved sessionsdelete_saved_game()- Remove a saved session
Note: Server persistence requires uncommenting server functions in src/views/game.rs (lines marked with comments)
- 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
- Regular Play: Just play normally - saving is automatic
- New Session: Always use "New Game" button for clean state
- Browser Compatibility: Ensure localStorage is enabled (default in all modern browsers)
- Privacy: All data stays in your browser, nothing is sent to external servers
Deploy ultimate-imposter using Docker for easy hosting and portability.
Build the Docker image:
docker build -t ultimate-imposter .Run the container:
docker run -d -p 8080:80 --name ultimate-imposter-app ultimate-imposterThe app will be available at http://localhost:8080
Build the image:
docker build -t ultimate-imposter:latest .Run in background:
docker run -d -p 8080:80 --name ultimate-imposter-app ultimate-imposter:latestRun with custom port:
docker run -d -p 3000:80 --name ultimate-imposter-app ultimate-imposter:latestView logs:
docker logs ultimate-imposter-appStop the container:
docker stop ultimate-imposter-appRemove the container:
docker rm ultimate-imposter-appRebuild 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:latestCreate 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: 5sRun with Docker Compose:
docker-compose up -dStop with Docker Compose:
docker-compose downFor production deployment on cloud platforms:
Deploy to DigitalOcean, AWS, or any VPS:
- SSH into your server
- Install Docker:
curl -fsSL https://get.docker.com -o get-docker.sh && sh get.docker.sh - Clone your repository:
git clone https://github.com/yourusername/ultimate-imposter.git - 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 deployDeploy to Railway:
- Connect your GitHub repository to Railway
- Railway will auto-detect the Dockerfile
- Deploy automatically on git push
The Dockerfile uses a multi-stage build for optimal size and performance:
- Builder Stage: Uses Rust image to compile the Dioxus app
- 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
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.confMIT License






