Awn Awn
Back to Awn
Documentation menu — Architecture
Start / Architecture
Version
1.0
Last verified
2026-08-09

Architecture

app/{Enums,Extensions,Plugins,Site,Themes}/
Modules/{Admin,Charity,Core,Site}/
plugins/{ContactForm,Events,Fundraising,KaramBanner}/
resources/views/themes/{karam,najda}/

Themes/plugins depend on stable application contracts and tenant context. Themes do not import plugins; current plugins do not import one another.

Discovery

ThemeRegistry iterates ThemeKey::cases() and reads resources/views/themes/{slug}/theme.json. PluginRegistry iterates PluginKey::cases(), reads plugin.json, and resolves the statically mapped driver. PluginServiceProvider registers plugin.{slug} views and package routes. Catalog rows are snapshots and cannot discover code.

Public request

  1. organization.route populates CurrentOrganization.
  2. Published delivery requires active organization and published site; signed preview skips that publication gate.
  3. CMS queries hide drafts outside preview.
  4. PluginPageResolver tries an enabled plugin page before exact CMS slug lookup.
  5. Plugin navigation merges with CMS navigation.
  6. ThemeResolver resolves assignment or configured default.
  7. PluginRenderer renders all three slots by priority.
  8. The static enum-backed theme view renders the response.

Every theme receives $organization, $page, $pluginPage, $navigationPages, $isPreview, $theme, and $pluginSlots.

Management surfaces

Organization requests resolve a tenant, then PluginDashboardResolver and PluginDashboardWidgetResolver use effective tenant plugins. Super Admin requests use super.admin, which establishes tenant bypass; PluginSuperAdminPageResolver and PluginSuperAdminWidgetResolver use only global installed/active state. Neither Super Admin nor organization UI is rendered by a theme.

State

Public and organization contributions require allowlisted, installed, globally active, tenant-enabled, and compatible state. Super Admin contributions require only allowlisted, installed, and globally active state. These states are independent. Theme activation normalizes settings, makes one assignment active, and invalidates theme/plugin caches.

Install validates definitions, requires core migrations, runs package migrations and declared seeders, synchronizes catalog, marks installed/active, and invalidates affected caches. Organization configuration is separate.

Ordering and validation

Slot priorities are 0..1000, default 100; lower first, slug breaks ties. Definition validation rejects duplicate organization/Super Admin IDs and routes, missing routes, settings collisions, middleware/scope mismatches, duplicate public page IDs/normalized patterns, and plugin routes without plugin.{slug}.. Enable validation also rejects CMS slug collisions. Runtime resolvers fail closed when global or tenant availability changes.

Organization navigation has two extension layers. PluginDashboardResolver::groupsForOrganization() groups each plugin's top-level management destinations into one sidebar submenu. PluginDashboardWidgetResolver renders ordered summary widgets from enabled plugins implementing ContributesDashboardWidgets.

Super Admin navigation mirrors that shape through PluginSuperAdminPageResolver::groupsForPlatform(), while PluginSuperAdminWidgetResolver renders global widgets on admin.dashboard.