Skip to Content
📧 Join the Teacharium waitlist to get access. 

TeachariumPlayer API

The TeachariumPlayer is a self-contained React component for embedding Teacharium lessons in your application. It handles all provider setup internally, making integration straightforward.

Installation

npm install @teacharium/player @teacharium/widget @measured/puck # or pnpm add @teacharium/player @teacharium/widget @measured/puck

Quick Start

import { TeachariumPlayer } from "@teacharium/player"; import { getWidgets } from "@teacharium/widget"; import lessonData from "./lesson.json"; function LessonPage() { return ( <TeachariumPlayer lesson={lessonData} widgets={getWidgets()} onComplete={(result) => console.log("Lesson completed", result)} /> ); }

Props Reference

Required Props

PropTypeDescription
lessonTeachariumLessonExportThe lesson data in export format

You must provide either widgets or puckConfig:

PropTypeDescription
widgetsTeachariumWidget[]List of widgets (recommended for most cases)
puckConfigConfigPre-built Puck config for advanced use cases

Optional Props

PropTypeDefaultDescription
configPartial<PlayerConfig>{}Player configuration options
mode"player" | "review""player"Playback mode (review disables interactions)
initialSessionStateSessionStateundefinedResume from saved session state
mediaResolversMediaResolverConfigNo-opHooks for resolving media URLs
onStepChange(state: SessionState) => voidundefinedCalled at step boundaries for auto-saving
onComplete(result: CompletionResult) => voidundefinedCalled when lesson completes
additionalComponentsRecord<string, ComponentConfig>undefinedExtra Puck components (when using widgets)
classNamestringundefinedCSS class for container
showStartButtonbooleantrueShow start button overlay
startButtonTextstring"Start"Custom start button text
headerContentReact.ReactNodeundefinedContent above the player
sideContentReact.ReactNodeundefinedContent alongside the player (e.g., debug panel)

Session State

The player uses SessionState to track the learner’s progress through a lesson. This includes:

  • Current position in the lesson
  • History of visited steps with variable snapshots
  • Widget states for each step (for resume/review)

SessionState Structure

interface SessionState { version: 1; lessonId: string; currentHistoryIndex: number; stepHistory: StepVisit[]; progress: LessonProgress; currentVariables: Record<string, string | number | boolean>; createdAt: string; updatedAt: string; } interface StepVisit { visitId: string; stepId: string; sectionIndex: number; stepIndex: number; variableSnapshot: Record<string, string | number | boolean>; widgetStates: Record<string, unknown>; itemStates: ItemState[]; visitedAt: string; }

CompletionResult

Sent via onComplete when the lesson finishes:

interface CompletionResult { /** Final variable values at lesson completion */ finalVariables: Record<string, unknown>; /** Final progress state */ progress: LessonProgress; /** Total score achieved (if items had scores) */ score?: number; /** Maximum possible score */ maxScore?: number; /** All items from the lesson */ items?: ItemData[]; /** Full session state for review mode */ sessionState: SessionState; }

Player Configuration

The config prop accepts these options:

interface PlayerConfig { showProgress?: boolean; // Show progress footer (default: true) allowPreviousStep?: boolean; // Allow going back allowSkipping?: boolean; // Allow skipping steps autoAdvance?: boolean; // Auto-advance between steps defaultStepDuration?: number; // Default step duration (ms) showTimer?: boolean; // Show timer UI debugMode?: boolean; // Enable debug logging }

Playback Modes

The mode prop controls how the player behaves:

