Skip to content

nullEFFORT/the-expo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

20 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

The Expo

Restaurant gamification platform powered by real POS data.

Turn your sales floor into a competitive arena. The Expo connects your Toast POS system to a suite of games played on a back-of-house TV. Your staff doesn't just play a game β€” they play their shift. Earn coins, redeem prizes, compete across the entire restaurant.


Platform Overview

The Expo is a modular game platform. The backend β€” Toast integration, player profiles, coin economy, prize shop β€” stays the same. The games are swappable skins that visualize the same sales data in different ways.

Toast POS β†’ Webhook β†’ Game Engine β†’ Active Game β†’ TV + Phones
                            ↓
                      Coin Economy β†’ Prize Shop

Every closed check feeds the current game. Every race/match awards coins. Coins persist across shifts. Players redeem coins for real-world prizes β€” gift cards, premium section picks, day-off priority, whatever the manager stocks the shop with.

Game Modes

🏎️ Shake N Bake (Racing) β€” Live

Split-screen 3D racing in a shared world. Each player gets their own camera viewpoint of the same scene β€” like Mario Kart multiplayer. Position is rank-based (leader out front, others behind by constant gaps). The road scrolls underneath to create forward motion. Score drives speed. Power-ups from dessert sales, big checks, and combo orders. Spinouts from voids and comps.

Race types:

  • Dollar Dash β€” total revenue
  • The Coke 500 β€” soft drink units
  • Dessert Derby β€” most desserts sold
  • Check Race β€” most checks closed
  • Item Rush β€” total items sold

🐲 Boss Raid (D&D Dungeon Crawl) β€” Alpha

The entire 4-hour shift plays out as a party adventure. No player control β€” the game plays itself. Your sales drive the party forward through a themed dungeon with rooms, minibosses, and a final boss.

How it works:

  • Auto-launches at 5:00 PM when at least 3 players are in the lobby
  • One party β€” everyone on shift fights together
  • Sales = damage β€” every closed check attacks the current enemy
  • Desserts heal β€” upsells power big moments
  • Voids backfire β€” spells misfire, take self-damage
  • Comps heal the enemy β€” you just made the boss stronger
  • Pace gate β€” on a slow night, you literally cannot reach the final boss

State machine: tavern β†’ overland β†’ dungeon_entry β†’ room_1 β†’ miniboss_1 β†’ room_2 β†’ miniboss_2 β†’ treasure β†’ approach β†’ boss_door β†’ boss_fight β†’ victory/defeat

10 themed quests (random selection per shift or manager pick):

  • The Tyrant's Feast (Dragon demands filet mignons)
  • The Saucier's Curse (Chef Mephisto and the mother sauce horror)
  • Grease Trap Abyss (Sentient fryer grievances)
  • The Expeditor's Revenge (Ghost haunts the pass)
  • Temple of the Lost Receipt (Mirror rooms, voids = wrong path)
  • Happy Hour Hellscape (2-for-1 demons)
  • The Walk-In Lich (Hot sales burn, cold dishes heal it)
  • Siege of Catering Castle (Wave defense)
  • The Birthday Wight (300-year birthday party)
  • Mount Corkage (Volcano crawl, wine = extinguisher)

Party classes β€” determined by your BOH partner's role:

BOH Role Class Ability
Line Cook Warrior +20% melee damage from entrees
Sous Chef Mage Wine bottles do 3Γ— AoE damage
Dishwasher Cleric Void-immune, heals on desserts
Prep Cook Rogue Appetizers give double-strike
Expo Paladin Combo bonuses 2Γ—
(none) Bard Jack of all trades

Presentation:

  • Real sprite pack characters (soldier/orc from Tiny RPG pack) with idle/walk/attack/hurt/death animations
  • Infernus hellscape tile-based backgrounds per area
  • Speech bubbles over characters for party banter and enemy taunts
  • Scene cards for area transitions and boss intros
  • Live HP bars, buffs (🍰 Dessert Rush), debuffs (πŸ’€ Cursed)
  • Historical pace calculator gates the final boss room

