Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

payload-notifications

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

payload-notifications

Generic notification infrastructure for Payload CMS with email, in-app, and external callback channels.

latest
Source
npmnpm
Version
0.1.10
Version published
Maintainers
1
Created
Source

payload-notifications

Multi-channel notification infrastructure for Payload CMS with document subscriptions and live messages.

npm version License: MIT

Overview

Payload has no built-in way to notify users about events. This plugin provides a server-side notify() / subscribe() / getSubscribers() API that you wire into your own hooks, endpoints, and workflows. A single notify() call can store an in-app notification, send an email, and fire an external callback -- each channel independent and optional. Everything is user-scoped with strict access control.

Features

  • Multi-channel delivery -- in-app, email, and external callbacks from a single notify() call. Per-user preferences control which channels are active.
  • Document subscriptions -- users follow collections or globals. getSubscribers() returns follower IDs for fan-out. Supports auto-subscribe (e.g. on first comment) and manual follows.
  • Live messages -- template tokens (t.actor, t.document('title'), t.meta('key')) that resolve against fresh data at read time. Renamed users and updated titles are reflected in existing notifications.
  • External callback -- onNotify hook for pushing to Slack, webhooks, queues, or anything else.
  • Admin bell component -- optional popover UI with unread badge, mark-read, unsubscribe, and delete actions.

Installation

pnpm add payload-notifications

Usage

// payload.config.ts
import { buildConfig } from "payload";
import { notificationsPlugin } from "payload-notifications";

export default buildConfig({
  // ...
  plugins: [
    notificationsPlugin({
      email: {
        generateSubject: ({ notification }) =>
          `Notification: ${notification.event}`,
        generateHTML: ({ notification, recipient }) =>
          `<p>Hi ${recipient.displayName}, ${notification.message}</p>`,
      },
    }),
  ],
});

Sending notifications

import { notify } from "payload-notifications";

await notify(req, {
  recipient: user.id,
  event: "comment.created",
  actor: commenter.id,
  message: "Someone replied to your post",
  documentReference: { entity: "collection", slug: "posts", id: post.id },
});

Subscriptions and fan-out

import {
  subscribe,
  getSubscribers,
  notify,
  createLiveMessage,
} from "payload-notifications";

const docRef = { entity: "collection", slug: "posts", id: post.id } as const;

await subscribe(req, { userId: commenter.id, documentReference: docRef });

const subscribers = await getSubscribers(req, docRef);
for (const recipientId of subscribers) {
  await notify(req, {
    recipient: recipientId,
    event: "comment.created",
    actor: commenter.id,
    message: createLiveMessage(
      (t) => t`${t.actor} commented on "${t.document("title")}"`,
    ),
    documentReference: docRef,
  });
}

Live messages

Static strings go stale when users rename themselves or documents get updated. Live messages store tokens that resolve against fresh data at read time:

import { notify, createLiveMessage } from "payload-notifications";

await notify(req, {
  recipient: user.id,
  event: "post.updated",
  actor: editor.id,
  message: createLiveMessage(
    (t) => t`${t.actor} edited "${t.document("title")}"`,
  ),
  documentReference: { entity: "collection", slug: "posts", id: post.id },
});
  • t.actor -- actor's display name (from admin.useAsTitle on the user collection)
  • t.document(field) -- a field from the referenced document
  • t.meta(key) -- a key from the notification's meta object

Options

OptionTypeDefaultDescription
emailNotificationEmailConfig--generateSubject and generateHTML functions. Omit to skip email.
onNotifyNotifactionCallback--Callback for every notification (Slack, webhooks, queues, etc).
notificationsSlugstring"notifications"Slug for the notifications collection.
subscriptionsSlugstring"subscriptions"Slug for the subscriptions collection.
pollIntervalnumber30Poll interval in seconds for the admin bell component.

API

All functions are server-side and require a PayloadRequest:

ExportDescription
notify(req, input)Deliver a notification. Respects per-user channel preferences.
subscribe(req, opts)Subscribe a user to a document. Deduplicates automatically.
unsubscribe(req, userId, ref)Remove a subscription.
getSubscribers(req, ref)Return all user IDs subscribed to a document.
createLiveMessage(fn)Build a serializable message template with dynamic tokens.

Contributing

This plugin lives in the payload-plugins monorepo.

Development

pnpm install

# watch this plugin for changes
pnpm --filter payload-notifications dev

# run the Payload dev app (in a second terminal)
pnpm --filter sandbox dev

The sandbox/ directory is a Next.js + Payload app that imports plugins via workspace:* -- use it to test changes locally.

Code quality

  • Formatting & linting -- handled by Biome, enforced on commit via husky + lint-staged.
  • Commits -- must follow Conventional Commits with a valid scope (e.g. fix(payload-notifications): ...).
  • Changesets -- please include a changeset in your PR by running pnpm release.

Issues & PRs

Bug reports and feature requests are welcome -- open an issue.

License

MIT

FAQs

Package last updated on 25 Feb 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts