Skip to content

LessonKit interoperability

LessonKit interoperability (LXPack 0.6.4+)

LXPack validates and packages LessonKit React courses for LMS delivery. @lessonkit/lxpack is the adapter between the two.

Requires Node.js 18+ and LXPack @lxpack/api 0.6.4+.

LessonKit current release: 1.0.0 · npm @lessonkit/* · docs lessonkit.readthedocs.io

Who uses what

You are… Start here
React / Vite author (recommended) LessonKitnpx @lessonkit/cli init, lessonkit dev, lessonkit package --target scorm12
Instructional designer / YAML author LXPack — lxpack init, markdown/HTML lessons, lxpack build
Integrator / CI @lessonkit/lxpack (packageLessonkitCourse) or @lxpack/api (packageLessonkit)

Workflow

  1. Author a React app with stable courseId, lessonId, and checkId props (@lessonkit/react).
  2. Describe the course in a LessonkitCourseDescriptor or root lessonkit.json (schemaVersion: 1).
  3. Build the Vite app (lessonkit builddist/).
  4. Package with lessonkit package or packageLessonkitCourse().
npx @lessonkit/cli init my-course
cd my-course
lessonkit dev
lessonkit build
lessonkit package --target scorm12

Programmatic packaging:

import { packageLessonkitCourse } from "@lessonkit/lxpack";

const result = await packageLessonkitCourse({
  descriptor: myCourseDescriptor,
  outDir: ".lxpack/course",
  spaDistDir: "dist",
  target: "scorm12",
  output: ".lxpack/out/course-scorm12.zip",
});

if (!result.ok) {
  console.error(result.issues);
  process.exit(1);
}

See LessonKit docs: packaging · CLI · LXPack bridge · golden example.

How it fits together

flowchart LR
  subgraph lk [LessonKit 1.0]
    REACT["@lessonkit/react"]
    CLI["@lessonkit/cli"]
    LKL["@lessonkit/lxpack"]
  end
  subgraph lxp [LXPack 0.6.4]
    API["@lxpack/api"]
    RT["@lxpack/runtime"]
    PKG["SCORM · xAPI · cmi5"]
  end
  REACT --> CLI
  CLI --> LKL
  LKL --> API
  API --> PKG
  RT --> PKG

LXPack-native workflow (no React)

For manifest-driven courses (course.yaml, markdown, HTML, components), use the lxpack CLI directly.

For interchange-only SPA projects (no hand-written course.yaml):

lxpack build --lessonkit ./lessonkit.json \
  --spa-lesson intro_spa=/abs/path/to/dist \
  --target scorm12

Or programmatically:

import { packageLessonkit } from "@lxpack/api";

await packageLessonkit({
  configDir: "/path/to/project",
  interchange: { /* LXPack v1 interchange */ },
  spaDirs: { intro_spa: "/abs/path/to/dist" },
  target: "scorm12",
});

SPA layouts

One Vite build, one type: spa lesson in the LXPack project. Multi-lesson navigation stays inside your React app.

  • Set layout: "single-spa" on the descriptor.
  • Copy source from spaDistDir (default dist) into {outDir}/dist.
lessons:
  - id: phishing_101
    title: Phishing Awareness
    type: spa
    path: dist/lessons/phishing-101

per-lesson-spa

One build output per lesson (multi-SCO friendly).

  • Set layout: "per-lesson-spa".
  • Each lesson needs spaPath (e.g. dist/lessons/intro).
  • Pass lessonSpaDirs: { intro: "/abs/path/to/build" } to packageLessonkitCourse.

See SCORM SPA recipes.

LMS bridge (iframe)

When the SPA runs inside LXPack, call the parent bridge (or rely on @lessonkit/react, which forwards completion events when window.parent.lxpackBridge.v1 exists):

import { notifyLxpackLessonComplete } from "@lessonkit/lxpack/bridge";

notifyLxpackLessonComplete("intro");

Direct calls (or non-React SPAs):

import { getLxpackBridge } from "@lxpack/spa-bridge";

const bridge = getLxpackBridge();
bridge?.completeLesson("phishing_101");
bridge?.submitAssessment({ id: "final_quiz", score: 0.9, passingScore: 0.7 });

Disable forwarding: config.lxpack.bridge = "off" on LessonkitProvider. See SPA bridge reference.

Interchange metadata (lessonkit.json)

Two related shapes:

Source Shape Parsed by
LessonKit project manifest schemaVersion: 1 at repo root @lessonkit/lxpack (parseLessonkitManifest)
LXPack interchange "format": "lessonkit", "version": "1" @lxpack/validators, @lxpack/api, lxpack CLI

@lessonkit/lxpack emits LXPack-compatible interchange when materializing projects. See lessonkit interchange reference.

Telemetry mapping

LessonKit telemetry event names map to LXPack track() via mapLessonkitTelemetryToLxpack from @lxpack/tracking-schema (re-exported by @lxpack/lessonkit and used in @lessonkit/lxpack/bridge).

Package map

LessonKit (1.0) LXPack (0.6.4) Role
@lessonkit/react React components, hooks, ThemeProvider
@lessonkit/core Identity, telemetry catalog
@lessonkit/xapi @lxpack/xapi xAPI (author-time vs export-time)
@lessonkit/lxpack @lxpack/api Descriptor → materialize → build
@lessonkit/cli @lxpack/cli Author CLI vs low-level LXPack CLI
@lxpack/spa-bridge Typed iframe bridge SDK
@lxpack/lessonkit LXPack meta-package (API + bridge re-exports)
@lxpack/conformance Shared export-target matrix for CI

See LessonKit and LXPack packages.

Conformance

LessonKit runs LXPack conformance in CI (npm run conformance:lxpack). LXPack maintainers:

pnpm --filter @lxpack/conformance test

Validate against the golden example:

git clone https://github.com/eddiethedean/lessonkit.git
cd lessonkit && npm ci && npm run build
npm -w lessonkit-example-lxpack-golden run package:scorm12