@creaditor/course-starterkit
v0.9.0
Published
Creaditor Course Builder - a course channel: sidebar of units & lessons, each lesson edited with the Creaditor
Readme
@creaditor/course-starterkit
A course channel for Creaditor — a peer to @creaditor/web-starterkit and
@creaditor/newsletter-starterkit. Where those edit a single page, this builds a
course: a sidebar of units (drawers) and lessons, where each lesson is one
Creaditor page.
Architecture
Three layers, cleanly separated:
@creaditor/course-core headless · offline · framework-agnostic
Course → Section → Lesson{ status, access, prerequisite, drip, doc }
CRUD + events (lesson:created, content:changed, settings:changed, …) + guards
CourseBuilder (this package) binds course-core ⇄ one Creaditor instance
openLesson() → setContent() editor onSave → setLessonContent()
UI shell (this package) <course-sidebar> · <lesson-settings>
"מבנה הקורס" (manage) ⇄ "עריכת שיעור" (the Creaditor takes the screen)- course-core is the developer surface. It never touches the DOM; every
mutation emits an event to persist/track, plus
before*guard hooks so production can enforce "locked stays locked" in the core, not just the UI. - A lesson is a web page, so lessons are edited with the existing web
element catalog (
channel: "web") — no new element types required. - One editor instance, content swapped per lesson. Each lesson's page is a
commands.toJSON()snapshot held in course-core, which keeps the whole course serializable and offline.
Two authoring modes
| Mode | Owns the screen | For | | --- | --- | --- | | מבנה הקורס | course chrome (curriculum + lesson settings) | arrange units, set נעול/פורסם/דרוש-שיעור-קודם | | עריכת שיעור | the Creaditor + its own design panel | edit the lesson page content |
Course-settings live in manage mode; page-design lives in the Creaditor — so the two inspector panels never compete for the same edge.
Lesson types
Adding a lesson opens a three-way menu — שיעור (lesson) · בוחן (quiz) ·
סרטון (video) — and the choice is stored as lesson.type, travels in
save-course-structure, and survives a reload.
lesson and quiz have real editors; video does not yet. Picking video
sets the type and shows its icon in the sidebar, but opens the ordinary page
editor. A quiz lesson opens on a real quiz authoring surface — see
The quiz element below.
Requires @creaditor/course-core@^0.2.0. On ^0.1.0 the engine drops type
silently, with no error at any layer.
The quiz element and the shape it stores
This package owns the quiz element, so this is where its stored shape is
defined. A quiz is a Creaditor element on a lesson's page — not a new
document type — registered from the course side through the editor's
plugins list. It appears only in the course builder; the web and
newsletter editors never see it.
One question type: single-answer multiple choice. The element node is
type: "quiz", and everything it owns lives under props.questions:
{
"questions": [
{
"id": "q_48c9574f",
"text": "What is the capital of France?",
"options": [
{ "id": "o_959bda38", "text": "Lyon", "correct": false },
{ "id": "o_178416ec", "text": "Paris", "correct": true },
{ "id": "o_855cfa0f", "text": "Marseille", "correct": false }
]
}
]
}A well-formed question holds 2 to 6 options with exactly one marked
correct, and non-blank text on the question and every option (whitespace-only
input is stored as ""). Those are enforced on authoring transitions, not on
data the element did not write — a question that arrives outside them renders as
it is and is flagged incomplete, because opening a lesson must never rewrite its
stored content.
Two things a host rendering this to learners has to know:
textis arbitrary creator-authored content. Escape it exactly as you would any other rich-text field. The element stores it verbatim and never turns it into markup on its own surface; past that boundary it is yours.- The
correctflags are in the payload. Shipping the whole lesson document to a learner's browser before grading ships them the answer key.
Authoring only. The correct answer is stored because it is authored content; this element evaluates nothing — no scoring, no student answers, no gradebook.
@creaditor/cdtr-course-builder's README is the integration-facing copy: it
documents the same shape beside the save-lesson-data event that carries it.
Status model (matches the market)
- lifecycle —
draft → published - access —
free(preview) ·locked(needs enrollment)
Independent axes: a lesson can be published but locked.
Status
- ✅
@creaditor/course-core— engine + tests (npm test) - ✅
CourseBuilder— editor-binding host (this file) - ✅ UI shell —
<course-sidebar>+<lesson-settings>, vanilla web components - ✅ Lesson types recorded (
lesson/quiz/video) - ✅ Quiz element — single-answer multiple choice, authoring only
- ⬜ Video lesson editor + completion-gating settings
- ⬜ Production render / SSR with locked-content enforcement
