Skip to content

Next-gen: javaabu/notifications v1.0 #15

Open

Description

@n4ff4h

Notifications toolkit: a BaseNotification that formats one message for every channel, database notification views and a latest-notifications component, model associations, icons and redirects, branded mail, optional translatable and Reverb.

Package: javaabu/notifications · Target: v1.0 · Wave: 3
Depends on: javaabu/permissions, javaabu/forms, @javaabu/forms, javaabu/manifest
Optional: javaabu/translatable, laravel/reverb

Built to the next-gen general rules: CI with test and coverage badges, full docs for people and agents, Laravel Boost guideline and skill, Javaabu codestyle, PHP 8.4 / Laravel 12+ (Laravel packages) or TypeScript (JS packages), Dhivehi and RTL, Blade and Inertia React for views, overridable controllers and policies with javaabu/permissions.

Checklist

Developed by an agent orchestrated from the Javaabu next-gen plan. Cross-package requests go in the dependency's repo with the cross-package label.

Activity

  1. added
    next-genNext-gen Javaabu packages
    epicTracks a whole package
    on Nov 4, 2026
  2. n4ff4h commented on Nov 5, 2026

    @n4ff4h
    CollaboratorAuthor

    Implementation plan

    Built like javaabu/exports v2 (the reference for routes, overridable controllers, views in both stacks, Reverb with a polling fallback), on Laravel's own notification system rather than beside it.

    Architecture

    • BaseNotification (extends Illuminate\Notifications\Notification, implements sms-notifications' SmsNotification). A notification defines message(object $notifiable): NotificationMessage once. The base class turns it into toMail() (branded MailMessage), toArray()/toDatabase(), toBroadcast(), toFcm() (when laravel-notification-channels/fcm is installed) and toSms() (through javaabu/sms-notifications, which this package requires). Per-channel tweaks go on the message (->sms('…'), ->mail(fn (MailMessage $mail) => …), ->fcm(fn …)), or by overriding toMail() etc. as usual.
    • Channels from preferences: via() takes the notification's channels ($channels, default from config), drops the ones the notifiable can't receive (no email, no phone number, FCM not installed), then asks the notifiable: a HasNotificationPreferences contract with a ready trait storing opt-outs in a JSON column. $required_channels can't be opted out of. Channel aliases sms and fcm map to the real channel classes.
    • NotificationMessage: title, body (lines), action text/URL, icon, colour, thumbnail, the subject model, extra data. Notification types can set defaults ($icon, $color).
    • Database model Javaabu\Notifications\Models\DatabaseNotification (extends Laravel's, configurable), with a subject morph (new nullable columns, written by a database channel that extends Laravel's). A Notifiable trait replaces Laravel's so the relation, broadcast channel and preferences use the package's model. Click redirects: GET notifications/{id} marks it read and redirects to the action URL (or the subject's notificationUrl()).
    • Routes by Route::notifications([...guard, prefix, name, middleware, controller]): index, latest (bell JSON), read/unread, read-all, destroy, the redirect. One controller, overridable from config, the macro or the container. JSON for expectsJson(), Blade or Inertia pages otherwise (notifications.views).
    • Policy and permissions: users always manage their own notifications (no permission needed, so the bell works for everyone). view_others_notifications and delete_others_notifications are registered with javaabu/permissions for support/admin use. Overridable via config or Gate::policy().
    • Views: Blade with javaabu/forms v2 components (notifications::notifications.index, <x-notifications::bell>, and a small notifications::bell script through manifest); Inertia React with @javaabu/forms and Onu (notifications::Notifications/Index, NotificationBell built on Onu's NotificationCenter, useNotifications hook), shipped as @javaabu/notifications through javaabu/manifest.
    • Live updates: when Reverb is installed (or forced), Laravel's broadcast channel sends new notifications on a private channel per notifiable, authorized for multi-auth; the bell listens through window.Echo. Otherwise it polls the latest route. Same switch as exports (notifications.broadcasting.enabled = auto/true/false).
    • Branded mail: notifications.mail.branding (name, URL, logo, colours, footer). A javaabu mail theme rendered from that config, and <x-mail::branded>, a message layout with the logo and footer. dir="rtl" and right-aligned text for Dhivehi. Apps' Mailables can use the same theme and layout.
    • Translatable (optional): the notifiable's locale (HasLocalePreference, or a locale attribute) is used for every channel. When javaabu/translatable is enabled, the locale is checked against its active languages, and database notifications store the title/body in every active language, so the bell and the page show the reader's current language. Detected through Support\Translations, as the contract describes.

    Order of work

    1. Foundations: PHP 8.4 / Laravel 12+, CI matrix, coverage and codestyle #1 foundations (skeleton, composer, Pint, CI matrix + Pint + JS + a no-translatable leg + a "no javaabu/helpers" check, badges)
    2. BaseNotification: one definition, every channel #2 BaseNotification, NotificationMessage, preferences, SMS and FCM
    3. Model associations, icons, colours, thumbnails and click redirects #3 subject morph, icons, colours, thumbnails, redirect
    4. Overridable controllers, policies and default permissions (RBAC, multi-auth) #12 routes, controller, policy, permissions, two guards
    5. Database notification views and controller #4 pages, Latest notifications component #5 bell, Blade (javaabu/forms) and Inertia React (@javaabu/forms) views #11 both stacks
    6. Live notifications with Reverb (optional) #7 Reverb and polling
    7. Branded mail #6 branded mail
    8. Optional javaabu/translatable support #13 translatable
    9. Dhivehi localization and RTL #10 Dhivehi and RTL, Documentation for people and agents #8 docs, Laravel Boost guideline and skill #9 Boost

    Decisions / open questions

    • The view namespace is notifications, shared with Laravel's own notifications::email. The package never ships email.blade.php, so Laravel's stays in place.
    • javaabu/stencil isn't used: the only form is a two-field filter, which doesn't meet the "larger forms" bar.
    • FCM is optional (suggest) because its channel brings in the Firebase SDK. SMS is required, since javaabu/sms-notifications has no dependencies beyond illuminate/support.
    • No notification-preferences page in v1: the API and storage are in place for apps (and a later version) to build one.
  3. n4ff4h commented on Nov 5, 2026

    @n4ff4h
    CollaboratorAuthor

    Final summary: javaabu/notifications v1.0 is done on main

    Every next-gen issue is closed except #14 (registering with docs.javaabu.com, for you). CI is green on every job: PHP 8.4/8.5 × Laravel 12/13 × lowest/stable, Pint, the React and Blade-script job (typecheck and Vitest), a leg without translatable, FCM and Reverb, and a check that javaabu/helpers and javaabu/settings ^1 aren't production dependencies. 78 PHPUnit tests and 16 Vitest tests.

    What was built

    • BaseNotification: one definition, every channel #2 BaseNotification: a notification defines message() once (NotificationMessage: title, lines, action, icon, colour, thumbnail, subject, data, plus per-channel sms(), mail(), fcm()), and gets toMail() (branded), toDatabase()/toArray(), toBroadcast(), toFcm() (laravel-notification-channels/fcm, optional) and toSms() (through javaabu/sms-notifications' configured driver). via() keeps the listed channels the notifiable has a route for and hasn't turned off (HasNotificationPreferences, with the ManagesNotificationPreferences JSON-column trait; * and per-type keys). notifications.required_channels can't be turned off. Every channel is built in the notifiable's locale (HasLocalePreference or a locale attribute).
    • Model associations, icons, colours, thumbnails and click redirects #3 Associations and redirects: a subject morph (new nullable columns, written by a database channel that extends Laravel's), NotificationSubject::notificationUrl()/notificationThumbnail() fallbacks, icons (Onu semantic names), colours mapped to Onu tones, and notifications.show, which marks a notification read and redirects.
    • Overridable controllers, policies and default permissions (RBAC, multi-auth) #12 Routes, controller, RBAC: Route::notifications([guard, prefix, name, middleware, controller]); one overridable controller (config, macro option or container); NotificationPolicy (a permissions ResourcePolicy) overridable from config, permissions.policies or Gate::policy(). Everyone manages their own notifications without a permission; view_others_notifications and delete_others_notifications are registered for support roles. Tested on two guards, including a user and an admin with the same id.
    • Database notification views and controller #4, Latest notifications component #5, Blade (javaabu/forms) and Inertia React (@javaabu/forms) views #11 Pages and bell in both stacks: the Blade page (javaabu/forms v2) and <x-notifications::bell> with a manifest script. The React page notifications::Notifications/Index (@javaabu/forms and Onu), plus NotificationBell (Onu's NotificationCenter), NotificationListItem and useNotifications, all as @javaabu/notifications through javaabu/manifest. BellData::make() supplies Inertia's shared props.
    • Live notifications with Reverb (optional) #7 Live updates: with Reverb installed (or forced), new database notifications broadcast on notifications.{type}.{id}, authorized for that notifiable whatever its guard. The bell and page listen with Echo, or poll latest otherwise (skipped while the tab is hidden).
    • Branded mail #6 Branded mail: notifications.mail.branding (name, URL, logo, colours, footer); a theme rendered from those colours; <x-mail::branded> (HTML and text) for notification mail and Mailables. Mail is right to left for RTL locales.
    • Optional javaabu/translatable support #13 Translatable (optional): with javaabu/translatable on, notifiable locales are checked against its active languages, and database notifications store their title, body and action text in every active language so each reader sees their own. Detected in Support\Translations. Tested with it, switched off, and in CI without it installed.
    • Dhivehi localization and RTL #10 Dhivehi and RTL: every string is in lang/en.json and lang/dv.json, kept in sync by a test. Views use logical utilities only (also tested), and the tests use Thaana.
    • Documentation for people and agents #8, Laravel Boost guideline and skill #9 Docs and AI: 20 Docusaurus pages (every option, API and view, Blade and React side by side), llms.txt, AGENTS.md/CLAUDE.md, the Boost guideline, and the javaabu-notifications skill with a common-mistakes reference.

    Decisions / intentionally out of scope

    • Notifiables use Javaabu\Notifications\Concerns\Notifiable instead of Laravel's trait (same API, the package's model, a guard-safe broadcast channel).
    • The view namespace is notifications, shared with Laravel's own notifications::email. The package never ships email.blade.php.
    • No javaabu/stencil form: the only form is a two-field filter.
    • No notification-preferences page in v1. The API and storage are there (label(), preferenceKey(), setNotificationPreference()).
    • FCM is optional (it brings in the Firebase SDK). SMS is required, since sms-notifications only depends on illuminate/support.
    • Mail uses physical CSS with an RTL swap, because email clients ignore logical properties.
    • Blade icons go through <x-forms::icon>, whose icon set is smaller than Onu's. The icon partial can be overridden.

    Cross-package

    For you

    1. Codecov: uploads fail with "Token required"; make CODECOV_TOKEN available to this repo (org secret). The badge stays blank until then.
    2. Docs: register the package on docs.javaabu.com (Register with Javaabu Docs (docs.javaabu.com) #14).
    3. Dhivehi review: have a native speaker check the table in docs/advanced-usage/dhivehi-and-rtl.md (for example ނޯޓިފިކޭޝަން vs. އެންގުން, and the mail greeting).
    4. Release: once forms v2, manifest, permissions v3 and translatable v3 are on Packagist, drop the VCS repositories (and the github: npm dev dependency on @javaabu/forms), then tag v1.0.0 and submit to Packagist.
  4. n4ff4h commented on Nov 6, 2026

    @n4ff4h
    CollaboratorAuthor

    Follow-up from Javaabu/manifest#17 (719f99c): the React page and components' npm packages (@javaabu/forms, @javaabu/onu, React, @inertiajs/react) are now declared with for: 'pages'. The Blade script imports none of them, so a Blade app's manifest:check only asks for Vite. Tests cover a Blade-only app and an Inertia app; the docs, Boost skill and changelog are updated. CI is green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicTracks a whole packagenext-genNext-gen Javaabu packages

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions