A comprehensive collection of examples for integrating H5P interactive content into custom applications via self-hosted deployment.
H5P is an open-source framework for creating interactive content: quizzes, presentations, videos, games, and more. The easiest way to use H5P is through h5p.com (managed hosting), WordPress, Moodle, or other supported platforms.
This project is for developers who need to self-host H5P and integrate it with custom applications using simple HTTP APIs.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your Application β
β (Flask, FastAPI, PHP, .NET, Django, or any stack) β
β β
β 1. Create content β iframe to H5P /new β
β 2. Play content β iframe to H5P /play/{id} β
β 3. Receive scores β webhook from H5P server β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β HTTP API
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β H5P Server (Node.js) β
β β
β - Creates and edits H5P content β
β - Renders H5P player β
β - Sends xAPI scores via webhook β
β - Stores content in filesystem β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Option A: Using Docker (Recommended)
docker compose up -d h5p-server
# Server running at http://localhost:3000Option B: Using Node.js directly
cd h5p-server
npm install
npm start
# Server running at http://localhost:3000Important: The H5P server requires core library files (JavaScript, CSS) to function. These are included in
h5p-server/h5p/core/andh5p-server/h5p/editor/. When using Docker, the localh5p-server/h5p/directory is mounted into the container. If you see 404 errors for/h5p/core/js/*.jsfiles, ensure the volume mount is working correctly.
| Example | Language | Best For |
|---|---|---|
| python-flask | Python | Simple integration, beginners |
| python-fastapi | Python | Modern async applications |
| php | PHP | WordPress-like environments |
| dotnet | C# | Enterprise .NET applications |
| django | Python | Full-featured Django apps |
| lti-provider | Python | LMS integration (Moodle, Canvas) |
# Flask example
cd examples/python-flask
pip install flask
python app.py
# Open http://localhost:5000All examples follow the same simple pattern:
1. Your app opens popup/iframe to: H5P_SERVER/new?returnUrl=YOUR_CALLBACK
2. User creates content in H5P editor
3. H5P server saves and redirects to: YOUR_CALLBACK?contentId=123
4. Your app stores the contentId in your database
1. Your app embeds iframe: H5P_SERVER/play/{contentId}?userId={userId}&webhookUrl={yourWebhook}
2. User interacts with H5P content
3. H5P server sends xAPI score to your webhook (if provided) + postMessage to parent
4. Your app stores the grade
Note: The
webhookUrlparameter is optional. If not provided, xAPI events are only sent viapostMessageto the parent window (useful for iframe embedding).
{
"contentId": "abc123",
"userId": "demo-user",
"statement": {
"verb": { "id": "http://adlnet.gov/expapi/verbs/completed" },
"result": {
"score": { "raw": 8, "max": 10 },
"completion": true
}
}
}| Example | Description | Run Command |
|---|---|---|
| Flask | Minimal Python web app | python app.py |
| FastAPI | Async Python with Pydantic | uvicorn app:app |
| PHP | No-framework PHP | php -S localhost:5000 |
| .NET | ASP.NET Core minimal API | dotnet run |
Each simple example demonstrates:
- Content listing, creation, editing
- H5P player embedding
- Score webhook handling
- SQLite storage
The Django example includes:
- Reusable
django_h5pplugin - Sample LMS with courses and activities
- Grade tracking per user
- Template tags for easy embedding
The LTI provider allows external LMS platforms to:
- Launch H5P content via LTI 1.3
- Return grades to LMS gradebook
- Works with Moodle, Canvas, Blackboard, etc.
The @lumieducation/h5p-server npm package provides H5P's core functionality, and @lumieducation/h5p-express provides AJAX endpoints for the H5P client-side JavaScript. However, as the docs note:
The Express adapter does not include pages to create, edit, view, list or delete content!
Our h5p-server wraps these libraries into a ready-to-use service with user-facing routes:
| Base Library Provides | Our Server Adds |
|---|---|
/ajax - AJAX calls for H5P client JS |
/new - Editor page for new content |
/content - Serve content files |
/edit/:id - Editor page for existing content |
/libraries - Serve library files |
/play/:id - Player page with xAPI tracking |
/temp-files - Temporary uploads |
/api/content - List/delete content REST API |
/params - Content parameters |
returnUrl - Callback after save with contentId |
/download - H5P package export |
webhookUrl - POST xAPI scores to your app |
postMessage - xAPI events to parent window |
|
| Cross-origin iframe fixes | |
| Docker image with health checks |
The base library is the engine. Our server adds the user-facing routes and integration glue.
The Node.js H5P server exposes these endpoints:
| Endpoint | Method | Description |
|---|---|---|
/new |
GET | H5P editor for new content |
/edit/{id} |
GET | H5P editor for existing content |
/play/{id} |
GET | H5P player |
/api/content |
GET | List all content |
/api/content/{id} |
GET | Get content metadata |
/api/content/{id} |
DELETE | Delete content |
/health |
GET | Health check |
Query parameters:
returnUrl- Where to redirect after save (for /new, /edit)userId- User identifier for tracking (for /play)
h5p-integration-kit/
βββ h5p-server/ # Node.js H5P server (shared)
β βββ src/index.js # Express app
β βββ package.json
β βββ Dockerfile
β
βββ examples/
β βββ python-flask/ # ~150 lines Flask app
β βββ python-fastapi/ # ~200 lines FastAPI app
β βββ php/ # ~300 lines vanilla PHP
β βββ dotnet/ # ~300 lines .NET 8 app
β βββ django/ # Full Django example
β β βββ django_h5p/ # Reusable plugin
β β βββ sample_lms/ # Demo LMS
β βββ lti-provider/ # LTI 1.3 tool provider
β
βββ docker-compose.yml # Run H5P server with Docker
βββ README.md # This file
βββ LICENSE # MIT License
For most users, h5p.com or platform plugins (WordPress, Moodle) are the best choiceβthey're maintained, supported, and easy to set up.
Self-hosting makes sense when you need:
- Custom tech stack integration β embed H5P in Flask, Django, .NET, or any framework
- Full infrastructure control β run on your own servers, air-gapped environments, or specific cloud providers
- Deep customization β modify the server, add custom xAPI handling, or integrate with existing auth systems
- Docker/container deployments β include H5P as a service in your stack
- H5P Server: Node.js 18+ (uses @lumieducation/h5p-server)
- Examples: See individual README files
# Start H5P server with Docker
docker compose up -d h5p-server
# Check it's running
curl http://localhost:3000/health
# Should return: {"status":"ok","service":"h5p-server"}
# For external access (e.g., LTI), set the public URL:
H5P_BASE_URL=https://your-public-url.com docker compose up -d h5p-serverVolume Configuration:
The docker-compose.yml mounts the local h5p-server/h5p/ directory by default. This includes:
core/- H5P core JavaScript and CSS fileseditor/- H5P editor fileslibraries/- Downloaded H5P content type librariescontent/- Your saved H5P content
For production, you may want to use a named Docker volume instead (see comments in docker-compose.yml).
Production Setup with Named Volume:
When using a separate data directory or named Docker volume (recommended for production), you must initialize it with the core H5P files before starting the container:
# Create data directory and copy required files
mkdir -p /var/lib/h5p-data
cp -r h5p-server/h5p/core /var/lib/h5p-data/
cp -r h5p-server/h5p/editor /var/lib/h5p-data/
chown -R 1001:1001 /var/lib/h5p-data # Match container user
# Run with volume mount
docker run -d --name h5p-server \
-p 3000:3000 \
-v /var/lib/h5p-data:/data/h5p \
-e H5P_BASE_URL=https://your-domain.com \
h5p-server:latestWithout the core/ and editor/ directories in your data volume, you'll get 404 errors for /h5p/core/js/*.js and /h5p/editor/ files, and the H5P editor/player won't load.
Troubleshooting:
If you get EACCES: permission denied errors when switching between Docker and local Node.js:
# Fix ownership to match your local user
sudo chown -R $USER:$USER h5p-server/h5p/The docker-compose.yml uses user: "${UID}:${GID}" to run as your host user, avoiding permission conflicts with mounted volumes.
This project uses a dual-license structure:
| Component | License | Why |
|---|---|---|
H5P Server (h5p-server/) |
GPL-3.0 | Uses @lumieducation/h5p-server which is GPL-licensed |
Examples (examples/) |
MIT | Communicate via HTTP API only, no GPL code incorporated |
The HTTP API boundary between components means you can:
- Run the H5P server as a Docker container (GPL applies to server code)
- Use the examples in proprietary projects (MIT allows this)
This project stands on the shoulders of giants:
- H5P - The incredible open-source framework for creating interactive content
- Lumi Education - The excellent Node.js implementation of H5P
- Claude Code - AI-assisted development
Contributions welcome! Areas of interest:
- Additional language examples (Ruby, Go, Java)
- LTI 1.1 support
- Deep linking implementation
- More H5P content type examples
- @lumieducation/h5p-server - The H5P Node.js library we use
- tunapanda/h5p-standalone - H5P player only (no editor)
- h5p/h5p-php-library - Official H5P PHP library
Made with care for the education community