A hands-on tour of the PhoenixKit notification system.
This page is the canonical example for how a module should send and manage notifications. Copy the patterns below into your own module.
The one rule: notifications are driven by the activity log
You never insert into phoenix_kit_notifications directly. Instead you log
a business activity with PhoenixKit.Activity.log/1, and core's activity hook
fans it out into a per-user notification automatically:
PhoenixKit.Activity.log(%{
action: "post.created", # "resource.verb"
module: "hello_world", # your module_key()
actor_uuid: actor.uuid, # who did it
target_uuid: recipient.uuid, # who should be notified
...
})A notification row is created only when target_uuid != actor_uuid — you
don't notify someone about their own action. Admins reading /admin/activity
get the audit trail; the target_uuid user gets the inbox notification.
What you'll see here
- Send a plain notification (the activity drives it).
- Send with custom display — override the icon / text / link via metadata.
- Read / manage — unread count, recent list, mark-seen, dismiss.
- Declare notification types from your module (see
notification_types/0inPhoenixKitHelloWorld) so users can mute them in their settings. - Live updates over PubSub via
PhoenixKit.Notifications.Events.subscribe/1.
Every core call is guarded with Code.ensure_loaded?/1 so the module compiles
and runs even on a host that doesn't ship the notifications/activity contexts.