npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

payload-plugin-admin-alerts

v1.0.0

Published

Dashboard system alerts for the Payload CMS admin UI — author messages, target audiences, allow per-user dismissals.

Readme

payload-plugin-admin-alerts

Dashboard system alerts for the Payload CMS admin UI. Author messages from the admin panel, target an audience (everyone or specific users), and let users dismiss them individually.

Features

  • admin-alerts collection for authoring messages (title, content, type, audience, dismissable flag)
  • Per-user dismissals tracked inline on the alert via a dismissedBy relationship field — no extra collection
  • Alert types: info, success, warning, error
  • Audience targeting: broadcast to all authenticated users, or pick specific users
  • "Active" / "Inactive" status for taking alerts down without deleting them
  • Dashboard panel that fetches and renders alerts on the admin home page
  • Per-user dismissal endpoint (POST /admin-alerts/:id/dismiss)
  • Access control: only the alert author can edit or delete; any authenticated user can read

Installation

pnpm add payload-plugin-admin-alerts
# or: npm install payload-plugin-admin-alerts
# or: yarn add payload-plugin-admin-alerts

Peer requirements: payload ^3.0.0, @payloadcms/ui ^3.0.0, react ^18 || ^19, react-dom ^18 || ^19.

Usage

Add the plugin to your payload.config.ts:

import { buildConfig } from 'payload'
import { payloadAdminAlerts } from 'payload-plugin-admin-alerts'

export default buildConfig({
  plugins: [
    payloadAdminAlerts({
      // defaults shown
      disabled: false,
      usersCollectionSlug: 'users',
    }),
  ],
  // ...
})

That's it. After Payload restarts you'll see a System → Admin Alerts entry in the admin nav and a new alerts panel on the dashboard.

Configuration

type PayloadAdminAlertsConfig = {
  /**
   * Disable the runtime behavior (dashboard UI + endpoints) while keeping
   * the collections registered, so the database schema stays consistent.
   * @default false
   */
  disabled?: boolean

  /**
   * Auth collection slug used for alert authors and audience targeting.
   * @default 'users'
   */
  usersCollectionSlug?: string
}

| Option | Type | Default | Notes | | --------------------- | --------- | --------- | ---------------------------------------------------------------------------------------------------- | | disabled | boolean | false | Skips registering the dashboard component and endpoints. Collections stay so migrations don't break. | | usersCollectionSlug | string | 'users' | Used by the createdBy and targetUsers relationship fields, and by access control checks. |

Creating alerts from hooks

Alerts are a normal Payload collection (admin-alerts). Create them from any collection hook, job, or endpoint with the Local API — for example, notify editors when content goes live:

import type { CollectionAfterChangeHook, CollectionConfig } from 'payload'

const alertOnPublish: CollectionAfterChangeHook = async ({
  doc,
  operation,
  previousDoc,
  req,
  context,
}) => {
  // Only run once per publish, not on every save
  if (context.skipAdminAlert) return
  if (operation !== 'update') return
  if (doc._status !== 'published' || previousDoc?._status === 'published') return

  await req.payload.create({
    collection: 'admin-alerts',
    data: {
      title: `Published: ${doc.title}`,
      content: 'A new post is live. Review it from the dashboard if needed.',
      type: 'success',
      status: 'active',
      audience: 'all',
      dismissable: true,
    },
    req, // pass req so the alert stays in the same transaction
    user: req.user, // createdBy is auto-set from the authenticated user
  })
}

export const Posts: CollectionConfig = {
  slug: 'posts',
  versions: { drafts: true },
  hooks: {
    afterChange: [alertOnPublish],
  },
  fields: [
    { name: 'title', type: 'text', required: true },
    // ...
  ],
}

Target a specific user (for example, the post author) instead of broadcasting:

await req.payload.create({
  collection: 'admin-alerts',
  data: {
    title: 'Your draft was rejected',
    content: 'An editor left feedback on your submission.',
    type: 'warning',
    status: 'active',
    audience: 'selected',
    targetUsers: [authorId],
    dismissable: true,
  },
  req,
  user: req.user,
})

Notes

  • Pass req into nested create calls so the alert participates in the same database transaction as the triggering operation.
  • Pass user: req.user when the hook runs in an authenticated request; the plugin sets createdBy automatically on create.
  • For system/cron contexts with no req.user, use overrideAccess: true and set createdBy yourself if you need an author for update/delete access.
  • Use req.context flags (for example context.skipAdminAlert) if your hook chain could re-trigger itself.

Collections

admin-alerts

Authored from the admin panel. Fields:

| Field | Type | Purpose | | -------------- | ------------------ | -------------------------------------------------------------------------------------- | | title | text, required | Heading shown on the dashboard card | | content | textarea, required | Body text | | type | select | info / success / warning / error — drives the styling | | status | select | active / inactive — only active alerts are surfaced | | dismissable | checkbox | If true, users can dismiss the alert for themselves | | audience | select | all or selected | | targetUsers | relationship[] | Shown only when audience === 'selected' | | createdBy | relationship | Auto-populated on create, read-only | | dismissedBy | relationship[] | Users who have dismissed this alert; edit to re-show or pre-dismiss for specific users | | alertPreview | ui field | Live preview of how the alert will render on the dashboard |

Dismissals

Dismissals live on the alert itself as the dismissedBy relationship array — no separate collection. POST /admin-alerts/:id/dismiss appends the requesting user to the field; the dashboard query filters out alerts where the current user appears in dismissedBy. To re-show an alert to a specific user, remove them from dismissedBy. To re-broadcast to everyone who'd dismissed it, clear the field.

Endpoints

The plugin registers two endpoints (mounted under your Payload API route, typically /api):

| Method | Path | Description | | ------ | --------------------------- | ----------------------------------------------------------- | | GET | /admin-alerts/dashboard | Returns { alerts: DashboardAlert[] } for the current user | | POST | /admin-alerts/:id/dismiss | Records a dismissal for the current user |

Both require an authenticated request.

Access control

  • Read any alert: any authenticated user
  • Create an alert: any authenticated user (you become createdBy)
  • Update / Delete: only the user who authored the alert

Dismissals are write-only and scoped to the requesting user.

Local development

pnpm install
pnpm dev          # starts the dev/ Payload app on http://localhost:3000
pnpm test:unit    # vitest unit tests
pnpm test:e2e     # playwright e2e tests
pnpm check        # typecheck + lint + tests

The dev/ directory contains a minimal Payload app preconfigured with the plugin.

Publishing

pnpm publish

prepublishOnly cleans dist/ and rebuilds. publishConfig swaps the source-pointing exports for the compiled dist/ outputs at publish time, so consumers always get the built files.

License

MIT

Media

This plugin was tested and developed in relation to my upcoming fairytale builder app.

Info example Darkmode example