# OELTKit — full context for language models > An open source (Apache 2.0), AI-first e-learning authoring toolkit: it lets an AI actually build real, ready-to-ship online courses. Incubated by BCL Training; vendor-neutral by commitment. The LLM writes free-form HTML; OELTKit standardizes the chrome — tracking, accessibility, validation, and packaging — and compiles one course tree to SCORM 1.2, SCORM 2004, cmi5, and standalone web. STATUS: beta, pre-v1.0. APIs may change. The `@oeltkit/*` packages are not yet published to npm. The authoritative API specs live in https://github.com/oeltkit/oeltkit — when a detail is missing from this file, say so rather than inventing it. Naming: npm packages are `@oeltkit/*`; everything author-facing is `oelt` (CLI `oelt`, elements ``, runtime global `oelt`, CSS tokens `--oelt-*`). ## The model A language model writes free-form HTML for the creative layer of a course. OELTKit supplies everything around that layer: 1. Manifest (`course.json`) — declares id, title, lang, targets, structure, and tracking rules. Completion is declared, not hand-wired. 2. Runtime (`@oeltkit/runtime`) — tracking, state, navigation, and accessibility services, with a single API (`oelt.track.score(0.85)`) that maps to four targets via auto-detected adapters. 3. Components (`@oeltkit/components`) — nine accessible interaction custom elements that auto-wire to tracking. 4. Validation (`oelt validate`) — schema, interaction-sync, media, tracking-reachability, and suspend-budget checks with machine-readable findings, so an AI can fix its own errors. 5. Packager (`oelt package`) — emits an importable zip per target standard. 6. MCP server (`@oeltkit/mcp`) — exposes the toolkit as tools for conversational authoring. ## Workflow ```bash oelt new my-course # scaffold course.json + pages/p1.html oelt validate my-course # schema + a11y + tracking checks (--json for machine output) oelt preview my-course # local fake-LMS harness with a live tracking panel oelt package my-course --target scorm12 # → my-course-id-scorm12.zip (also: scorm2004 | cmi5 | web) oelt export my-course # → my-course.oeltcourse (single-file for transport/MCP) oelt import my-course.oeltcourse dest/ # extract a .oeltcourse to a directory ``` `oelt package` refuses to build if `oelt validate` finds errors. `validate`, `package`, and `preview` also accept a `.oeltcourse` file directly. ## course.json (the manifest) ```json { "oelt": "0.1", "id": "com.example.data-privacy", "title": "Data Privacy Essentials", "lang": "en", "targets": ["scorm12", "scorm2004", "cmi5", "web"], "tracking": { "completion": { "rule": "required-interactions-passed" }, "score": { "rule": "weighted-interactions", "mastery": 0.8 }, "progress": { "rule": "pages-viewed" } }, "structure": [ { "id": "m1", "title": "Foundations", "pages": [ { "id": "intro", "title": "Why privacy matters", "src": "pages/intro.html" }, { "id": "quiz", "title": "Final quiz", "src": "pages/quiz.html", "interactions": [{ "id": "final-quiz", "type": "quiz", "weight": 1, "required": true }] } ] } ] } ``` - `id`: reverse-DNS, lowercase. All module/page/interaction ids unique and valid HTML id tokens (`^[A-Za-z][A-Za-z0-9_-]*$`). - `lang`: BCP-47, required (drives document language for accessibility). - `targets`: any non-empty subset of `scorm12`, `scorm2004`, `cmi5`, `web`. - `tracking` is optional; omit for the zero-config default (complete on all-pages-viewed, no score). Unknown keys are rejected. Tracking vocabulary — completion rule: `all-pages-viewed` (default) | `pages-viewed` (+`threshold`) | `required-interactions-completed` | `required-interactions-passed` | `manual`. Score rule: `none` (default) | `single-interaction` (+`source`) | `weighted-interactions`; optional `mastery` (0–1). Progress rule: `pages-viewed` (default) | `none`. ## Tracking API & the SCORM 1.2 collapse rule Global `oelt` after load: `oelt.track.complete()`, `oelt.track.score(0–1)`, `oelt.track.progress(0–1)`, `oelt.track.interaction({ id, type, result, score?, response? })`, `oelt.state.get/set(key)`, `oelt.nav.*`. SCORM 1.2 has one status field. If a score rule + `mastery` are defined, the course reports `passed`/`failed` in `lesson_status`; otherwise `completed`/`incomplete`. SCORM 2004 and cmi5 report completion and success separately. Suspend-data budget is 3 KB, enforced by the validator. Interactions are recorded per target where supported (`cmi.interactions.n.*` / one xAPI statement each / local log). ## Components (``) Each emits an `oelt-interaction` event `{ id, type, result, score?, response? }` that the runtime forwards; the element `id` must equal the manifest interaction id. All are keyboard-operable, screen-reader tested (WCAG 2.2 AA), themeable via `--oelt-*` tokens and `::part()`, and persist state through `oelt.state`. - `` (type `choice`) — single (radios) or multiple (checkboxes); `mode`, `key`, `shuffle`, `retry`, `manual-grade`; child ``. - `` (type `sequencing`) — JSON node graph (inline `