  • "player" (default): Normal playback mode. Learners can interact with widgets and their progress is tracked.
  • "review": Read-only mode. Shows previous work with all interactions disabled. Use this when revisiting completed lessons.
<TeachariumPlayer lesson={lessonData} widgets={widgets} mode="review" initialSessionState={savedSessionState} />

Media Resolution

Lessons may reference media files (images, videos, voiceovers) by ID. You provide resolver hooks that map these IDs to actual URLs.

import { TeachariumPlayer } from "@teacharium/player"; import { getWidgets } from "@teacharium/widget"; // Map media IDs to static file paths const mediaFiles: Record<string, string> = { "media:abc123": "/lessons/my-lesson/images/intro.png", "media:def456": "/lessons/my-lesson/images/diagram.jpg", }; // Hook that resolves media IDs to URLs function useMediaUrl(mediaId: string | undefined) { if (!mediaId) { return { data: null, isLoading: false, error: null }; } return { data: mediaFiles[mediaId] ?? null, isLoading: false, error: null }; } // Hook that resolves voiceover content to audio URLs function useVoiceoverUrl( contentHash: string | undefined, voice: string | undefined, ) { if (!contentHash || !voice) { return { data: null, isLoading: false, error: null }; } return { data: `/lessons/my-lesson/audio/${contentHash}.mp3`, isLoading: false, error: null, }; } function LessonPage() { return ( <TeachariumPlayer lesson={lessonData} widgets={getWidgets()} mediaResolvers={{ useMediaUrl, useVoiceoverUrl, }} /> ); }

The resolver hooks must return this shape:

interface MediaUrlResult { data: string | null | undefined; isLoading?: boolean; error?: Error | null; }

Saving and Resuming Progress

Saving Progress

Use the onStepChange callback to persist session state at each step boundary:

function LessonWithSaving({ lessonData }) { const handleStepChange = async (sessionState: SessionState) => { // Save to localStorage, server, etc. localStorage.setItem( `lesson-session-${lessonData.lesson.id}`, JSON.stringify(sessionState), ); }; return ( <TeachariumPlayer lesson={lessonData} widgets={getWidgets()} onStepChange={handleStepChange} /> ); }

Resuming Progress

Pass saved session state as initialSessionState:

function ResumableLesson({ lessonData }) { const savedSession = JSON.parse( localStorage.getItem(`lesson-session-${lessonData.lesson.id}`) || "null", ); return ( <TeachariumPlayer lesson={lessonData} widgets={getWidgets()} initialSessionState={savedSession} /> ); }

Review Mode for Completed Lessons

When a lesson is completed, you can display it in review mode:

function ReviewLesson({ lessonData, completedSessionState }) { return ( <TeachariumPlayer lesson={lessonData} widgets={getWidgets()} mode="review" initialSessionState={completedSessionState} /> ); }

Complete Example

import { useState, useEffect } from "react"; import { TeachariumPlayer, type TeachariumLessonExport, type SessionState, type CompletionResult, } from "@teacharium/player"; import { getWidgets } from "@teacharium/widget"; // Media resolution const mediaFiles: Record<string, string> = { "media:intro-image": "/lessons/intro/images/intro.png", }; function useMediaUrl(mediaId: string | undefined) { if (!mediaId) return { data: null }; return { data: mediaFiles[mediaId] ?? null }; } function useVoiceoverUrl( contentHash: string | undefined, voice: string | undefined, ) { if (!contentHash || !voice) return { data: null }; return { data: `/lessons/intro/audio/${contentHash}.mp3` }; } export function LessonPage({ lessonData, }: { lessonData: TeachariumLessonExport; }) { const [initialSession, setInitialSession] = useState< SessionState | undefined >(); const [isReviewMode, setIsReviewMode] = useState(false); // Load saved session on mount useEffect(() => { const saved = localStorage.getItem(`session-${lessonData.lesson.id}`); if (saved) { const session = JSON.parse(saved) as SessionState; setInitialSession(session); setIsReviewMode(session.progress.status === "completed"); } }, [lessonData.lesson.id]); // Save session state at step boundaries const handleStepChange = (state: SessionState) => { localStorage.setItem( `session-${lessonData.lesson.id}`, JSON.stringify(state), ); }; // Handle completion const handleComplete = (result: CompletionResult) => { localStorage.setItem( `session-${lessonData.lesson.id}`, JSON.stringify(result.sessionState), ); console.log("Lesson completed!", { score: result.score, maxScore: result.maxScore, variables: result.finalVariables, }); }; return ( <div className="h-screen"> <TeachariumPlayer lesson={lessonData} widgets={getWidgets()} mediaResolvers={{ useMediaUrl, useVoiceoverUrl }} initialSessionState={initialSession} mode={isReviewMode ? "review" : "player"} onStepChange={isReviewMode ? undefined : handleStepChange} onComplete={handleComplete} config={{ showProgress: true, allowPreviousStep: true, }} showStartButton={true} startButtonText="Begin Lesson" /> </div> ); }

TypeScript Types

Import types from the package:

import type { TeachariumPlayerProps, TeachariumLessonExport, SessionState, CompletionResult, LessonProgress, PlayerConfig, MediaResolverConfig, } from "@teacharium/player";
Last updated on