Pub Quiz Platform — Host app

Combined app document — Host app

Status Draft
App Host app
Generated 2026-05-13
Source of truth .claude/context/apps/host.md

The TV-show app — runs the live quiz session on a TV or projector. Receives .quiz packages from the Designer over local Wi-Fi, advertises itself for Clients to discover, advances slides during the session, and is paired with a Remote for quizmaster control. Runs on iPad, Windows, macOS, and Android tablets.

Overview

The Host renders the Host canvas of each slide at the connected display's native resolution (typical target: 1920×1080 TV or projector). It is the authoritative source of session state — timer, scores, slide pointer, locked/unlocked input — and pushes per-Client slide content eagerly to each Client as it joins.

The Host also accepts a paired Remote (one per session) over a control-message WebSocket. The Remote drives navigation, sees the slide mirror + host-notes + live state, and (in Alpha) issues rich commands like jump-to-slide and trigger-element-reveal.

For the cross-cutting requirements, scope, and platform list, see the project PRD.

User flows

Per-flow diagrams (lifecycle, idle/load, join, session controls, fallback overlay, Remote pairing) live on the dedicated flow page, each linked to its relevant UI mockups.

Architecture

A Unity project, sibling to Quiz.Client, Quiz.Remote, and Quiz.Preview. Two top-level scenes — MainMenu (pre-quiz lobby: load .quiz, accept Designer transfers, list connected teams, start session) and Play (slide-driven runner). References com.quiz.shared-assets, com.quiz.runtime, com.quiz.core via UPM. See Per-App Scaffolding — Host for the on-disk shape. Cross-cutting:

Design notes

The brand identity, palette, typography, and motion language are project-wide and live in the Design Specification. Host-specific design notes (canvas, in-room visual hierarchy, animations) are tagged *{host}* in that document.

Build plan

The Host's items are part of the single project Build Plan. Filter visually for host — Host-tagged work is concentrated in Load-bearing prototype, Designer→Host transfer (Host side), Host live-session features, Crash recovery, First-pass animation.

User flows — detail

Surface-to-surface navigation flows for the Host. Each diagram is a Mermaid flowchart rendered inline. Authoring conventions and theme tokens live in .claude/skills/mermaid-diagrams/SKILL.md.

Surfaces in Host surfaces. Functional requirements in Functional Requirements — Host.

2. Idle + load

Mockups: Idle · Incoming transfer · Package incompatible · Settings

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Inter, system-ui, sans-serif","fontSize":"14px","primaryColor":"#FFFFFF","primaryBorderColor":"#FF009F","primaryTextColor":"#1F1933","secondaryColor":"#F0EBE3","secondaryBorderColor":"#16B2EB","secondaryTextColor":"#1F1933","tertiaryColor":"#F8F5F0","tertiaryBorderColor":"#5A536B","tertiaryTextColor":"#1F1933","lineColor":"#5A536B","edgeLabelBackground":"#F8F5F0","mainBkg":"#F8F5F0","clusterBkg":"#F0EBE3","clusterBorder":"#DDD5C8","titleColor":"#1F1933","nodeBorder":"#5A536B"},"flowchart":{"useMaxWidth":false,"htmlLabels":false,"curve":"basis","padding":20,"nodeSpacing":70,"rankSpacing":80}}}%% flowchart TB ID[Idle screen] ID -->|tap quiz card| LD[Loaded] ID -->|Load file…| OS[OS file picker] --> RCV[Receive + validate] --> ID ID -->|Settings| ST[Settings dialog] ID -->|tap quiz row long-press| QCM[Quiz context menu] QCM --> QSTART[Start session] --> JO[Join screen] QCM --> QPREV[Preview slides] --> LD QCM --> QDEL[Delete from device] --> ID ID -->|incoming push| IT[Incoming-transfer prompt] IT -->|accept| ITR[Receiving... CRC32 + resume] --> ITD[Done banner] --> ID IT -->|reject| ID RCV -->|object-type mismatch| PI[Package-incompatible dialog] --> ID classDef terminal fill:#E8F5EC,stroke:#36D17B,stroke-width:2px,color:#1F1933,rx:14,ry:14 class LD,JO terminal

3. Join + start

Mockups: Join screen · Remote pair prompt

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Inter, system-ui, sans-serif","fontSize":"14px","primaryColor":"#FFFFFF","primaryBorderColor":"#FF009F","primaryTextColor":"#1F1933","secondaryColor":"#F0EBE3","secondaryBorderColor":"#16B2EB","secondaryTextColor":"#1F1933","tertiaryColor":"#F8F5F0","tertiaryBorderColor":"#5A536B","tertiaryTextColor":"#1F1933","lineColor":"#5A536B","edgeLabelBackground":"#F8F5F0","mainBkg":"#F8F5F0","clusterBkg":"#F0EBE3","clusterBorder":"#DDD5C8","titleColor":"#1F1933","nodeBorder":"#5A536B"},"flowchart":{"useMaxWidth":false,"htmlLabels":false,"curve":"basis","padding":20,"nodeSpacing":70,"rankSpacing":80}}}%% flowchart TB JO[Join screen\nQR + URL + code + roster] JO -->|team connects| TR[Team roster row added] TR -->|long-press| TCM[Team context menu] TCM --> RN[Rename team] --> TR TCM --> KK[Kick] --> JO TCM --> AC[Assign colour — Beta] --> TR JO -->|Start quiz ▸| SE[Session] JO -->|Back to library| BCONF{Teams joined?} BCONF -->|yes| BC[Confirm leave] --> ID[Idle] BCONF -->|no| ID JO -->|Pair Remote| RP[Remote pair prompt\ncode + QR] --> RPA[Remote accepts / rejects] --> JO classDef decision fill:#FFF1DC,stroke:#FFA94D,stroke-width:2px,color:#1F1933 classDef terminal fill:#E8F5EC,stroke:#36D17B,stroke-width:2px,color:#1F1933,rx:14,ry:14 class BCONF decision class SE,ID terminal

