ulams is a headless LMS: a Laravel 13 API built from vendored packages, two small Node services
(H5P and PDF), an Astro reference frontend with a framework-free SDK and UI catalogue, a React admin
panel and a legacy React learner app, all in one Yarn and Turborepo monorepo. Start with the
architecture, then set up the stack.
Architecture Services, hosts, request flow, workers and backing services. API packages Every package in api/packages, grouped by domain. Tenancy Database, bucket and keys per tenant; --domain; content origin; isolation tests. Authentication Passport tokens, roles, demo login, LTI launches, how clients keep tokens. API reference Swagger UI, the generated spec, SDK types and the endpoint index.
Generative UI Page documents, bindings, validation and fallbacks; AG-UI streaming to come.
Testing PHPUnit suites, Vitest, Playwright, integration tests. Debugging Logs, Horizon, the database, the services. CI What runs on every pull request.
Non-negotiables
LMS entities are changed through domain services, never by writing tables directly.
Every new endpoint gets a tenant isolation test; learner-facing UI meets WCAG 2.2 AA.
Uploaded content is untrusted input; third-party package code runs only on the content origin.
H5P stays in its isolated GPL service; no @lumieducation/* imports in MIT code.
Do not use or depend on escolalms/recommender.
Existing tests and linters stay green; H5P and SCORM behaviour does not change by accident.
Generated reference pages (packages , permissions ,
settings , environment variables ,
endpoints , events ,
artisan commands , scheduled jobs ,
UI catalogue ) are rebuilt from the repository on every docs build.
Decisions are in Decisions ; contributing rules in Contributing .