Contributing¶
The maintainer reference for building, testing, and extending Moodle Playground.
Requirements
Node.js 18+, npm, Python 3, and Git. PHP 8.3 with pdo_sqlite is needed to build Moodle
bundles (make bundle, make prepare-dev, make prepare-all, make up) — the build
generates the install snapshot — and to run make up-local. The worker-only path
(make prepare) and make serve do not need PHP. Composer is only needed to build
Moodle 5.1+ bundles.
Common commands¶
npm install # Install dependencies
make prepare # Install deps + build the PHP worker (fast local iteration)
make prepare-dev # Worker + the default Moodle bundle
make prepare-all # Worker + all Moodle bundles (CI/release)
make bundle # Build the default branch bundle (override with BRANCH=...)
make bundle-all # Build all Moodle branch bundles
make serve # Start the dev server on http://localhost:8080
make up # Full build (all branches) + serve
make up-local # Run a native php -S Moodle for the selected branch
make up-local respects BRANCH=..., LOCAL_PORT=..., and LOCAL_PHP=..., and reuses the
patched checkout in .cache/moodle/<branch>. Local SQLite state is isolated per branch under
.cache/local/<branch>/, so switching branches does not reuse the same database or moodledata.
make up-local
BRANCH=main make up-local
BRANCH=MOODLE_500_STABLE LOCAL_PORT=8082 LOCAL_PHP=php83 make up-local
A local HTTP server is required
A Service Worker only registers on https or http://localhost. Opening index.html
from file:// will not work. Use make serve and visit http://localhost:8080.
Worker bundling¶
The PHP worker (php-worker.js) is bundled with esbuild into dist/php-worker.bundle.js.
This bundles all runtime dependencies (@php-wasm/web, @php-wasm/universal, and shared
modules) into a single ESM file loaded as a Web Worker. WASM and ICU data files are copied
to dist/ with content hashes.
The blueprint engine is bundled into this worker too — the step registry and PHP generators execute inside the bundled worker, not in the shell's main thread.
Rebuild after editing runtime or blueprint code
After changing anything under src/runtime/** or src/blueprint/**, run
npm run build-worker (or make build-worker). Otherwise the running app keeps using
the stale bundle — a new blueprint step fails with Unknown step type: <name>.
make test exercises the source directly, so it does not catch a missing rebuild.
When verifying in the browser, also clear the Service Worker caches (use the Reset
Playground button) because the SW caches the old bundle.
Generated assets¶
| Path | Description |
|---|---|
assets/moodle/ |
Prebuilt Moodle ZIP bundle (extracted into MEMFS at runtime) |
assets/moodle/snapshot/ |
Pre-built install snapshot (install.sq3) |
assets/manifests/ |
Bundle manifests |
dist/ |
esbuild output (worker bundle, WASM, ICU data) |
Do not hand-edit generated artifacts unless the task is specifically about the build output.
Project structure¶
src/
shell/main.js # Shell UI: toolbar, address bar, iframe host, logs
remote/main.js # Runtime host: registers the SW, hosts the scoped iframe
runtime/
bootstrap.js # Moodle bootstrap and install
php-loader.js # PHP instance creation (@php-wasm/web)
php-compat.js # WP Playground API compatibility layer
config-template.js # config.php generator
blueprint/ # Step-based blueprint system
parser.js # JSON / base64 / data-URL parsing
schema.js # Hand-written validator
constants.js # {{KEY}} placeholder substitution
resources.js # Named resource registry
resolver.js # Blueprint source resolution
executor.js # Sequential step runner
steps/ # Step handlers (filesystem, Moodle API, PR overlay, ...)
php/helpers.js # PHP code generators for Moodle API calls
shared/ # Shared utilities
patches/shared/ # Canonical shared build-time patches
patches/<branch>/ # Optional branch-specific source-root overrides
scripts/ # Build and utility scripts
assets/blueprints/ # Blueprint definitions, examples, and JSON schema
tests/ # Unit (node:test) and e2e (Playwright) tests
docs/ # This documentation site
See Architecture for how these layers fit together at runtime.
Tests¶
Unit tests use Node's built-in node:test (no framework). E2E tests use Playwright.
make test # Run all unit tests
make test-e2e # Run Playwright browser tests (Chromium + Firefox)
make lint # Run Biome on src/, tests/, scripts/
make format # Auto-fix lint and formatting issues
First-time e2e setup: npm run test:e2e:install. To target one browser, use
make test-e2e-chrome or make test-e2e-firefox.
Documentation¶
The documentation site is built with Zensical
and the Material theme. It is not plain MkDocs — do not run mkdocs serve/mkdocs build.
# Install docs dependencies (requirements-docs.txt contains exactly: zensical)
pip install -r requirements-docs.txt
# Preview locally with auto-reload
zensical serve
# Build the production site into site/
zensical build
Pages live under docs/ and the nav is defined in mkdocs.yml.
Adding a blueprint step¶
Steps are the units of blueprint provisioning. To add one:
- Add a handler in
src/blueprint/steps/— either in an existing module or a new file. A handler isasync (step, context) => { ... }; validate required fields and throw a clear error if they are missing. - Register the name by wiring the handler into
src/blueprint/steps/index.js(callregister("<stepName>", handler)from the module's register function). - Add the name to the schema enum in
assets/blueprints/blueprint-schema.jsonso the step validates. - Rebuild the worker with
npm run build-worker(the blueprint engine runs inside the bundled worker — see Worker bundling above). - Add a unit test under
tests/blueprint/and runmake test.
For PHP generated by a step, add the generator in src/blueprint/php/helpers.js. See the
Blueprint reference for the full list of existing steps.
Where internal notes live¶
This page is the contributor-facing reference. Deeper material — Architecture Decision Records (ADRs), SQLite/WASM migration notes, troubleshooting, and known issues — is linked from Internal notes.
AGENTS.md at the repository root is the authoritative guide for AI coding agents and the
specialist agent skills under .agents/skills/. Consult it for domain-deep conventions,
checklists, and known pitfalls before working in an unfamiliar area.