Production checklist¶
Appendix — part of LMS Go-Live
This checklist covers production guardrails in detail. For the full go-live path (including the smoke-test branch), start with LMS Go-Live and return here for the observability matrix.
Use this checklist before shipping a LessonKit course to learners in an LMS, standalone site, or LRS-backed deployment.
Packaging target¶
Target |
|
|
xAPI transport |
|---|---|---|---|
SCORM / xAPI / cmi5 (LXPack iframe) |
|
Required in production — LMS parent origin(s) |
Required if you report to an LRS |
Standalone web (no LMS parent) |
|
Omit |
Required if you report to an LRS |
The lessonkit init template scaffolds lxpack.bridge: "off". Set "auto" and configure allowedParentOrigins before packaging for LMS iframe targets:
lxpack: {
bridge: "auto",
allowedParentOrigins: ["https://your-lms.example"],
},
Development builds allow bridge forwarding without an allowlist; production builds deny it when the list is empty. See LXPack bridge reference.
Do not ship config.preview.allowConsoleTelemetry in learner-facing production builds — it is for Read the Docs demo bundles only. Wire real sinks and all config.observability hooks instead.
Verify the parent exposes window.parent.lxpackBridge.v1 in SCORM previews before go-live. If the bridge is missing, completions stay in the UI only.
xAPI and analytics¶
Configure a transport —
config.xapi.transportorconfig.xapi.client. Without it, statements queue in memory only.Use timeout + backoff — prefer
createFetchTransportfrom@lessonkit/xapi(usesAbortSignal.timeoutand retry backoff). WireexitTransportfor pagehide keepalive delivery.Flush on tab exit —
LessonkitProvidercallsflushOnExit(keepalive) then asyncflushonvisibilitychange(hidden) andpagehide. Custom clients must implementflushOnExitthemselves.Monitor queue depth — use
config.observability.onXapiQueueDepthand handleonXapiQueueCapwhen the queue drops oldest statements (default cap: 1000).Never embed LRS secrets in the bundle — use short-lived tokens from your backend or LMS proxy; do not ship Basic auth passwords in client JavaScript.
Session and resume¶
Unique
blockIdon eachPage,InteractiveBook, andAssessmentSequencewhenpersistCompoundStateis enabled (defaulttrue).Kiosk / shared devices — set
config.session.persistCompoundState: falseor use private browsing. See Security.Expect multi-tab last-write-wins — same origin tabs share
sessionStoragekeys.
Observability (required in production)¶
When telemetry or xAPI delivery is configured, wire observability hooks so silent data loss surfaces in your monitoring stack. Required hooks depend on what you enable:
Config |
Required hooks |
|---|---|
Tracking or xAPI enabled |
|
Tracking delivery ( |
+ |
xAPI delivery ( |
+ |
Example when both tracking and xAPI use fetch transports:
observability: {
onTelemetrySinkError: (err, ctx) => reportError({ ...ctx, err }),
onTelemetryBufferDrop: () => metrics.increment("lessonkit.telemetry.buffer_cap"),
onXapiQueueDepth: (depth) => metrics.gauge("lessonkit.xapi.queue", depth),
onXapiQueueCap: () => metrics.increment("lessonkit.xapi.queue_cap"),
onLxpackBridgeMiss: (event) =>
reportWarning("lxpack_bridge_missing", { event: event.name }),
onXapiTransportError: (err) => reportError({ code: "xapi_transport", err }),
},
onTelemetryBufferDrop fires when the telemetry batch buffer (cap 1000) drops new events. onTelemetrySinkError covers both per-event sinks and batchSink failures. onLxpackBridgeMiss alerts when SCORM/LMS parent lacks lxpackBridge.v1 (set lxpack.bridge: "auto" only in LMS shells). onXapiTransportError is required when xAPI delivery is configured — it fires when the LRS transport fails after retries.
lessonkit init scaffolds these hooks in src/courseConfig.ts. Production builds call assertProductionCourseConfig() (via shouldEnforceProductionGuard() in the template) — console sinks, tracking.enabled without a sink/batchSink, missing delivery config, or missing hooks throw before the app mounts.
CI / build¶
Pin aligned
@lessonkit/*versions (framework 1.7.x).Set
VITE_XAPI_PROXY_URLandVITE_ANALYTICS_URL(see.env.examplein scaffolded projects).tracking.xapi.activityIriinlessonkit.jsonmust be HTTPS for xAPI/cmi5 packaging.lessonkit buildandlessonkit packagerun under Node 18+; setLESSONKIT_CMD_TIMEOUT_MSif builds need a limit (default 30 minutes per subprocess).lessonkit devhas no subprocess timeout.