Status: Alpha. The engine, narration, and combat math are working. Client rendering is under active debugging β€” see BossRaidErrorBoundary.jsx for the on-screen crash inspector.

πŸ₯Š Coming Soon

  • Fighter β€” 1v1 bracket tournaments, sales = damage, HP bars
  • Battle Royale β€” lowest seller gets eliminated every 30 minutes, last one standing wins

More game skins can be added without touching the backend. The game engine is decoupled from the renderer.


Features

Player Accounts

  • One profile per employee β€” tied to their Toast employee GUID
  • Character builder β€” single anatomical sprite with modular addons (shirt hue, flair emoji, accent color)
  • Alias β€” pick a racing/fighting name that shows up in every game
  • 4-digit PIN β€” log back in between shifts to check balance and redeem prizes
  • Persistent coins β€” earn from every game, spend whenever you want
  • React Context (PlayerProvider) holds session state across routes

Voting Lobby

  • Pre-shift lobby at /tv shows QR code + joined players + live vote counts
  • Players scan in, pick their avatar, then vote for tonight's game mode
  • Winning game auto-launches when the shift starts
  • Votes update in real time via SSE

Coin Economy

  • Earn coins from game results and achievements
    • πŸ₯‡ 1st place: 100 coins
    • πŸ₯ˆ 2nd place: 50 coins
    • πŸ₯‰ 3rd place: 25 coins
    • Participation: 10 coins
    • Big check ($200+): +10 coins
    • First dessert of the race: +5 coins
  • Spend coins in the prize shop
  • Admin controls prize inventory β€” custom names, costs, quantities

Prize Shop

  • Browse available prizes from your phone
  • Redeem with one tap
  • Track redemption status (pending / fulfilled)
  • Manager fulfills redemptions from the admin panel

TV Display

  • Racing mode β€” Three.js split-screen 3D viewports (hero layout or auto grid)
  • Boss Raid mode β€” 2D sprite scene with tile-based backgrounds, animated characters, speech bubbles, scene cards
  • Lobby mode β€” QR code + joined players + live vote counts
  • Automatic mode switching based on active game state
  • Error boundary wraps the Boss Raid renderer to surface crashes on-screen + in server logs
  • Announcer bar with play-by-play
  • Winner podium screen on game end

Mobile Companion (PWA)

  • Onboarding: Pick your employee β†’ create character β†’ set PIN β†’ done
  • During race: Clean pit-board view (position, score, leaderboard)
  • During Boss Raid: Persistent adventurer HUD (class, HP, party status, buffs, current target)
  • Between games: Shop, history, profile, vote for next game
  • Tab nav: 🏁 Game | πŸ›’ Shop
  • Scan QR to join
  • Trash talk engine (30+ pre-made messages)
  • Add-to-homescreen (PWA)

Admin Panel (/hnic)

  • PIN-protected
  • Start/stop games (races or Boss Raid)
  • Boss Raid controls: pick quest, seed historical pace from Toast, add heroes, force-end run
  • Layout mode selector (hero grid vs auto grid)
  • Toast POS configuration (client ID, secret, restaurant GUID)
  • Webhook URL display for Toast setup
  • Prize management β€” CRUD for gift card inventory
  • Redemption fulfillment β€” mark redemptions as delivered
  • Employee sync β€” pull roster from Toast API
  • Live connection stats (TV screens, phones connected)

Game Engine

  • Processes Toast order webhooks in real time
  • Routes orders to the active game(s) β€” Shake N Bake and Boss Raid run in parallel when both are configured
  • Power-up detection: desserts, big checks ($100+), combos (5+ items), wine bottles
  • Spinout detection: voids, comps
  • Game-scoped join tokens β€” new QR per game, dead when game ends
  • Historical pace baseline pulled from Toast /orders/v2/ordersBulk (last 4 shifts same DOW)
  • BOH partner abilities β€” pair FOH server with kitchen staff for buffs

