@ludus/game-engine-react
React components and hooks for embedding Ludus games. Live spectating, replay gallery with filters, commentary integration, and game state management.
Installation
Section titled “Installation”npm install @ludus/game-engine-reactComponents
Section titled “Components”SpectatorShell
Section titled “SpectatorShell”Main layout wrapper for viewing a game — composes GameViewer, Leaderboard, CommentaryFeed, and ReplayControls.
import { SpectatorShell } from '@ludus/game-engine-react';
<SpectatorShell gameId="game-123" mode="live" // or "replay" showCommentary={true}/>LiveSpectatorShell
Section titled “LiveSpectatorShell”Composes SpectatorShell with useLiveCommentary for live games with integrated AI commentary.
import { LiveSpectatorShell } from '@ludus/game-engine-react';
<LiveSpectatorShell gameId="game-123" commentaryProvider={provider} />CommentedReplayShell
Section titled “CommentedReplayShell”Drop-in replay viewer with built-in commentary (pre-generated on load, filtered by current turn).
import { CommentedReplayShell } from '@ludus/game-engine-react';
<CommentedReplayShell replay={gameReplay} persona={ORIANA} />ReplayGallery
Section titled “ReplayGallery”Gallery of past games with filtering and sorting.
import { ReplayGallery } from '@ludus/game-engine-react';
<ReplayGallery replays={replayList} onSelect={(replay) => navigate(`/replay/${replay.replayId}`)}/>Supports filtering by game type and sorting: newest, oldest, longest, shortest.
ReplayCard
Section titled “ReplayCard”Individual replay card for the gallery.
ReplayControls
Section titled “ReplayControls”Playback controls: play/pause, step forward, scrub to turn, speed selector.
Leaderboard
Section titled “Leaderboard”Player rankings with active player highlighting.
CommentaryFeed
Section titled “CommentaryFeed”Scrollable AI commentary messages with auto-scroll to latest.
useReplay
Section titled “useReplay”Replay playback with play/pause/seek/speed control.
import { useReplay } from '@ludus/game-engine-react';
const { currentTurn, totalTurns, currentEntry, isPlaying, speed, play, pause, seek, setSpeed } = useReplay(replay);useGameState
Section titled “useGameState”Subscribe to live game state via a transport-agnostic StateProvider.
import { useGameState } from '@ludus/game-engine-react';
const { state, connected, error } = useGameState('game-123', stateProvider);useLiveCommentary
Section titled “useLiveCommentary”Subscribe to live commentary via CommentaryProvider.
import { useLiveCommentary } from '@ludus/game-engine-react';
const { messages, active } = useLiveCommentary(commentaryProvider);// messages: CommentaryMessage[]useReplayCommentary
Section titled “useReplayCommentary”Pre-generates all commentary for a replay on load, filters by current turn.
import { useReplayCommentary } from '@ludus/game-engine-react';
const { messages, loading } = useReplayCommentary({ replay, persona: ORIANA, currentTurn });useReplayList
Section titled “useReplayList”Paginated replay list with filtering.
import { useReplayList } from '@ludus/game-engine-react';
const { replays, loading, loadMore, refresh } = useReplayList({ gameType: 'konquista', orderBy: 'newest' });useReplayDetail
Section titled “useReplayDetail”Load a single full replay by ID.
import { useReplayDetail } from '@ludus/game-engine-react';
const { replay, loading, error } = useReplayDetail('replay-123');Services
Section titled “Services”ReplayService
Section titled “ReplayService”Firestore persistence for replays.
import { ReplayService } from '@ludus/game-engine-react';
const service = new ReplayService(firestoreDb);await service.save(gameReplay);
const { replays, lastDoc } = await service.list({ gameType: 'konquista', limit: 10, orderBy: 'newest' });const replay = await service.get('replay-123');Event Converters
Section titled “Event Converters”Convert ReplayEntry to GameEvent for the commentary pipeline.
import { replayToGameEvents, makeGameStartEvent, makeGameOverEvent } from '@ludus/game-engine-react';
const events = replayToGameEvents(replay); // GameEvent[] including synthetic start/end eventsInterfaces
Section titled “Interfaces”StateProvider
Section titled “StateProvider”Transport-agnostic live game state (WebSocket, Firestore, in-process):
interface StateProvider { subscribe(gameId: string, onState: (state: BaseGameState) => void, onError?: (error: Error) => void): () => void;}CommentaryProvider
Section titled “CommentaryProvider”Transport-agnostic live commentary:
interface CommentaryProvider { subscribe(callback: (msg: CommentaryMessage) => void): () => void; getHistory(): CommentaryMessage[];}CommentaryMessage
Section titled “CommentaryMessage”interface CommentaryMessage { id: string; turn: number; text: string; persona?: string; timestamp: number;}import type { StateProvider, CommentaryProvider, CommentaryMessage, SpectatorConfig, GameViewProps, GameViewerProps, ReplayFilters, SortOrder, ReplayListResult, ReplaySummary } from '@ludus/game-engine-react';