H5P libraries
Needs review
Needs review: Tenant admins with h5p_library_install can still install libraries through the editor's Hub tab or a .h5p upload; only the /h5p/libraries and /h5p/content-type-cache routes are platform-only. Confirm this is intended.
H5P content types (Multiple Choice, Drag and Drop, Interactive Video and so on) are H5P libraries. The Courses → H5P libraries screen lists the libraries installed in the H5P service, and lets a platform administrator upload, restrict and delete them and refresh the list of content types available from the H5P Hub.
Creating and editing H5P content itself is covered in the creators guide.
How H5P is built
Section titled “How H5P is built”H5P runs in its own service so that its GPL code never mixes with the rest of ulams (ADR 0003):
| Part | What it does |
|---|---|
api/h5p (app key api-h5p) |
Node.js service built on Lumi’s h5p-nodejs-library. Serves the H5P player, editor, AJAX endpoints, library administration and a small REST API under /h5p/* on every API host. Owns the h5p schema in each tenant database and stores files in the tenant bucket. |
api/packages/h5p (h5p) |
Laravel package. A read-only model of the service’s h5p.contents table, the admin content list with usage counts (GET /api/admin/h5p/contents, DELETE /api/admin/h5p/unused), an HTTP client for server-to-server calls (upload, download, delete, orphan clean-up) and the H5P permissions. It never writes to the h5p schema. |
| admin and learner apps | Never load H5P code. They frame the service’s embed pages and talk to them with postMessage. |
The full service reference (environment variables, routes, embedding protocol, tenancy) is in the api/h5p README.
Libraries are shared by all academies
Section titled “Libraries are shared by all academies”All tenants use one library volume (/data/libraries in the image). Installing, updating or
deleting a library therefore affects every academy. Content, user state and results stay per
tenant (tenant database and bucket). In production the volume is a normal Docker volume of the h5p
service; see H5P service in production.
Because of this, the service only accepts library writes on the platform host (tenant id
default, api.localhost in development). The guard is the platformOnlyWrites middleware in
api/h5p/src/http/platformOnly.ts,
mounted in front of /h5p/libraries and /h5p/content-type-cache. On a tenant host,
POST, PATCH and DELETE on those routes answer 403 with
“H5P libraries are shared by all academies; install and update them on the platform.” GET
stays open, so tenant administrators can see the list.
The libraries screen
Section titled “The libraries screen”
The table shows, for each installed library:
- Title, with a runnable tag for content types (libraries a learner can play directly) and an addon tag for add-ons.
- Machine name and version (
major.minor.patch). - Instances: how many contents use it as the main library, plus how many use it as a dependency (shown in brackets).
- Dependents: how many other libraries depend on it.
- Restricted: a switch, enabled only for runnable libraries. A restricted content type can only
be used by users with
h5p_library_installorh5p_library_update. - Delete: enabled only when the service reports that the library can be deleted (nothing depends on it).
Users who may update libraries also see:
- Upload a library: a
.h5pfile sent toPOST /h5p/libraries(fieldfile). The result says how many libraries were installed and updated. - Update content type cache: refreshes the H5P Hub list (
POST /h5p/content-type-cache/update) and shows when it was last updated. The service also refreshes this cache in the background.
Ways to install content types
Section titled “Ways to install content types”-
From the platform admin panel: upload a library package on this screen.
-
From the H5P editor: users with
h5p_library_installorh5p_library_updatesee the H5P Hub in the content-type selector and can install from there (needsH5P_HUB_ENABLED=true, the default). -
By uploading content:
POST /h5p/contents/upload(the editor’s upload tab) installs every library inside the package when the caller may install libraries. -
From the command line, in the H5P container:
Terminal window docker compose exec h5p node dist/cli/seed.js --hub H5P.MultiChoice,H5P.DragQuestion
Seeding sample content: make h5p-seed
Section titled “Seeding sample content: make h5p-seed”make h5p-seed (in api/makefile) runs:
docker compose exec h5p node dist/cli/seed.js --samplesThe seeder runs as the system user and imports the curated sample packages (Image Hotspots, Drag
and Drop, Dialog Cards, Flashcards, Branching Scenario, Interactive Video, Multiple Choice, Course
Presentation, True/False, Fill in the Blanks, Memory Game). Importing a package also installs the
libraries it contains. make migrate-fresh and make refresh call h5p-seed at the end.
Useful options of seed.js:
| Option | Effect |
|---|---|
--samples [k1,k2] |
Import all curated samples or only the listed keys |
--list-samples |
Print the sample keys and exit |
--hub <A,B> |
Install these content types from the H5P Hub first |
--tenant <id> |
Tenant to import into; default default (the platform). A tenant’s id is its storage directory name, e.g. coffee_localhost |
--out <file> |
Also write the JSON report to a file |
Positional arguments are local .h5p files, directories or URLs. The exit code is 2 if any
item failed.
Permissions
Section titled “Permissions”All H5P permissions come from H5PPermissionsEnum and are granted to the admin role by
H5PPermissionSeeder. The H5P service reads them from GET /api/profile/me.
| Permission | Used for |
|---|---|
h5p_library_list |
Opening this screen (GET /h5p/libraries) |
h5p_library_read |
Reading one library |
h5p_library_upload, h5p_library_install |
Uploading a library package |
h5p_library_update |
The restricted switch; with h5p_library_install, Hub installs and using restricted types |
h5p_library_delete |
Deleting a library |
The menu entry also disappears when the H5P package is not installed or the
hideInMenu-CoursesH5ps setting is on. See Permissions.
Configuration
Section titled “Configuration”Laravel side (api/packages/h5p/src/config.php):
| Variable | Default | Purpose |
|---|---|---|
H5P_SERVICE_URL |
http://h5p:8080 |
Where Laravel reaches the service |
H5P_INTERNAL_TOKEN |
none | Shared secret for server-to-server calls (X-Internal-Token); must match the service |
H5P_SERVICE_TIMEOUT |
300 |
Seconds, for large uploads and exports |
Service side, the variables most relevant to libraries: H5P_HUB_ENABLED, H5P_LIBRARIES_PATH,
H5P_MAX_TOTAL_SIZE_MB (upload limit, default 256) and PLATFORM_HOSTS (hosts treated as the
platform). See Environment variables and the
api/h5p README.
Known limitations
Section titled “Known limitations”- Libraries are global. There is no per-academy set of content types; restricting a type restricts it everywhere.
- The service caches library metadata in Redis. After changing the library volume by hand, clear
the
h5p:lib:*keys. - No events or notifications are emitted for library changes.