Skip to content

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

LearnStack

A shared platform for education businesses that teach live.

Development branch CI status

One foundation. Many ways to teach.

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; browser sign-in, enrolment, payments and live teaching are still ahead. See current status before trying the local scaffold.

What it does

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.

Where it is today

Phase 01, Phase 02a and Phase 02d are complete; Phase 02b is in progress. Phase 02d, the two-tenant walking skeleton, merged through PR #28 on 2026-10-11. In Phase 02b, P02b-0 through P02b-5 are complete, P02b-1–5 merged through PRs #29–#33, and P02b-6's realm and identity implementation is merged through PR #34; BFF sessions and phase exit remain P02b-7–8, so browser sign-in is not implemented. Packet state lives in the Phase 02b document's Status block; the roadmap lists every phase.

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, create-only provisioning defaults and semantic built-in seed verification 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, durable events/subscriber delivery, background jobs, the closed tenant bearer/AccountSite boundary and development realm reconciliation BFF sessions and phase-exit enforcement 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.

Quickstart

1. Prepare the tools

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

2. Bootstrap from the repository root

make hooks     # optional: install the repository Git hooks

Continue with the manual HTTPS prerequisites below, then run make demo. It creates missing private configuration and restores dependencies without changing Git hooks. make seed converges application data and the development identity realm without starting the API or web. Direct .NET Seeder remains data-only.

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. Both combined entries then await the same bounded development-realm reconciler. Older private files must explicitly add KEYCLOAK_WEB_CLIENT_SECRET; existing passwords/MFA and provider IDs are preserved. Prepare this secret before the first make dev import, and retain it across reruns. Older files also need explicit private permissions after verifying their ownership/type; Makefile creation does not repair existing files. The realm guide owns setup, refusal, safe secret recovery and qualification details.

3. Prepare local HTTPS and start the applications

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.local

Manually 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 demo

This 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.

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. Supply Authentication:Tenant:Issuer too: the canonical HTTPS tenant-realm URL, with loopback HTTP allowed only in Development. The development configuration defaults to http://localhost:8080/realms/learnstack; issuer configuration is validated without contacting Keycloak at startup. Credential-free public reads remain available when Keycloak is stopped. P02b-6 owns current realm issuance/ reconciliation qualification; browser sessions remain P02b-7.

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. See local setup and Compose documentation for troubleshooting.

Everyday commands

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.

How it fits together

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 Tenant API bearer boundary, real issuance and safe development realm reconciliation implemented; browser sessions remain P02b-7
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).

How this codebase defends itself

  • 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.

What is in the repository

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

Where to start

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)

Documentation layout

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.

Conventions

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.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages