E-learning Courseware for School Managers
A gamified, bilingual LMS for school-governance training - fifteen SCORM courses, an in-house SCORM runtime, tracked progress and certificates.

- Role
- Frontend developer
- Year
- 2025 - 2026
- Stack
- SCORM 2004 / 1.2
- HTML5 courseware
- JavaScript
- Service Worker
- Web Audio
- Laravel 12
- Blade
- Alpine.js
- Tailwind CSS
- Playwright
- k6
- What I did
- Fifteen SCORM courses in two languages: one SCO per course, its own manifest, ~500 page frames
- SCO runtime library: API discovery across frames, suspend-data page map, buffered commits, quiz scoring and interactions
- Course player shell: paging, resume and restart, postMessage bridge to page frames, mute state, cache-busting
- Asset precache over a service worker with range requests, retries and slow-network fallback
- Web Audio background music and SFX that survive iOS autoplay rules
- Area release gate, course model and seeder, admin progress views, Pest and Playwright coverage
Overview
School managers in Hong Kong complete governance training across four areas - school-based management, human resources, finance, and development and policy. This platform delivers it as fifteen short animated courses with quizzes, tracks completion per learner, and issues certificates the school office can file.
Learners sign in, follow an island map of the four areas, and pick up any course where they left off, in English or Traditional Chinese. Each course is a SCORM package played inside the LMS, so progress, scores and completion are reported in a standard way. Administrators manage schools and learners, release new courses area by area and follow learner progress.
Learning as an island map
The dashboard is a map: four islands for the four areas, each with a completion badge and a Start button, a My Progress island, and a shortcut back to the last course. A release gate lets the team publish new courses in an area one at a time without touching the database.

Packaged the SCORM way
Each course is a self-contained SCORM 2004 package: an imsmanifest.xml declaring one organisation, one item and a single resource of scormType sco that points at index.html. The LMS parses the manifest for the launch URL and edition, mounts the SCO in a frame with autoplay and fullscreen allowed, and steps aside.
Because the LMS was built in-house rather than bought, we wrote the runtime too. A small JavaScript module exposes both API (SCORM 1.2) and API_1484_11 (SCORM 2004) on the host window, with the full error-code table, read-only elements and suspend-data byte limits from the spec - so any conformant package could run here, not just ours.

What the SCO tells the LMS
Inside the package, a helper library climbs the frame chain until it finds the API, calls Initialize, and reads cmi.suspend_data - a JSON map of which pages are done - so a learner resumes exactly where they stopped. It writes cmi.location and cmi.completion_status as pages advance, records each quiz answer as a cmi.interactions entry, sets cmi.score and cmi.success_status against an 80 percent pass mark, and commits at checkpoints rather than on a timer so slow connections are never spammed.
Every Commit is mirrored to a Laravel endpoint with a flat snapshot of the CMI data. The server merges completed pages into the stored map, recomputes progress so it can never go backwards, stamps completion once, and logs each step to its own channel - which is what drives the badges, certificates and admin reports.
Fast on a school network
Courses are heavy - video, narration, hundreds of illustrated frames - and the audience is on shared school Wi-Fi. A service worker fronts every course asset with a versioned cache and range-request support for seekable video. Before the first page renders, a precache pass warms the list for that course, shows a bilingual loading screen, warns when the network is slow, and retries up to five times.
Audio has its own rules on iOS: a child frame cannot unlock an AudioContext, so background music and sound effects play from the parent frame through Web Audio, and the resume call races a timeout so a blocked autoplay never hangs the boot sequence.

The admin side
System administrators see the numbers from the top down: managers who started, who completed at least one course, total logins, and a training-record report with date range and Excel export. School and manager lists handle assignment, locking after failed logins, and dummy accounts for testing. Certificates are generated on demand by overlaying the learner's name and bilingual course title on a PDF template.


Results
- 15
- Courses shipped as SCORM packages, in two languages
- ~500
- Course page frames built and versioned
- 600
- Concurrent learners in k6 load tests