Event Reference
All WebSocket messages are JSON objects with a type field. The transport is PartySocket (native WebSocket under the hood).
Client β Serverβ
create_sessionβ
Sent by host to create a new session.
{
type: 'create_session';
title: string;
hostId: string; // e.g. 'TANNIC-FALCON'
timerSeconds: number; // 15β120
wines: Array<{
name: string;
questions: Array<{
category: 'color' | 'country' | 'grape_variety' | 'vintage_year' | 'wine_name';
correctAnswer: string;
distractors: [string, string, string];
}>;
}>;
}
join_sessionβ
Sent by participant to join a waiting session.
{ type: 'join_session'; code: string }
rejoin_hostβ
Sent by host on socket open to re-authenticate (after page refresh or reconnect).
{ type: 'rejoin_host'; hostId: string }
rejoin_sessionβ
Sent by participant on socket open when a rejoinToken is in localStorage.
{ type: 'rejoin_session'; rejoinToken: string }
host:start / host:pause / host:resume / host:reveal / host:next / host:endβ
Host control events β no additional payload.
{ type: 'host:start' }
{ type: 'host:pause' }
{ type: 'host:resume' }
{ type: 'host:reveal' }
{ type: 'host:next' }
{ type: 'host:end' }
submit_answerβ
Sent by participant to select or change an answer.
{ type: 'submit_answer'; questionId: string; optionId: string }
Server β Clientβ
session:createdβ
Sent to host after successful create_session.
{ type: 'session:created'; code: string; hostId: string }
participant:joinedβ
Sent to the joining participant.
{ type: 'participant:joined'; pseudonym: string; rejoinToken: string }
lobby:updatedβ
Broadcast to all connected clients when a participant joins or leaves the lobby.
{ type: 'lobby:updated'; participants: string[] }
host:state_snapshotβ
Sent to host on rejoin_host (full current state).
{
type: 'host:state_snapshot';
code: string;
hostId: string;
phase: SessionPhase;
participants: string[];
question: QuestionPayload | null;
rankings: RankingEntry[];
}
participant:state_snapshotβ
Sent to participant on rejoin_session.
{
type: 'participant:state_snapshot';
pseudonym: string;
phase: SessionPhase;
question: QuestionPayload | null;
}
sessions:listβ
Sent to host listing their past and active sessions (sourced from KV).
{
type: 'sessions:list';
sessions: Array<{
code: string;
title: string;
createdAt: string;
status: 'waiting' | 'active' | 'ended';
participantCount: number;
finalRankings?: RankingEntry[];
}>;
}
game:questionβ
Broadcast when a new question starts.
{
type: 'game:question';
questionId: string;
prompt: string;
category: QuestionCategory;
options: Array<{ id: string; text: string }>; // shuffled; no 'correct' flag
roundIndex: number;
questionIndex: number;
totalQuestions: number;
totalRounds: number;
timerMs: number;
}
game:timer_tickβ
Emitted every second during question_open and question_paused.
{ type: 'game:timer_tick'; remainingMs: number }
game:timer_paused / game:timer_resumedβ
{ type: 'game:timer_paused'; remainingMs: number }
{ type: 'game:timer_resumed'; remainingMs: number }
game:participant_answered (host only)β
{ type: 'game:participant_answered'; answeredCount: number; totalCount: number }
game:answer_revealedβ
Sent to host:
{
type: 'game:answer_revealed';
correctOptionId: string;
results: Array<{ pseudonym: string; points: number; totalScore: number }>;
}
Sent to each participant:
{
type: 'game:answer_revealed';
correctOptionId: string;
myPoints: number;
myTotalScore: number;
}
game:round_leaderboardβ
{
type: 'game:round_leaderboard';
rankings: RankingEntry[];
roundIndex: number;
totalRounds: number;
}
game:final_leaderboardβ
{ type: 'game:final_leaderboard'; rankings: RankingEntry[] }
session:endedβ
{ type: 'session:ended' }
errorβ
{ type: 'error'; message: string }
Connection / Lifecycle Eventsβ
server:state_snapshotβ
Sent by the backend to every client immediately after they connect or reconnect. Contains the current session phase so clients can restore their UI state.
Direction: Server β Client
Payload:
{
"phase": "waiting | question_open | question_paused | question_revealed | round_leaderboard | ended",
"code": "1234"
}
Participants use this event to detect when a session has ended while they were disconnected. If
phase === "ended", the client transitions to the ended state and clears the rejoin token.
sessions:listβ
Sent to the host in response to connecting with a host ID. Contains all sessions stored under that host ID.
Direction: Server β Host
Payload:
[
{
"code": "1234",
"title": "My Wine Night",
"createdAt": "2024-01-01T00:00:00.000Z",
"status": "waiting | ended",
"participantCount": 3
}
]
host:state_snapshotβ
Sent to a host on reconnect to restore their session state.
Direction: Server β Host
Payload: Same shape as the full host game state (participants, current question, phase, etc.)
participant:state_snapshotβ
Sent to a participant on reconnect to restore their game state.
Direction: Server β Participant
Payload: Same shape as the full participant game state (phase, current question, selected option, etc.)
Typesβ
type QuestionCategory = 'color' | 'country' | 'grape_variety' | 'vintage_year' | 'wine_name';
type SessionPhase = 'waiting' | 'question_open' | 'question_paused' | 'question_revealed' | 'round_leaderboard' | 'ended';
interface RankingEntry {
pseudonym: string;
score: number;
rank: number;
}