4. Session — controls (operator window)

Mockups: Operator window · Audience window · End-session confirm · Final standings

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Inter, system-ui, sans-serif","fontSize":"14px","primaryColor":"#FFFFFF","primaryBorderColor":"#FF009F","primaryTextColor":"#1F1933","secondaryColor":"#F0EBE3","secondaryBorderColor":"#16B2EB","secondaryTextColor":"#1F1933","tertiaryColor":"#F8F5F0","tertiaryBorderColor":"#5A536B","tertiaryTextColor":"#1F1933","lineColor":"#5A536B","edgeLabelBackground":"#F8F5F0","mainBkg":"#F8F5F0","clusterBkg":"#F0EBE3","clusterBorder":"#DDD5C8","titleColor":"#1F1933","nodeBorder":"#5A536B"},"flowchart":{"useMaxWidth":false,"htmlLabels":false,"curve":"basis","padding":20,"nodeSpacing":70,"rankSpacing":80}}}%% flowchart TB SE[Session\naudience window + operator window] SE -->|Next slide ▸| SE SE -->|◂ Previous| SE SE -->|+10s| SE SE -->|Skip timer| SE SE -->|Lock now| SE SE -->|Unlock| SE SE -->|Show leaderboard| SE SE -->|Trigger reveal — Alpha| SE SE -->|Jump to slide… — Alpha| JTS[Jump dialog] --> SE SE -->|Score overrides — Alpha| SO[Overrides panel] --> SE SE -->|Pause session| PA[Paused overlay] --> SE SE -->|End session…| ES{Confirm?} ES -->|yes| EN[Session end · final standings] ES -->|no| SE SE -->|Mute jingles| SE SE -->|client disconnect| RB[Reconnecting banner] --> SE SE -->|Remote disconnect| RD[Remote-disconnected notification] --> SE classDef decision fill:#FFF1DC,stroke:#FFA94D,stroke-width:2px,color:#1F1933 classDef terminal fill:#E8F5EC,stroke:#36D17B,stroke-width:2px,color:#1F1933,rx:14,ry:14 class ES decision class EN terminal

5. Single-display fallback overlay

Mockups: Audience window (overlay state)

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Inter, system-ui, sans-serif","fontSize":"14px","primaryColor":"#FFFFFF","primaryBorderColor":"#FF009F","primaryTextColor":"#1F1933","secondaryColor":"#F0EBE3","secondaryBorderColor":"#16B2EB","secondaryTextColor":"#1F1933","tertiaryColor":"#F8F5F0","tertiaryBorderColor":"#5A536B","tertiaryTextColor":"#1F1933","lineColor":"#5A536B","edgeLabelBackground":"#F8F5F0","mainBkg":"#F8F5F0","clusterBkg":"#F0EBE3","clusterBorder":"#DDD5C8","titleColor":"#1F1933","nodeBorder":"#5A536B"},"flowchart":{"useMaxWidth":false,"htmlLabels":false,"curve":"basis","padding":20,"nodeSpacing":70,"rankSpacing":80}}}%% flowchart TB AW[Audience window only\nno second display] -->|tap / move mouse| OV[Overlay summoned\ncontrol row visible] OV -->|auto-hide 4s| AW OV -->|operator action| AW

6. Remote pairing

Mockups: Remote pair prompt

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Inter, system-ui, sans-serif","fontSize":"14px","primaryColor":"#FFFFFF","primaryBorderColor":"#FF009F","primaryTextColor":"#1F1933","secondaryColor":"#F0EBE3","secondaryBorderColor":"#16B2EB","secondaryTextColor":"#1F1933","tertiaryColor":"#F8F5F0","tertiaryBorderColor":"#5A536B","tertiaryTextColor":"#1F1933","lineColor":"#5A536B","edgeLabelBackground":"#F8F5F0","mainBkg":"#F8F5F0","clusterBkg":"#F0EBE3","clusterBorder":"#DDD5C8","titleColor":"#1F1933","nodeBorder":"#5A536B"},"flowchart":{"useMaxWidth":false,"htmlLabels":false,"curve":"basis","padding":20,"nodeSpacing":70,"rankSpacing":80}}}%% flowchart TB RPP[Remote pair prompt\nopened from join / settings / operator menu] RPP -->|show code + QR| WAIT[Wait for Remote] WAIT -->|Remote scans QR or types code| RA[Accept prompt — Remote 'X' wants to pair] RA -->|Accept| PAIRED[Paired indicator on operator HUD] RA -->|Reject| WAIT RPP -->|Regenerate code| RPP PAIRED -->|Remote disconnects| WAIT classDef terminal fill:#E8F5EC,stroke:#36D17B,stroke-width:2px,color:#1F1933,rx:14,ry:14 class PAIRED terminal

See also: Host surfaces · Networking · Functional Requirements — Host.