Architecture

Architecture Overview

5 min read

Notifal 2.x / 3.x is organized as modules on top of shared infrastructure and domain layers. This page maps the moving parts so you know where to hook in or resolve services.

Start with Getting Started for Developers if you have not read the boot sequence yet.

High-level layout

notifal/
├── app/
│   ├── Bootstrap/Plugin.php          # init orchestration
│   ├── Core/                         # Container, AbstractServiceProvider, helpers
│   ├── Domain/                       # Tags, Settings (cross-cutting)
│   ├── Infrastructure/WordPress/     # Admin UI, hooks, migrations
│   ├── Modules/                      # Feature modules (OnPageNotification, Templates, Campaign, Forms, Ai)
│   └── Shared/                       # Admin list views, fields, toasts
└── build/                            # Compiled JS/CSS (enqueue these in production)

Notifal Pro adds notifal-pro/app/ with the same module pattern and bridges into base hooks (display rules, analytics, content source).

Module discovery

Plugin::boot_modules() scans:

app/Modules/*/ServiceProvider.php

Each provider extends Notifal\Core\Foundation\AbstractServiceProvider and defines:

PiecePurpose
protected static array $servicesClasses to instantiate via the container
protected const FILTER_HOOKOptional filter to add/remove services (per module)
boot()Optional early setup on the provider itself

Registration flow:

  1. Filter service list (if FILTER_HOOK is set)
  2. Provider boot()
  3. For each service: Container::get() , then register() / boot() on the instance

Example module filters:

ModuleService filter hook
On-page notificationsnotifal/onpage/services
Templatesnotifal/templates/services
Campaignsnotifal/campaign/services
Formsnotifal/forms/services
Ainotifal/ai/services
Tags domainnotifal/tags/services
Settings domainnotifal/settings/services
Global infrastructurenotifal/infrastructure/services

Dependency injection

notifal_app( string $class ) resolves singletons from Notifal\Core\Foundation\Container.

Typical usage:

  • Inside Notifal services (constructor injection via container)
  • In your extension code after notifal/initialized

Avoid new \Full\Namespace\Class() for Notifal services unless the class is documented as a value object or DTO.

Custom post types (CPT)

CPT slugPurpose
notifal_onpage_notifOn-page notification posts
notifal_templateNotification templates (HTML Builder, Block, Elementor)
notifal_campaignCampaigns
notifal_formForms identity, field definitions, emails, and integration secrets (@since 3.0.0)

Post type registration args are filterable:

FilterCPT
notifal/onpage_post_type/argsOn-page notifications
notifal/template_post_type/argsTemplates

Notification settings are stored in post meta on the notification CPT. Campaign settings use campaign post meta. Forms store fields and settings on the Form CPT.

On-page notification module (largest surface)

Under app/Modules/OnPageNotification/:

LayerResponsibility
Application/Services/Business logic: eligibility, save, tracking, display rules, content source
Infrastructure/WordPress/CPT, REST ApiRegistrar, repositories
Presentation/Admin views, frontend assets, API controllers

Frontend flow:

  1. JS calls GET /wp-json/notifal/v1/onpage/eligible
  2. EligibilityService + NotificationEligibilityChecker apply rules
  3. NotificationDataPreparer builds payload (filters apply here)
  4. JS tracks via POST /wp-json/notifal/v1/onpage/track

See REST API Reference and Hooks: Notifications and Eligibility.

Templates module

Handles template CRUD, HTML Builder sanitization, Elementor widgets, import/export, and preview routes.

Key integration filters: notifal/template/import/result, notifal/template/html/sanitize/before, notifal/templates/services.

See Hooks: Templates and Rendering.

Campaign module

Campaigns link notifications through campaign assignment meta. Schedule checks run in CampaignSettingsService and integrate with NotificationEligibilityChecker through notifal/campaign/schedule_check.

User-facing behavior: What Are Campaigns?.

Forms module (@since 3.0.0)

Under app/Modules/Forms/:

LayerResponsibility
Application/Services/Submit pipeline, validation, emails, integrations, field sync
Infrastructure/WordPress/notifal_form CPT, AJAX submit, repositories
Presentation/Admin Forms UI, submissions inbox, frontend assets

HTML templates own presentation. The Form CPT owns secrets and durable field definitions. Public submit uses WordPress AJAX with server-side integrity and spam checks.

See Hooks: Forms and Notifal Forms Overview.

AI module (@since 3.0.0)

Under app/Modules/Ai/:

LayerResponsibility
Application/Services/Connection, usage, generation bridge to notifal.com
Infrastructure/Gateway/Server-side HTTP client for hosted AI (credentials stay in PHP)
Presentation/Admin UI assets for Noti chat and the OnPage wizard

HTML Builder uses floating Noti chat (html_template). OnPage list uses the hosted wizard (onpage_notification). The browser never receives hosted AI credentials.

See Hooks: Hosted Notifal AI.

Tags domain

app/Domain/Tags/ is booted before modules because templates and notifications depend on tag resolution.

  • RegisterTags.php registers built-in tags on notifal/tag/register
  • TagManager resolves {tag} placeholders in content
  • REST: /wp-json/notifal/v1/tags, /wp-json/notifal/v1/dynamic-keys

See Hooks: Tags and Dynamic Data.

Admin UI building blocks

Shared admin UI lives in app/Shared/AdminUI/:

  • FieldRenderer , form controls used in notification and campaign editors
  • BaseListView , list tables for notifications, templates, campaigns

Extension points: notifal/admin/onpage/%s/before, notifal/admin/onpage/%s/%s/before (tab and section), plus field-level notifal/field/*/before/{id} actions.

See Hooks: Admin UI Extension.

  1. Architecture Overview (you are here)
  2. REST API Reference
  3. Hook Reference Hub