BOH Partner System

FOH server picks a kitchen partner at race start. Each BOH role maps to a D&D class in Boss Raid and gives a buff in Shake N Bake.

Role Shake N Bake Ability Boss Raid Class
🍳 Line Cook Dessert boost lasts 2Γ— longer Warrior
πŸ₯˜ Sous Chef Wine/cocktail sales give extra boost Mage
🧼 Dishwasher Immune to one void spinout per race Cleric
πŸ₯¬ Prep Cook Appetizer sales give speed boost Rogue
πŸ“’ Expo Combo bonus at 3 items instead of 5 Paladin
(none) β€” Bard

Both FOH and BOH share in the coin winnings β€” kitchen staff gets rewarded too.


Tech Stack

Layer Technology
Backend Node.js, Express, SQLite (better-sqlite3)
Frontend React 18, Vite
3D Engine Three.js with FBXLoader (Shake N Bake)
2D Engine CSS sprite-sheet animation (Boss Raid)
Real-time Server-Sent Events (SSE)
Mobile Progressive Web App (PWA)
Deploy Docker on macvlan (br0) at 192.168.1.40:3005
POS Toast API (OAuth2, webhooks)

Project Structure

the-expo/
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ index.js              # Express entry + debug/tv-error endpoint
β”‚   β”œβ”€β”€ db.js                 # SQLite schema + queries
β”‚   β”œβ”€β”€ sse.js                # SSE client manager
β”‚   β”œβ”€β”€ game-engine.js        # Shake N Bake scoring
β”‚   β”œβ”€β”€ toast-auth.js         # Toast OAuth token manager
β”‚   β”œβ”€β”€ games/
β”‚   β”‚   └── boss-raid/
β”‚   β”‚       β”œβ”€β”€ engine.js     # State machine, tick loop, pace, buffs
β”‚   β”‚       β”œβ”€β”€ encounters.js # Mob pool definitions
β”‚   β”‚       β”œβ”€β”€ quests.js     # 10 themed dungeons
β”‚   β”‚       β”œβ”€β”€ narrator.js   # Flavor text generator + banter + taunts
β”‚   β”‚       β”œβ”€β”€ classes.js    # BOH β†’ class mapping + abilities
β”‚   β”‚       β”œβ”€β”€ pace.js       # Historical pace calculator
β”‚   β”‚       └── routes.js     # Boss Raid API endpoints
β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   └── auth.js           # PIN + session guards
β”‚   └── routes/
β”‚       β”œβ”€β”€ webhook.js        # Toast order receiver (routes to both games)
β”‚       β”œβ”€β”€ races.js          # Race CRUD + QR + SSE
β”‚       β”œβ”€β”€ players.js        # Registration, profiles
β”‚       β”œβ”€β”€ coins.js          # Balance, transactions, redemption
β”‚       β”œβ”€β”€ trashtalk.js      # Pre-made message system
β”‚       β”œβ”€β”€ games.js          # Game voting + lobby
β”‚       └── admin.js          # Admin API (PIN-protected)
β”œβ”€β”€ client/
β”‚   └── src/
β”‚       β”œβ”€β”€ tv/
β”‚       β”‚   β”œβ”€β”€ TVApp.jsx                  # TV shell β€” auto-switches modes
β”‚       β”‚   β”œβ”€β”€ TVLobby.jsx                # Pre-shift voting screen
β”‚       β”‚   β”œβ”€β”€ BossRaidTV.jsx             # Boss Raid main view
β”‚       β”‚   β”œβ”€β”€ BossRaidScene.jsx          # Sprite scene + hero/enemy animation
β”‚       β”‚   β”œβ”€β”€ BossRaidBackground.jsx     # Infernus tile backgrounds per area
β”‚       β”‚   β”œβ”€β”€ BossRaidEffects.jsx        # Popups, bubbles, scene cards, banners
β”‚       β”‚   └── BossRaidErrorBoundary.jsx  # On-screen crash inspector
β”‚       β”œβ”€β”€ games/
β”‚       β”‚   └── shake-n-bake/              # Racing game mode
β”‚       β”‚       β”œβ”€β”€ SplitScreenGame.jsx    # Three.js renderer
β”‚       β”‚       β”œβ”€β”€ LayoutManager.js       # Viewport grid calculator
β”‚       β”‚       β”œβ”€β”€ PlayerHUD.jsx          # Per-player overlay
β”‚       β”‚       └── AnnouncerBar.jsx       # Play-by-play ticker
β”‚       β”œβ”€β”€ mobile/                        # Phone companion
β”‚       β”‚   β”œβ”€β”€ Register.jsx               # Multi-step onboarding
β”‚       β”‚   β”œβ”€β”€ CharacterBuilder.jsx       # Avatar + sprite helpers
β”‚       β”‚   β”œβ”€β”€ Dashboard.jsx              # Race view (simplified)
β”‚       β”‚   β”œβ”€β”€ BossRaidHUD.jsx            # Adventurer HUD during raid
β”‚       β”‚   β”œβ”€β”€ CoinShop.jsx               # Prize shop
β”‚       β”‚   β”œβ”€β”€ TrashTalk.jsx              # Message sender
β”‚       β”‚   └── MobileApp.jsx              # Tab navigation
β”‚       β”œβ”€β”€ admin/AdminApp.jsx             # Admin panel
β”‚       β”œβ”€β”€ context/PlayerContext.jsx      # Persistent player session
β”‚       └── hooks/useSSE.js                # SSE subscription hook
β”œβ”€β”€ public/models/
β”‚   β”œβ”€β”€ characters/
β”‚   β”‚   β”œβ”€β”€ char_free/                     # Base player avatar (12-layer sprite)
β”‚   β”‚   └── tiny_rpg_clean/
β”‚   β”‚       β”œβ”€β”€ soldier/                   # Hero sprites (idle/walk/attackΓ—3/hurt/death)
β”‚   β”‚       └── orc/                       # Enemy sprites
β”‚   └── tilesets/infernus/                 # 639 hellscape tiles for Boss Raid
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ fetch-assets.sh                    # Download heavy assets from GH releases
β”‚   └── simulate.js                        # Fire fake webhooks for local testing
β”œβ”€β”€ docs/
β”‚   └── toast-api.md                       # Toast API integration notes
β”œβ”€β”€ .env.example                           # Env var template (copy to .env)
β”œβ”€β”€ Dockerfile                             # Multi-stage (alpine build + slim runtime)
β”œβ”€β”€ docker-compose.yml                     # Portable base compose (localhost)
└── CLAUDE.md                              # Dev reference

