Skip to content

Architecture & Domain Model

This page is the map. It explains which moving parts exist, where requests enter, and how the core school entities relate — read it before the other System Internals pages.

KoAkademy is a modular monolith. One Laravel 13 application serves everything — admin panel, portals, public pages, and API — running on PHP 8.5. The supported production image uses FrankenPHP behind Caddy in the default single-node Swarm topology; long-lived application and queue workers must not leak mutable state across requests or jobs.

The production container images are multi-stage builds (docker/Dockerfile and docker/Dockerfile.franken) that install Composer dependencies, generate Wayfinder routes, build Vite assets, and package the runtime processes.

Supporting services are external: PostgreSQL (primary data), Redis (cache, sessions, queues), Gotenberg (PDF rendering), and S3-compatible object storage (uploads via media library).

EntryPath / guardImplementationAudience
Administration panel/admin (web guard)Filament 5 panel, SPA modeAdministrative staff
Admin workspace/administrators/*Inertia + React pagesAdministrative staff
Faculty portalfaculty routesInertia + React pagesTeaching staff
Student portalstudent routesInertia + React pagesStudents
Public pages/, /enrollment*, /setup, /docs, /changelog, /id-card/verify/{token}Inertia + React pagesEveryone
API/api/* (auth:sanctum)Laravel API routesIntegrations

Two things to know about this table:

  1. There is no separate admin application. The Filament panel and the three React portals share the same models, policies, and services.
  2. A second Filament panel (portal, /portal) exists but is intentionally a stub — the real student/faculty experiences are the Inertia/React portals. Do not build new features into the stub panel.

The domain is school administration. The principal entities and their relationships:

  • School — the tenant. Most records carry a school_id (see Multi-school tenancy below).
  • Student — a person enrolled or enrollable; holds documents, signature, clearances, medical records (module), and a generated institutional identifier (configurable format).
  • Faculty — teaching staff; assigned to classes and departments.
  • Course / Department / Program — the curriculum structure students enroll into. Senior High is modeled as its own cluster (SHS strands and SHS students).
  • Class — a taught section of a subject: schedule, room, capacity, assigned faculty, roster. Timetable conflict detection guards scheduling.
  • StudentEnrollment — a student’s enrollment for an academic period; moves through the verification pipeline (see Enrollment engine).
  • ClassEnrollment / SubjectEnrollment — the join between an enrollment and the classes/subjects it includes; grades live at this level and follow a submit → finalize → verify workflow.
  • Transactions / Invoices — assessments, payments, and statements of account issued to students.
  • Events, Announcements, NotificationTemplates — calendar, broadcast messaging, and templated notifications.

Around these sit cross-cutting records: User accounts with roles, activity-log entries, media attachments, export jobs, and enrollment-policy records.

Tenancy is lightweight and school-scoped — there is no stancl/tenancy package and no database-per-tenant:

  • A SchoolScope global scope applies school_id filtering to tenant-owned models.
  • TenantContext resolves the active school from the session (current_school_id), falling back to the user’s default school; super administrators bypass the scope.
  • SetTenantContext middleware establishes the context per request; the /organizations API (list, current, switch, store, clear-context) powers the organization switcher in the UI.

When you add a tenant-owned model, give it a school_id and the global scope — never filter by school manually in controllers.

PlaneStoreNotes
Relational dataPostgreSQLSingle source of truth; SQLite supported for dev/tests
Cache / sessions / queuesRedisSeparate redis and redis-pdf queue connections (see Queues & PDF)
FilesS3-compatible storagespatie/laravel-medialibrary; required in production
SearchScout, database driver by defaultMeilisearch optional
SettingsDatabase via spatie/laravel-settingsGeneralSetting holds institution-wide configuration
Feature flagsDatabase via Laravel PennantSee Modules & feature flags
PathContents
app/Services, models, middleware, jobs, policies, Filament panel, enrollment engine (app/Enrollment/)
Modules/Six optional domain modules (Laravel Modules)
routes/Web route files split per audience, api.php, channels.php
resources/js/Inertia React pages and components (~184 pages)
database/Migrations, factories, seeders
docker/Production image, supervisord variants, runtime scripts
docs/This documentation site

Reading guide for the rest of this section

Section titled “Reading guide for the rest of this section”
  1. Auth, roles & permissions — who can do what, and how sign-in is hardened.
  2. Modules & feature flags — how optional functionality is composed and toggled.
  3. The enrollment engine — the deepest subsystem: pipeline, policies, blueprints.
  4. Queues, jobs & PDF — background work and document generation.
  5. Frontend architecture — Inertia, React, Wayfinder, and the design system.
  6. Extending the enrollment engine — contracts for custom rules and actions.