Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tomato Notifications Module Laravel Package

tomatophp/tomato-notifications-module

A Laravel notifications module for TomatoPHP apps that centralizes notification management, delivery, and templates, with admin-panel integration for configuring and tracking notifications without building the infrastructure from scratch.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by confirming the package fits your stack: tomato-notifications-module is part of the TomatoPHP admin ecosystem and expects a Filament-based panel plus the Tomato admin/auth scaffolding. On a bare Laravel app, install that foundation first — the module's resources, policies, and user menu integration assume it exists.

composer require tomatophp/tomato-notifications-module
php artisan vendor:publish --tag=tomato-notifications-config
php artisan vendor:publish --tag=tomato-notifications-migrations
php artisan migrate

If a publish tag is rejected, run php artisan vendor:publish interactively and pick the provider — tag names have shifted between TomatoPHP releases and are the most common first-run stumble.

Where to look first, in order:

  1. config/tomato-notifications.php — channel toggles, template/table names, queue settings, gateway credentials.
  2. The Filament resource(s) under src/Filament (or src/Resources) — this is the CRUD surface for notification templates and logs, and tells you the actual schema faster than the migrations do.
  3. The model for templates (NotificationsTemplate or similarly named) — inspect $fillable to learn the placeholder/variable convention and the lang column before writing any copy.
  4. The send-side service/action class — that's the API you'll call from your own code, not the Filament UI.

First use case to prove the wiring end-to-end: create a template in the admin panel with key welcome and a body containing one placeholder, send it from a tinker session or a queued job to a single user, then verify three things — a row in the template's log table, a row in Laravel's notifications table (if the database channel is on), and a rendered email. Getting all three confirms the template lookup, variable substitution, channel dispatch, and logging in one pass. If mail is queued, start a worker before testing or you'll chase a phantom bug.

Implementation Patterns

Template-first vs. class-first notifications. Keep marketing and transactional copy (welcome, password reset, invoice ready) in DB templates so non-developers can edit wording and translations. Keep notifications whose payload is structural — anything where a missing or renamed variable should be a compile-time-ish failure — as ordinary Laravel Notification classes. Mixing the two is fine; the mistake is templating a notification whose body is mostly data.

The send path. The canonical flow is: resolve a user or collection → hand the package the template key plus a key/value array of variables → it renders per recipient → dispatches across the configured channels → writes a log row. Wrap this in your own thin service so your app calls Notify::template('welcome', $user, [...]) rather than the package directly. That indirection is what saves you when a template key gets renamed or a channel is swapped.

Bulk and segmented sends. Chunk recipients (chunkById, ~500) inside a queued job; never loop in a controller. Set $tries, a backoff, and a failed() handler on the job. If you fan out to email or SMS, apply RateLimited or ThrottlesExceptions middleware on the job — provider rate limits are the usual cause of a 40-minute bulk send turning into a 4-hour one.

Queue hygiene. Implement ShouldQueue on anything that reaches mail or an external gateway, and use ->afterCommit() (or after_commit = true on the connection) so you don't notify users about records that a rolled-back transaction erased. Serialize user IDs, not Eloquent models, in job payloads — it keeps payloads small and avoids stale-state surprises.

Localization. Use one template row per lang and set the locale per recipient immediately before dispatch ($user->preferred_locale), not per batch. A batch that sets locale once will silently send everything in the last recipient's language.

Filament integration. Register the plugin in your panel provider; the database-notification bell in the top bar then reads from Laravel's notifications table. Mark-as-read and polling behavior come from Filament, not this package — so if read state looks wrong, look at your Notifiable model and the panel config before blaming the module.

Audit trail. Treat the log table as an append-only delivery record: add your own status, provider_message_id, and failed_reason columns via a separate migration rather than editing the published one. Extend the logging side with a listener on NotificationSent / NotificationFailed so both package-sent and class-sent notifications land in the same place.

Testing. Notification::fake() proves dispatch but not rendering — it will happily pass while your template renders {name} literally. Add one test per template that renders the body with real variables and asserts on the output; snapshot the rendered HTML to catch silent placeholder regressions across releases.

Gotchas and Tips

  • Placeholder syntax is the #1 support issue. {name}, {{name}}, and :name are all conventions used somewhere in the Laravel ecosystem; this package uses one and does not error on the others — it just renders them literally. Read the substitution code once and write a test with a deliberately missing key to see whether you get an empty string, the literal token, or an exception. That behavior is your contract.
  • Filament/Tomato version coupling. This module rides on the Tomato admin panel; Filament v3 vs v4 and tomato-admin version bounds are the usual composer conflict. Pin the whole Tomato set together and upgrade them as a unit rather than bumping one.
  • Migration collisions. Do not re-publish a notifications table migration — Laravel ships one, and a duplicate will either fail or quietly create a mismatched schema. Check what the publish tag actually emits before running migrate.
  • HTML vs. plain text. Template bodies are HTML. If your mail notification builds the message with line() instead of html(), recipients see raw tags and the bug looks like a template problem.
  • External channels need their own package. SMS/WhatsApp/push routes depend on separate TomatoPHP gateway packages plus credentials. Missing credentials typically fail at send time and land in the log table or failed_jobs, not at boot — so a "silent" non-delivery usually means an unconfigured gateway, not a broken module.
  • Debugging order. notification_logs → failed_jobs → storage/logs/laravel.log → Notification::fake() in a test. Fakes hide exactly the channel errors you're hunting, so remove the fake before concluding anything.
  • Cache rendered templates. In bulk sends the same template is fetched and rendered thousands of times. Cache by template ID + locale, and bust it from an observer on the template model's saved/deleted events — otherwise editors won't see their changes until the TTL expires, which reads as a bug.
  • Upgrade posture. v1.0.2 ships with a changelog link only — no published breaking changes, no new features documented, no deprecations. Treat it as a patch: pin ^1.0, run composer update tomatophp/tomato-notifications-module, re-publish any assets if the install uses them, and re-run your template-rendering tests. If you have production copy in DB templates, export the template rows before upgrading so a schema tweak in a patch release can't strand your content.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core