tomatophp/filament-alerts
Send notifications to users with reusable templates, multiple channels, and full logs. Built for Filament with native notifications, database and email drivers, FCM support, and custom drivers, types, and actions.
Architecture fit. tomatophp/filament-alerts is a Filament-panel plugin, not a general Laravel notification package. It installs as a service provider + facade (FilamentAlerts), registers a panel plugin (FilamentAlertsPlugin::make()), and expects consuming models to adopt an InteractsWithNotifications trait alongside Laravel's Notifiable. Internally it is a thin orchestration layer over an abstract Driver class with concrete DatabaseDriver, EmailDriver, and pluggable Discord/FCM drivers, fronted by two Eloquent resources (templates and delivery logs) and backed by queue jobs (NotifyDatabaseJob, etc.). That is a sound, conventional shape for a Filament add-on and it fits cleanly if — and only if — our admin surface is Filament-first and our delivery needs are modest. It is a poor fit for an API-first or headless product where the operator UI is incidental.
Integration feasibility. Ceremony is low: composer require, a one-shot filament-alerts:install command, one plugin line in the panel provider, one trait on User, and a queue worker. That is roughly a half-day to first send. The package is unusually generous with extension seams for its size: custom drivers, types, actions, and user types register through the facade; resource tables/forms/infolists/actions expose static register() hooks; and every resource class is swappable via config. Crucially, those hooks mean we can customize without forking, which materially reduces the maintenance exposure that a 83-star, 0-dependent package would otherwise imply. The hideNotificationsResources() toggle also lets us consume the delivery engine while keeping our own UI, which is the integration mode I would favor.
Technical risk. The risks are concentrated in coupling and in what the package does not do:
Filament\Tables\Actions\* and Filament\Infolists\*, which are Filament v3 namespaces; Filament v4 relocated actions to Filament\Actions. This is the single largest risk — a Filament major upgrade becomes a blocking dependency, not an incremental task.sendUse() macro is attached to Filament\Notifications\Notification, a vendor class. Any macro-name collision or upstream refactor of that class breaks delivery silently at runtime, not at install time.boot(). That ordering interacts badly with config caching, package discovery, and test bootstrapping; registrations can vanish in a console or test context without an obvious failure.["find" => "replace"] arrays. There is no Blade rendering, no escaping contract, no localization/translation variants, no conditional blocks, and no template versioning — so an in-flight template edit changes the content of notifications already queued.modelId, iterates $model::all(). On a real user table this is a memory and queue-flood hazard with no chunking, throttling, or batching in evidence.php artisan config:cache.TPM verdict: viable as a UI and delivery-log accelerator behind our own abstraction, not as a system of record. Treat the low composite score as "spike before commit," not "reject."
Key questions for the maintainer / spike:
composer.json constraints — PHP, Laravel, and Filament (^3.x only)?sendUse() guarded against macro collision, and is it registered idempotently?Notification object serialized into the job payload, and is it stable across Filament patch releases?Stack fit. This assumes Laravel 10/11/12-class runtime, a Filament v3 panel, a relational database, and a working queue (Redis preferred; database acceptable for pilot volumes). Email requires a transport; FCM requires HTTPS service-worker registration and device-token storage, which is a separate front-end workstream — plan for it explicitly rather than treating it as a driver config toggle.
Migration path. Two scenarios:
App\Contracts\NotificationDispatcher with send(TemplateKey $key, Notifiable $recipient, array $vars) and implement it over FilamentAlerts::notify(). Package classes never appear in domain code.Notifiable + Mail): do not migrate existing flows in the first phase. Run the package in parallel for new flows only, with the logs table as the comparison surface. Migrating live transactional email onto a package with an unversioned template model is a backward step unless the template builder is the actual requirement.Compatibility. Build a short matrix before committing: Filament version (hard pin), Laravel version, PHP version, DB engine (MySQL vs Postgres for JSON/data columns), queue driver, mail transport, and FCM SDK version. Pin the package to an exact tag; use cweagans/composer-patches rather than a fork for small fixes, and only fork if a Filament v4 migration becomes necessary.
Build-vs-buy calibration. Laravel Notifiable + a notifications table + a modest Filament resource delivers roughly 60–70% of this in about two weeks of engineering — minus the visual template builder, the delivery log UI, and FCM. That is the real value being purchased. Frame the decision as "two weeks of build avoided for one vendor dependency assumed," and make it explicit.
Sequencing:
Maintenance. Assume we own the upgrade path, not the vendor. Budget recurring effort each Filament major (namespace churn) and each Laravel major (queue/serialization changes). The abstraction layer is the mitigation that keeps a future rip-and-replace to days rather than quarters. Track the upstream repo for Filament v4 activity; if none appears within our upgrade window, plan the fork.
Support. Community-only: GitHub issues, no SLA, small community means low-probability long-tail answers. We need an internal runbook covering install, template key registry, driver registration, queue recovery, and log pruning. The hook-based customization means the runbook is short — but it must exist before the second engineer touches it.
Scaling. Three distinct bottlenecks:
Cap any single send with an explicit chunked dispatcher in our wrapper; never call the package's no-modelId path against a production user table.
Failure modes (ranked by likelihood × impact):
| Mode | Detection | Mitigation |
|---|---|---|
| Queue worker down — sends silently stall (all delivery is queued) | Queue depth / lag alert | Supervisor + alert on queue:monitor; health check |
Macro collision or Filament upgrade breaks sendUse() |
Runtime exception on send | Pin Filament; smoke test in CI |
Static registrations lost under config:cache / test bootstrap |
Missing drivers in dropdown | Integration test asserting registry contents |
| Template deleted or edited while notifications queued | Wrong/blank body in logs | Template versioning; soft-delete; FK guard |
| Duplicate sends on job retry | Log dedup check | Idempotency key in wrapper |
| SMTP credentials rotated in DB but config cached | Mail failures | Bypass config cache for mail; document |
| FCM token invalidation | Rising failure rate in logs | Scheduled token pruning |
| Log table bloat | Disk/report latency | Scheduled prune command |
Observability. Build a per-driver success/failure dashboard directly off the logs table on day one — it is the package's best feature and the cheapest operational control we get. Also alert on failed_jobs volume and queue age.
Security & compliance. Three items gate customer-facing rollout: (1) Filament policies on both resources — the sender UI is effectively a broadcast tool, so access is privileged; (2) SMTP credentials in the database are an admin-compromise vector, so prefer env-based transport and use the settings hub only in development; (3) notification logs contain message content and recipient identifiers, which makes them in-scope for GDPR retention limits — implement pruning with a documented window before the first customer send. No unsubscribe/opt-out mechanism is provided and none should be assumed; that is ours to build.
Ramp-up. A Filament-fluent developer reaches productive use in under a day; the driver/type/action registry and the static resource hooks are discoverable and follow Filament idioms. The non-obvious costs are the config-driven resource class overrides and the boot-order sensitivity of the registries — both belong in onboarding docs. Estimate one to two sprints from spike to hardened production for a single engineer, plus a front-end allocation if FCM is in scope.
How can I help you explore Laravel packages today?