Architecture overview
How the platform is put together — Laravel 13 + Filament v4, three panels, the services layer, observers, jobs and the request lifecycle.
Architecture overview
The platform is a single Laravel application that serves four surfaces — three Filament panels, a REST/mobile API, and the public marketing + docs site — over one MySQL database with tenant isolation at the model layer. This page is the map; the detailed pages are linked at the bottom.
Who this is for
Developers and hosting admins who will maintain, extend or debug the install.
Difficulty: Medium · Time: about 10 minutes · Prerequisites: familiarity with Laravel and a checkout of the repository.
The stack
| Concern | Choice |
|---|---|
| Framework | Laravel 13 (PHP 8.4+) |
| Admin UI | Filament v4 (Livewire under the hood) |
| Database | MySQL (leadhub locally; any MySQL 8-compatible server in production) |
| Queue | sync locally; database + worker in production — see Queues, jobs & scheduler |
| Scheduler | Laravel's scheduler driven by one cron entry (php artisan schedule:run every minute) |
| Deployment target | Shared cPanel/Apache hosting (subdomain install), not Docker |
Surfaces and panel providers
| Surface | Path | Provider / entry |
|---|---|---|
| Tenant CRM | /admin |
App\Providers\Filament\AdminPanelProvider (panel id admin) |
| Super Admin | /super-admin |
App\Providers\Filament\SuperAdminPanelProvider (id super-admin) |
| Agency (Meta Ops) | /agency |
App\Providers\Filament\AgencyPanelProvider (id agency) |
| REST API | /api/v1 |
API-key authenticated controllers (routes/api.php) |
| Mobile API | /api/v1/mobile |
Device-token authenticated controllers (routes/api.php) |
| Marketing + docs | /, /pricing, /docs |
Blade controllers/views |
| OpenAPI viewer | /api/docs |
Api\ApiDocsController |
Request lifecycle
flowchart LR
A[HTTP request] --> B[bootstrap/app.php middleware]
B --> C{Surface}
C -->|/admin /super-admin /agency| D[Filament panel provider]
C -->|/api/v1| E[REST controller + api.key middleware]
C -->|/api/v1/mobile| F[Mobile controller + DeviceAuthenticate]
D --> G[Service layer app/Services]
E --> G
F --> G
G --> H[Eloquent models + BelongsToTenant global scope]
H --> I[(MySQL)]
bootstrap/app.php is the single wiring point: middleware groups, alias list (tenant.scope, api.key, portal.auth, login.lockout, sa.ip.allowlist, Spatie role/permission), CSRF exceptions for token-authenticated inbound endpoints, and the API/mobile error-envelope renderers.
Key middleware on every web request
App\Http\Middleware\TrustProxies— trusts nothing by default; opt in viaTRUSTED_PROXIES.App\Http\Middleware\ResolveTenant— resolves and binds the workspace for web requests.App\Http\Middleware\TrackUserSession,SetLocale,SecurityHeaders.
API and mobile requests bind their tenant from the credential instead — see Authentication.
The services layer
Business logic lives in app/Services/ and is called by controllers, jobs and Filament actions — controllers stay thin.
Representative services:
| Area | Services |
|---|---|
| Lead capture | Services\LeadSources\*, ConnectorRegistry, MetaConnector, MetaLeadFormService |
| Messaging | Services\WhatsApp\* (MetaCloudWhatsAppProvider, template/message/media services) |
| Billing | Services\CommercialBilling\*, TenantSubscriptionState, EntitlementService |
| Onboarding | guided-onboarding services backing business_onboarding + steps |
| Mobile | MobileApp\MobileAppConfig, push via PushService |
| AI | Services\Ai\AiChatClient (provider openai/deepseek) |
Model observers
Registered observers in app/Observers/ keep cross-cutting behavior out of controllers:
LeadObserver— lead lifecycle side effects.LeadAuditObserver— audit trail for lead changes.LeadWebhookObserver— outbound webhook triggers.MeetingBookingObserver— appointment/booking side effects.TenantCacheFlushObserver— clears tenant-keyed caches when a tenant changes.TenantProvisioningObserver— provisions a new workspace's defaults.
Jobs and scheduler
Background work is queued (app/Jobs/) and driven by routes/console.php — inbound webhook processing (ProcessInboundWebhook), push delivery (SendPushToUser), email sequences, AI SDR, Meta ops, billing lifecycle, retention/erasure, backups. The full, exact schedule is documented in Queues, jobs & scheduler.
Tenancy, auth and RBAC in one line each
- Multi-tenancy:
BelongsToTenantglobal scope, fail-closed;app('current_tenant')binds the workspace — see Multi-tenancy & isolation. - Auth: web session / API keys / device tokens — see Authentication.
- RBAC: Spatie roles +
HasRolePermissionsprefixes; nav tiers are display-only — see Roles & permissions (RBAC).
Conventions to follow when extending
- New tenant-owned table → add
tenant_id, use theBelongsToTenanttrait on the model, and a composite unique index (tenant_id+ natural key). - New Filament resource → set
protected static string $permissionPrefix = '…'anduse HasRolePermissions. - New background task → add the job class and one
Schedule::line inroutes/console.phpwith->withoutOverlapping(10)and->onFailure($logFailure('…')). - New inbound webhook → token/signature verified, CSRF-exempt path registered in
bootstrap/app.php, idempotency key enforced, failure recorded — see Webhooks (inbound). - Docs: every nav slug in
App\Support\DocsNavmust have a matching file underresources/docs/— the nav tree is the single source of truth for the information architecture.
Related guides
Was this page helpful?
Thanks — noted. ✦