A shared platform for education businesses that teach live.
Product vision · Current status · Quickstart · Architecture · Documentation
LearnStack is being built as a white-label platform for multi-branch education businesses. A language school, a yoga studio and a music school share one codebase and database schema, while keeping their own content, branding and tenant boundaries. The product design supports a platform subdomain and optional custom domains; a business does not need to bring its own domain.
The endorsed direction adds an optional Course Marketplace alongside those sites: shared discovery, platform checkout, commission and institution payouts. Its pilot plan and direction ADR are Proposed; payment, seller operations and marketplace delivery are still ahead.
The difference between those businesses lives in tenant customization data. The platform vision defines the scope and the boundary between customization and capabilities that require platform code.
Under active development. The backend foundation and Education schema are implemented. The first working browser experience is the current milestone; authentication, enrolment, payments and live teaching are still ahead. See current status before trying the local scaffold.
The product vision connects discovery, course content and live teaching in one place. The planned surfaces serve the people on each side of that experience:
| Surface | Who it serves | Intended experience |
|---|---|---|
| Public site | Visitors and prospective learners | Discover a school, browse its catalog and explore its content. |
| Admin Studio | Institution staff and instructors | Author content, manage people and organize teaching. |
| Learner portal | Enrolled learners | Work through lessons, track progress and join live sessions. |
| Optional Course Marketplace | Learners and participating institutions | Shared discovery and central checkout; endorsed target, architecture approval pending. |
The public catalog, course and lesson pages are implemented. Studio and learner portal remain scaffolds; the status below separates delivered work from remaining product and validation obligations.
Built for different ways of teaching. Content types and level taxonomies already have a validated customization model. The wider design covers page blocks, lesson items, rules, custom fields and notification templates; their delivery is tracked in the roadmap. Institutions and their branches follow the Tenant / Organization model.
Phase 01, Phase 02a and Phase 02d are complete. Phase 02d is merged through PR #28 on 2026-10-11. P02b-0's entry audit is complete. P02b-1 is complete and merged through PR #29 on 2026-10-12. Its merge closeout records transactional event production, enforcement, completed reviews and final CI verification under Accepted ADR-0057. P02b-2's revised package and ADR-0046 are Accepted. Steps 1–2 completed both review rounds; Step 3 implements hosted dispatch and observation, with both independent review rounds complete. Its delivery record owns its runtime evidence. Step 4 enforcement and local closeout are complete; all four steps completed both independent review rounds. CI and merge status live in the delivery record. P02d-1 is complete and merged: Education domain, schema and isolation proofs. P02d-2's decision package and ADR-0050/0051 are Accepted as of 2026-10-02, with four implementation steps. Step 1 implements the access policy, exact definition/locale readers, text-card metadata validation and seed verification queries. Both Step 1 review rounds passed. Step 2 adds locale/branding writers and JSON audit redaction; both review rounds passed. Step 3 adds Education writers; both review rounds and the focused fix review passed. Step 4 completes convergent seed execution after both review rounds. P02d-2 is complete and merged through PR #23 on 2026-10-02; the merge closeout records verification. P02d-3 read internals are implemented; the decision package is Accepted — 2026-10-02, with Step 1 implemented and both review rounds passed. Step 2 implements batched definition reads; both review rounds passed. Step 3 adds generation caching and scope-safe bypass; both review rounds passed. P02d-3 is complete and merged through PR #24 on 2026-10-03; its merge closeout records final verification. P02d-4 is complete and merged through PR #25 on 2026-10-08; its merge closeout records final verification. Its four steps deliver the read-only host boundary, anonymous site/Education GET/HEAD reads and OpenAPI/SDK/CI controls. Every step completed both review rounds; final fix verification and all six real required CI jobs pass. The sixth required OpenAPI check is active, with all other live protection settings preserved. Trusted server rendering is delivered by P02d-5. P02d-6 implements localized catalog/course/lesson pages, ordered text fields, safe themes and metadata; its product closeout records automated verification/reviews and scoped browser/VoiceOver observations. The original P02d-6 implementation is complete. ADR-0055 remediation delivers single-bootstrap admission and passing production replacement proofs; all three steps completed both independent review rounds, and the Step 3 record owns completed Step 3 reviews, verified fixes and delivery evidence. P02d-6 is complete and merged through PR #27 on 2026-10-10; its merge closeout records final verification. P02d-7's demo, Lighthouse and phase-exit decision package and ADR-0056 were approved on 2026-10-11. All four steps completed both independent review rounds. The shared demo, genericity fences and seeded browser/Lighthouse proof pass real CI; the seventh required context is active. The Step 4 record owns CI enforcement, reviews and the positive phase-exit verdict. PR #28 is merged; the merge closeout owns final verification. P02b-0 and P02b-1 are complete; P02b-2 producer dispatch and enforcement are locally complete, with both independent review rounds complete for all four steps; the Step 4 record above owns CI/merge status. Consumer delivery remains P02b-3. The P02d-4 decision package is Accepted — 2026-10-03. All four implementation steps and their review loops are complete. P02d-5 supplies trusted server rendering; P02d-6 supplies public page consumers and P02d-7 the two-host browser demo.
| Area | Delivered now | Next milestone |
|---|---|---|
| Tenancy | Tenant provisioning, organizations, locales, typed settings/branding reads, host resolution and database isolation | User membership and permissions in Phase 03 |
| Customization | Content types, level taxonomies, exact-definition and generation-cached batched display readers, text-card metadata validation and tenant-authored seeds | Remaining authoring capabilities across Phases 04–08a |
| Audit | Classified write path and transactional durability for business changes | Operational hardening in Phase 11 |
| Education | Course and Lesson aggregates, translations, protected-content policy, scoped authoring commands, complete demo seeds and isolated public GET/HEAD reads | Full versioned curriculum in Phase 05 |
| API foundation | Error contracts, validation, tenancy, concurrency, observability, transactional event production and hosted producer dispatch with production-census enforcement (all four P02b-2 steps and both review rounds locally complete) | Authentication and durable event consumption in Phase 02b |
| Frontend | Native TLS ingress, live locale entry, trusted server caller, localized catalog/course/lesson pages, safe themes, accessibility controls/manual smoke and generated typed SDK | Full renderer/Studio and Playwright Test/axe in Phase 06 |
Four modules contain domain implementations: Tenancy, Customization, Audit and Education. Identity, Content and Media remain scaffolded.
The subsequent product milestones are CMS and media (04), the full course catalog (05), renderer and Studio (06), enrolment and progress (07), assessment and notifications (08a), scheduling (08b), live classroom (08c), and billing (09). The roadmap dependency map owns the order: 02d runs before 02b, despite the filenames.
Use Docker with Compose V2, Git, Make, Bash, Python 3, curl and OpenSSL (the TLS test fixtures require its CLI), plus:
| Tool | Repository requirement |
|---|---|
| .NET SDK | 10.0.112 with the roll-forward policy in backend/global.json |
| Node.js | >=22.23.1, as declared in frontend/package.json |
| pnpm | 9.12.3, pinned in frontend/package.json |
make hooks # optional: install the repository Git hooksContinue with the manual HTTPS prerequisites below, then run make demo. It
creates missing private configuration and restores dependencies without changing
Git hooks. make seed remains available for infrastructure/database-only use.
The seed provisions demo-english and demo-yoga, their organizations and host
mappings, enabled locales, distinct branding, built-in and tenant-authored definitions,
and eight scoped courses, ten lessons and twenty-seven translations. It uses the
ordinary authoring pipeline and verifies completed acts before skipping them on rerun.
SeedData owns the complete inventory.
The demo prepares a missing private 32-byte hop secret in the ignored root .env.
Existing values and optional projections must agree; they are not reset.
Install mkcert using its official instructions. Run its trust step yourself, then create the local leaf certificate:
mkcert -install
mkdir -p .data/tls
mkcert -cert-file .data/tls/public.pem -key-file .data/tls/public-key.pem \
localhost demo-english.learnstack.local demo-yoga.learnstack.localManually map the two seeded names to 127.0.0.1 in your hosts file. Repository
commands never edit that file or install trust. Keep the CA private key local;
only the ignored leaf/key paths belong in .env.
make demoThis foreground command restores pinned dependencies, starts the selected default
stack, waits for PostgreSQL before migrations, retains both Keycloak realm gates,
converges the seed and builds/starts the production API and native HTTPS web.
Readiness includes actual seeded lesson content; nine seed-derived URLs are printed.
Ctrl+C joins its owned API/web processes and preserves local infrastructure/data.
Use make down to stop infrastructure explicitly. A second demo invocation or a
foreign listener is refused; no foreign process is killed. If a hard kill leaves
.data/demo.lock, confirm the earlier process tree has stopped before removing
that lock manually. Missing/stale configuration or TLS is refused without reset.
Local demo database validation accepts only Host, Port, Database,
Username and Password, with case-insensitive keys. Supported aliases are
Server for Host; User Name, Userid, User Id and Uid for Username;
and Pwd and Psw for Password. Single- or double-quoted values preserve
whitespace and semicolons; double the matching quote to escape it. Duplicate
canonical fields and unsupported keys are refused. Host must be localhost or
127.0.0.1; port defaults to 5432 and must resolve to 5432. Role, password and
database must match the root configuration. This is the closed local demo
grammar, not general Npgsql connection-string support;
demo-database.mjs owns validation.
For separate development/watch terminals, retain make public-api and
make public-web. The CI lifecycle uses an isolated checkout/project and disposable
configuration through make demo DEMO_MODE=ci. Install its locked managed browser
first with cd frontend && pnpm exec playwright install --with-deps chromium.
The CI mode requires a fresh checkout configuration and artifact directory; use
local make demo for an existing workstation. The
Step 4 record
owns actual CI and protection receipts.
Readiness is http://127.0.0.1:5080/healthz for the API and
https://localhost:3000/api/healthz for the web listener. pnpm dev/start also use
this launcher. Both processes read the same private root source; a web .env.local
projection is optional and must match. No shell evaluates the values. Ordinary
no-hop API startup remains supported outside this paired renderer recipe; supply
both ConnectionStrings:Default (learnstack_app) and
ConnectionStrings:OutboxDispatcher (learnstack_outbox_admin). The mandatory
API worker verifies dispatcher connectivity at startup.
P02d-5 is complete: ingress, visitor budgets and public entry. The web
bootstraps the captured host through the API, redirects using enabled/default
locales and refuses unavailable scope. The server caller enforces no-store,
deadline/body limits and the closed authenticated hop. All four steps completed
both independent review rounds and fix verification. Source fences, the no-skip
test runner and real-API production HTML/RSC proofs pass. The
remediation and closeout record
owns current review/CI evidence. P02d-6 implements public pages;
P02d-7 supplies make demo and the seeded browser/Lighthouse proof. See
local setup and
Compose documentation for troubleshooting.
| Command | Purpose |
|---|---|
make help |
List available tasks. |
make demo |
Build/start the seeded production sites; Ctrl+C preserves local data. |
make dev |
Start the default local infrastructure. |
make migrate |
Apply platform and module migration chains. |
make test |
Restore dependencies and run backend and frontend suites; Docker is required. |
make lint |
Check backend formatting and frontend lint rules. |
make down |
Stop infrastructure while preserving its data volumes. |
The service inventory and optional gated profile live in
infra/compose/README.md.
A modular monolith: one ASP.NET Core host, explicit module boundaries and a
PostgreSQL database with a DbContext per module. One Next.js application holds the
three product surfaces. See the
technical architecture and
cross-module contracts.
| Layer | Choice | Current scope |
|---|---|---|
| Backend | .NET 10 · ASP.NET Core · EF Core · MediatR | Foundation and four domain modules implemented |
| Database | PostgreSQL 18 | Migrations, tenant / organization RLS and integration proofs |
| Frontend | Next.js 15 · React 19 · TypeScript | App/UI scaffolds; generated SDK and injected transport implemented |
| Observability | OpenTelemetry · Serilog → OTLP | Cross-cutting backend instrumentation implemented |
| Identity | Keycloak | Local realms configured; application authentication belongs to Phase 02b |
| Storage and search | SeaweedFS · PostgreSQL full-text search | Selected architecture; feature delivery belongs to Phases 04–05 |
| Live classroom | LiveKit through a provider adapter | Planned in Phase 08c, starting with Cloud and retaining a self-hosted path |
Infrastructure grows against explicit triggers. The running foundation uses
InProcessEventBus, InMemoryCacheService, ConfigurationSecretProvider and
NullEntitlementProvider. Adapter ownership and activation conditions live in
Infrastructure Stack Standards and
ADR-0035.
Deployment wiring is distinct from product readiness. Development and SaaS
have current backend wiring. Dedicated, SelfHostedOnline and
SelfHostedAirGapped are prepared seams pending
Phase 11.
LearnStack Hub is the separate operator
control plane. Its boundary is explicit: it stores tenant metadata, never tenant
content, and communication goes through named adapters
(ADR-0034).
- Isolation reaches the database. Tenant context, EF query filters and PostgreSQL
RLS work together. Isolation tests run as
learnstack_app, the same non-bypass role used by the API. Database standard. - Required business audit records commit with their changes. The business transaction owns durability; unclassified operations fail closed. Audit write path.
- Architecture claims have executable checks. Module boundaries, isolation conventions and documentation claims are checked against a named test catalogue.
- Verification includes failure cases. The suites exercise planted violations and mutations as well as successful paths. CI rejects skipped backend tests; the workflow defines the current checks.
backend/
src/ API, shared kernel, infrastructure and domain modules
tests/ Unit, architecture, contract and integration suites
analyzers/ LearnStack Roslyn analyzers
frontend/
apps/web/ Public catalog, course and lesson pages
Admin Studio and learner portal scaffolds
packages/ Shared config, UI and generated API SDK
infra/ Compose stack and service configuration
scripts/ Seed and verification helpers
docs/ Architecture, decisions, standards, roadmap and module specs
| Your question | Start here |
|---|---|
| What are we building, and for whom? | Platform vision · MVP scope |
| What works today, and what comes next? | Roadmap · Current phase |
| How do I contribute? | Contributing · Working agreement · Engineering standards |
| Why was a decision made? | ADR index |
| How are institutions isolated? | Tenant isolation · Tenancy module |
| How does customization work? | Customization model · Module spec |
| How are courses and lessons modeled? | Education module |
| How is the audit trail built? | Audit subsystem · Audit module |
| What belongs in the Hub? | Hub architecture · Deployment models |
| What does a term mean here? | Glossary |
Every architecture document — browse by topic
Strategy and shape · 01 Platform Vision · 02 Domain Model · 03 Module Boundaries · 04 Technical Architecture · 05 MVP Scope · 06 Extension Model · 11 Extension Points · 19 MVP Vertical Slice
Platform substrate · 09 Tenant Isolation · 10 Cross-Module Contracts · 15 Events and Outbox · 28 Platform Tenant + Organization · 31 Audit Subsystem · 32 Tenant Customization Model · 33 Cross-Cutting Concerns
Product surfaces · 12 Localization · 13 Identity and Authentication · 14 Frontend Architecture · 16 Media Pipeline · 17 Page Builder · 20 Search · 21 Feature Flags and Entitlements · 23 Data Protection (KVKK / GDPR)
Live classroom · 07 In-App Live Classroom · 08 Cost Model · 18 WebRTC Build vs Adopt
Hub, deployment and edge · 22 Custom Domains · 24 LearnStack Hub · 25 Deployment Models · 26 Hybrid License Model · 27 Custom Domain + TLS · 29 Dapr Integration · 30 API Gateway (APISIX)
| Directory | Purpose |
|---|---|
docs/architecture/ |
Product and system concepts; browse the complete index above. |
docs/decisions/ |
Architectural decisions, their context and consequences. |
docs/standards/ |
Engineering rules and their enforcement status. |
docs/roadmap/ |
Dependency-ordered phases, decision gates and delivery records. |
docs/modules/ |
Module contracts, permission matrices and audit coverage. |
Documentation is English; diagrams use Mermaid with a text fallback. Commits follow Conventional Commits. The glossary, ADRs, standards and roadmap each own their respective facts; other documents link to those sources. See Contributing, the documentation standard and review standard before opening a pull request.