Quick Start

1. Clone + fetch assets

git clone https://github.com/nullEFFORT/the-expo.git
cd the-expo
./scripts/fetch-assets.sh

Why a separate fetch step? Heavy binary assets (3D car models, sprite sheets, tile packs β€” ~87 MB) are published as a GitHub Release artifact instead of being committed to git. The fetch script downloads the bundle for the pinned version (ASSETS_VERSION in the script) and extracts it into client/public/models/.

The script will try GITHUB_TOKEN, then the gh CLI, then the token embedded in the origin remote URL (works for HTTPS clones with credential helpers). If you bump the asset bundle later, edit ASSETS_VERSION in the script and re-run it.

2. Configure environment

cp .env.example .env
# Fill in TOAST_RESTAURANT_GUID, TOAST_CLIENT_ID, TOAST_CLIENT_SECRET, DOMAIN

3a. Development

cd server && npm install && npm run dev    # http://localhost:3005
cd client && npm install && npm run dev    # http://localhost:5173

3b. Docker

docker compose up -d --build

Default deployment binds to localhost:${PORT}. For Unraid/macvlan setups, create a docker-compose.override.yml with your br0 network + persistent data volume (see the example pattern in this repo's CLAUDE.md).

Asset bundle contents

What scripts/fetch-assets.sh puts into client/public/models/:

Path Source pack Used by
MovieCarsSet/ MovieCarsSet FBX Shake N Bake 3D cars
characters/char_free/ Char Free (itch.io) Player avatars (12-layer sprite)
characters/tiny_rpg_clean/soldier/ Tiny RPG Character Asset Pack v1.03b (free tier) Boss Raid heroes
characters/tiny_rpg_clean/orc/ Tiny RPG Character Asset Pack v1.03b (free tier) Boss Raid enemies
tilesets/infernus/ PVGames Infernus (free tier) Boss Raid hellscape backgrounds

To swap in your own content: replace files at the paths above and rebuild β€” the client references them by absolute URL, no config changes needed.

Toast POS Setup

  1. Get API credentials from Toast Web (Standard API access)
  2. Enter client ID + secret in admin panel (/hnic)
  3. Sync employee roster from the admin panel
  4. Configure Toast to send order webhooks to your /api/webhook/orders endpoint
  5. Each closed check fires the active game(s)

API Endpoints

Public

  • GET /api/games β€” list game modes with vote counts
  • POST /api/games/vote β€” cast vote (session required)
  • GET /api/lobby/players β€” voting lobby roster
  • GET /api/boss-raid/state β€” current run state
  • GET /api/boss-raid/quests β€” list available quests
  • POST /api/webhook/orders β€” Toast order receiver
  • POST /api/webhook/test β€” manual order simulation

Admin (PIN-protected via x-admin-pin header)

  • POST /api/admin/boss-raid/start β€” start a run with optional questId and dailySpecials
  • POST /api/admin/boss-raid/end β€” force-end the current run
  • POST /api/admin/boss-raid/seed-history β€” pull historical pace from Toast
  • POST /api/admin/boss-raid/add-hero β€” manually add a player to the party

Debug

  • POST /api/debug/tv-error β€” TV client posts React crash reports here; logged to docker logs the-expo

Roadmap

Phase 1: Foundation βœ…

  • Toast integration + webhook receiver
  • Game engine with power-ups/spinouts
  • TV display + mobile companion
  • Race-scoped QR code joining

Phase 2: Shake N Bake Polish βœ…

  • Three.js 3D rendering with FBX models
  • Split-screen shared world
  • BOH partner system
  • Coin economy + prize shop
  • Admin panel with prize management
  • Sale pop animations

Phase 3: Player Accounts + Voting βœ…

  • Persistent player profiles tied to Toast employee GUIDs
  • Manager-triggered employee roster sync
  • First-login onboarding: pick employee β†’ character builder β†’ PIN
  • PIN login for returning players
  • Modular character builder (shirt hue, flair, accent color)
  • Pre-shift voting lobby with live SSE updates

Phase 4: Boss Raid 🚧 (alpha)

  • Backend engine, state machine, tick loop
  • 10 themed quests + 30+ mob definitions
  • Pace calculator with historical baseline
  • Sprite-based TV renderer (Tiny RPG pack)
  • Infernus tile backgrounds per area
  • Speech bubbles and scene cards
  • Buffs/debuffs on party cards
  • Mob auto-attack with real HP drops
  • Slow-pace hole-drop mechanic (visual + engine)
  • On-screen error boundary with server-side crash reporting
  • [OPEN BUG] Client renders blank after raid start β€” no heroes on map, screen flashes blank. Error boundary ships crash reports to /api/debug/tv-error; see docker logs the-expo for stack traces.

Phase 5: More Games

  • Fighter (1v1 tournament bracket)
  • Battle Royale (elimination mode)

Phase 6: Multi-Restaurant

  • Multiple Toast restaurants per install
  • Cross-location tournaments
  • Franchise leaderboards

License

Private. Built for ForkLift Restaurant (Tupelo, MS).


"If you ain't first, you're last." β€” Ricky Bobby

About

Restaurant gamification platform. Toast POS data drives competitive games on a back-of-house TV. First game mode: Shake N Bake (racing).

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages