@beanchain/handbook-lms
v0.2.0
Published
Reusable LMS core contracts and React primitives for Handbook courses.
Downloads
19
Readme
@beanchain/handbook-lms
Reusable package for Handbook LMS logic.
Modules
@beanchain/handbook-lms/core: Canonical LMS types, schemas, and shared contracts.@beanchain/handbook-lms/adapter: Adapter interfaces for host data integration.@beanchain/handbook-lms/config: Strict UI config contract anddefineHandbookLmsConfighelper.@beanchain/handbook-lms/react-headless: Headless editor/review/learning hooks.@beanchain/handbook-lms/react-mui: Prebuilt MUI editor/review/learning components.@beanchain/handbook-lms/react: Legacy provider + headless course library component.@beanchain/handbook-lms/contracts: HTTP endpoint constants and helpers.@beanchain/handbook-lms/sql: Provider-agnostic DB guidance + Supabase appendix.
Canonical contracts
Use @beanchain/handbook-lms/contracts for canonical runtime schemas:
- Entity schemas: course, section/module/stage/question hierarchy, progress, assignments, learning summary.
- Mutation schemas: curriculum CRUD payloads, reorder payloads, review payloads, assignment update payloads.
These schemas are intended for adapter-boundary validation only. Package hooks/components assume canonical data and should not receive domain-specific field names.
Adapter boundary pattern
Validate requests/responses in host adapters before crossing the package boundary:
import {
handbookLmsSectionListSchema,
handbookLmsReviewModuleInputSchema
} from "@beanchain/handbook-lms/contracts";
const curriculum = handbookLmsSectionListSchema.parse(await apiFetch("/api/lms-courses/.../curriculum"));
const reviewPayload = handbookLmsReviewModuleInputSchema.parse(input);If your backend uses different naming, map to canonical package fields in the adapter (for example target_exercise_ids -> target_question_ids).
Host app setup checklist
- Implement
HandbookLmsAdapterper domain (team courses,solution seeking, etc.). - Define strict UI config with
defineHandbookLmsConfig. - Keep backend endpoints + database migrations in host repo.
- Pass only canonical models into package hooks/components.
- Optionally pass
notificationscallbacks into package UI components to integrate host-level toast systems.
Draft publishing workflow
The package assumes a true draft model for course editing:
- Draft metadata + curriculum are edited privately through draft endpoints.
- Live course
publishedandactivetoggles stay separate and remain immediate controls. - Publishing applies draft state to live in one operation.
- Discarding removes draft state without changing live content.
- Adapter methods required for this workflow:
getDraft(courseSlug)lockDraft(courseSlug)saveDraftCourseDetails(courseSlug, data)publishDraft(courseSlug)discardDraft(courseSlug)updateLiveCourseSettings({ courseId, data: { published?, active? } })
Recommended host endpoint contract:
GET /api/lms-courses-admin/:slug/draftPATCH /api/lms-courses-admin/:slug/draft/coursePOST /api/lms-courses-admin/:slug/draft/lockPOST /api/lms-courses-admin/:slug/draft/publishPOST /api/lms-courses-admin/:slug/draft/discard
For prebuilt editor UI, use HandbookLmsCourseEditorWorkspace or compose these primitives:
HandbookLmsDraftDetailsCardHandbookLmsLiveAvailabilityCardHandbookLmsEditorControlsCardHandbookLmsDraftChangesDialogHandbookLmsCurriculumEditor
HandbookLmsCurriculumEditor includes:
- Distinct section/module/stage/question visual hierarchy styling for easier scanning.
- Collapsible module bodies with explicit expand/collapse controls.
- Auto-expansion when adding or saving stages.
Example compositions:
- Team full editor: show all cards + curriculum structure.
- Single-course admin editor: hide draft details/live availability, keep editor controls + structure.
UI config reference
All keys in HandbookLmsUiConfig are required and strongly typed.
Autosave notification keys:
labels.autosaveNotice: Message used for autosave success notices.workflow.enableAutosaveNotifications: Enables/disables autosave notices from learning workspace.workflow.autosaveNotificationCooldownMs: Minimum interval between autosave notices.
Recommended defaults:
workflow.enableAutosaveNotifications: trueworkflow.autosaveNotificationCooldownMs: 12000labels.autosaveNotice: "Progress autosaved."
Example:
import { defineHandbookLmsConfig } from "@beanchain/handbook-lms/config";
export const lmsConfig = defineHandbookLmsConfig({
labels: {
editorTitle: "Course Editor",
reviewTitle: "Course Review",
backButton: "Back",
addSection: "Add section",
addModule: "Add module",
addStage: "Add stage",
addQuestion: "Add question",
editAction: "Edit",
archiveAction: "Archive",
restoreAction: "Restore",
saveAction: "Save",
cancelAction: "Cancel",
saveResponseAction: "Save response",
submitModuleAction: "Submit module",
passAction: "Mark passed",
requestRevisionAction: "Request revision",
applyStatusAction: "Apply status",
noModulesMessage: "No modules are currently configured.",
autosaveNotice: "Progress autosaved."
},
workflow: {
enableModuleDragAndDrop: true,
enableStatusOverride: true,
enableFollowUpAssignments: true,
enableTargetedQuestionSelection: true,
enableAutosaveNotifications: true,
autosaveNotificationCooldownMs: 12000
},
validation: {
slugPattern: /^[a-z0-9]+(?:-[a-z0-9]+)*$/,
slugPatternMessage: "Use lowercase letters, numbers, and single dashes only.",
requiredTitleMessage: "Title is required.",
requiredSlugMessage: "Slug is required.",
requiredSummaryMessage: "Summary is required.",
requiredPromptMessage: "Prompt is required."
},
naming: {
course: "Course",
section: "Section",
module: "Module",
stage: "Stage",
question: "Question",
learner: "Learner",
reviewer: "Reviewer",
assignment: "Assignment"
}
});Notes:
- Autosave notices are emitted through
notificationscallbacks passed toHandbookLmsLearningWorkspace. - If no external notification callbacks are provided, autosave notices are suppressed by default.
- Manual save/submit notifications still work through the existing notification pathways.
Semver policy
MAJOR: Breaking API or schema contract changes.MINOR: Backward-compatible API additions.PATCH: Bug fixes and documentation-only updates.
Publishing
This package is published to npm using the workflow at .github/workflows/publish-handbook-lms.yml.
Local development
- Build compiled outputs:
npm run build --workspace @beanchain/handbook-lms - Typecheck package only:
npm run typecheck --workspace @beanchain/handbook-lms
Peer dependencies
react@mui/material@mui/icons-material@hello-pangea/dnd@uiw/react-md-editorzod
