Architecture in one screen
Conventions do the locating. Types do the explaining.
The router scans only conventional module controller folders, then reads native PHP attributes. Each request resolves a tenant before a model exists. In multi-tenant mode, that resolution selects credentials for a distinct database.
Why it stays simple
- One front controller and one dependency-free autoloader.
- One vanilla navigation file; the server still renders canonical HTML.
- One request-scoped container; tenant-bound services never survive the request.
- One fixed pipeline for rate limiting, CSRF, authorization, validation and headers.