Build SCORM 2004 e-learning packages from Markdown lessons and YAML quizzes using a static-site generator workflow.
An AI agent for working with Schorm, a CLI-driven static-site generator that transforms Markdown lessons, YAML quizzes, and Handlebars templates into SCORM 2004 compliant e-learning packages.
This agent helps you develop, extend, and troubleshoot Schorm - a "Hugo for SCORM" tool that enables developers to create LMS-ready e-learning content using familiar web development workflows. The agent understands Schorm's architecture, conventions, and SCORM 2004 requirements.
When working with Schorm, always follow these design principles:
1. **Commands delegate to core modules** - Command files in `src/commands/` are thin orchestrators; business logic lives in `src/core/`
2. **Deterministic builds** - Same input files must produce identical output with no side effects
3. **File-first, CLI-first** - All content lives in files (Markdown, YAML), no databases
4. **TypeScript interfaces as contracts** - `src/core/course-model.ts` defines canonical data structures
5. **ES modules with `.js` extensions** - Always use `.js` extensions in TypeScript imports (Node16 module resolution)
```
Source Files → Course Model → Template Render → SCORM Manifest → ZIP Package
```
```
build/
*.html # Lesson/quiz HTML files
imsmanifest.xml # SCORM manifest
assets/ # Theme CSS + runtime JS
media/ # Copied media files
```
1. **Create the command file** in `src/commands/your-command.ts`
2. **Export a Commander Command object**:
```typescript
import { Command } from 'commander';
export const yourCommand = new Command('your-command')
.description('What your command does')
.action(async () => {
// Delegate to core modules
});
```
3. **Import and register** in `src/cli.ts`:
```typescript
import { yourCommand } from './commands/your-command.js';
program.addCommand(yourCommand);
```
4. **Implement business logic** in appropriate `src/core/` module
5. **Add integration tests** in `test/commands/your-command.test.ts` using this pattern:
```typescript
const projectPath = path.join(TEST_DIR, 'test-project');
execSync(`${CLI_PATH} init test-project`, { cwd: TEST_DIR });
execSync(`${CLI_PATH} your-command`, { cwd: projectPath });
// Assert expected output
```
The course model (`src/core/course-model.ts`) defines these core structures:
**Load a course**:
```typescript
import { loadCourse } from '../core/course-model.js';
const course = loadCourse(coursePath);
```
All content items must have unique `id` and descriptive `title` fields.
Use `src/core/markdown.ts` for lesson parsing:
```typescript
import { parseLesson, findLessons } from '../core/markdown.js';
// Parse single lesson
const lesson = parseLesson('content/intro.md');
// Find all lessons recursively
const lessons = findLessons('content/');
```
**Frontmatter requirements**:
```yaml
---
id: lesson-intro
title: Introduction to SCORM
module: module-01
duration: 10
objectives:
- Understand SCORM basics
- Create first package
---
```
Schorm uses Handlebars via `src/core/templates.ts`:
```typescript
import { TemplateEngine } from '../core/templates.js';
const engine = new TemplateEngine(themePath);
await engine.loadPartials();
engine.registerHelpers();
const html = engine.render('lesson.html', {
lesson: lessonData,
course: courseData
});
```
**Template locations**:
Create `imsmanifest.xml` using `src/core/manifest.ts`:
```typescript
import { generateManifest } from '../core/manifest.js';
const manifest = generateManifest({
identifier: course.id,
title: course.title,
version: course.version,
organizations: [/* hierarchical structure */],
resources: [/* physical files */]
});
```
**Organizations** define learning hierarchy (modules/items).
**Resources** list physical files (HTML, media, assets).
```typescript
if (!course.id) {
throw new Error('Course must have an id');
}
```
```typescript
try {
await buildCore(options);
} catch (error) {
console.error('Build failed:', error.message);
process.exit(1);
}
```
```bash
npm run dev -- init my-project
npm run build
node bin/schorm build
npm test # Run once
npm run test:watch # Watch mode
```
Tests in `test/commands/` invoke the real CLI binary:
```typescript
import { execSync } from 'child_process';
import path from 'path';
import fs from 'fs';
const TEST_DIR = path.join(process.cwd(), 'test-output');
const CLI_PATH = path.join(process.cwd(), 'bin', 'schorm');
describe('your command', () => {
afterEach(() => {
// Clean up test-output/
});
it('should do expected thing', () => {
const projectPath = path.join(TEST_DIR, 'test-proj');
// Create test project
execSync(`${CLI_PATH} init test-proj`, { cwd: TEST_DIR });
// Modify files as needed
fs.writeFileSync(
path.join(projectPath, 'content', 'test.md'),
'---\nid: test\ntitle: Test\n---\n# Content'
);
// Run command
execSync(`${CLI_PATH} your-command`, { cwd: projectPath });
// Assert output
expect(fs.existsSync(path.join(projectPath, 'build', 'expected.html'))).toBe(true);
});
});
```
Focus on these SCORM 2004 4th Edition data model elements:
`theme-default/assets/schorm-runtime.js` provides:
- `init()` - Initialize SCORM session
- `setValue(key, value)` - Set data model element
- `getValue(key)` - Read data model element
- `commit()` - Persist data to LMS
- `terminate()` - End SCORM session
This file must be copied to build output as a static asset. The preview server injects a mock SCORM API for local testing.
```yaml
id: course-001
title: My E-Learning Course
version: "1.0"
modules:
- id: module-01
title: Introduction
items:
- lesson-01
- quiz-01
```
```yaml
---
id: lesson-intro
title: Getting Started
module: module-01
duration: 15
objectives:
- Learn the basics
- Complete first activity
---
Your Markdown content here.
```
```yaml
id: quiz-01
title: Chapter 1 Quiz
module: module-01
questions:
- id: q1
text: What is SCORM?
type: multiple_choice
options:
- Shareable Content Object Reference Model
- Simple Content Organization Model
- Standard Course Object Repository
correct_answer: 0
```
```yaml
scorm_version: "2004-4th"
theme: "theme"
```
For deeper architectural details, consult:
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/schorm-scorm-generator/raw