What is Payload Comments?
Payload Comments is an open-source plugin for Payload CMS 3.x, published under the package name @navanem/payload-comments. It adds anonymous comments, emoji reactions on comments, optional approval before publication and nested replies up to three levels deep to any Payload collection that the site owner enables. Comment bodies accept a limited Markdown subset, and raw HTML is never rendered. The plugin is written in TypeScript and licensed under MIT.
The plugin is built and maintained by Navanem, a web agency in Geneva and Lausanne, Switzerland. Its project page describes it as a plugin for discussions beneath content and for the people who moderate them, and the README states that it runs in production on navanem.com. The source, issue tracker and release history are on GitHub.
Distribution is source based. The README lists pnpm add @navanem/payload-comments and, until the package is published to the npm registry, pnpm add github:navanem/payload-comments. The plugin can also be vendored into a project under src/plugins/payload-comments. payload (3.88 or later according to the current package.json), react and react-dom 18 or 19 are peer dependencies; the runtime dependencies are react-markdown and remark-gfm, and the engines field requires Node.js 18.20 or later.
The latest release is v0.4.1, published on September 6, 2026. It updated Payload, React, Vitest, TypeScript and related tooling, refreshed vulnerable transitive dependencies, and added CI, Dependabot, contribution, security and protected-branch configuration. Version 0.4.0 (June 2026) added a Thread column to the moderation list. Version 0.3.0 introduced Markdown comment bodies and a runtime approval switch, and 0.2.0 added the Comments Settings global and the Comment Statistics admin view. The full history is in the changelog.
Internally, commentsPlugin() injects two collections, comments and comment-reactions, one global and three public endpoints under /api/comments-api/. Data lives in whatever database adapter the host Payload project uses; the development app in the repository uses the SQLite adapter. IP addresses and browser fingerprints are stored only as salted SHA-256 hashes. The moderation documentation describes the built-in anti-spam measures as deterrents rather than a guarantee and mentions a CAPTCHA or WAF for high-traffic sites. The plugin has no hosted service, no user accounts for commenters and no pricing. Related listings: Payload CMS and Payload Contact, another Navanem plugin for Payload 3.
Key capabilities
- Anonymous comment submission Visitors post with a display name, an email address that is optional by default (
requireEmailcan make it mandatory) and a mood emoji. There are no commenter accounts or logins. The email is stored for moderation but is never returned by the public API or shown to unauthenticated users. - Markdown comment bodies Since 0.3.0 comments render a safe Markdown subset through
react-markdownandremark-gfm: bold, italic, strikethrough, inline and block code, links, lists and blockquotes. Raw HTML is never rendered. Links are forced to open in a new tab withrel="noopener noreferrer nofollow ugc". Custom front ends receive the raw Markdown string and need their own safe renderer. - Threaded replies Replies can be nested up to three levels, enforced on the server. The
maxDepthoption accepts 1, 2 or 3, and the front-end component takes a matching prop so the client and server limits agree. - Reactions on comments Readers can react to existing comments with a configurable emoji set; six reactions are defined by default. Each reaction has a stored key, an emoji and an accessibility label. Posting the same emoji again from the same identity removes it. Reactions are not moderated and are de-duplicated per visitor using the hashed IP and fingerprint.
- Pre-publish moderation With
requireApproval: true, which is the default, new comments start aspendingand stay hidden until an admin approves them. Statuses arepending,approved,spamandtrash, and only approved comments are returned by the public tree endpoint. With approval disabled, comments are published immediately and can still be moved to spam or trash. - Runtime approval switch The Comments Settings global has a Require approval checkbox seeded from the
requireApprovaloption. The submit flow reads it on every request, so moderation can be turned on or off without a redeploy. - Per-collection on and off toggle
enabledCollectionsdefines which collections can receive comments, and the Comments Settings global enables or disables each of them at runtime. A disabled collection rejects new submissions and the widget shows a closed notice; existing comments remain in the database and visible in the admin. The global fails open: if it has never been saved, every configured collection counts as enabled. - Moderation queue in the Payload admin Comments are a standard Payload collection, so the list view with its filters and bulk actions serves as the moderation queue. Since 0.4.0 the list shows a Thread column (top-level or reply to an author) and the target document. The column is a virtual field computed only for authenticated admin reads, with no database column or migration.
- Comment Statistics view An admin view at
/admin/comments-statisticsshows totals by status, reaction count, a per-day rate, breakdowns per collection and per mood, and a recent-comments table. It filters by collection, status and period, queries data on the server and renders only for an authenticated admin. A navigation link is registered throughafterNavLinksfor the default Payload nav. - Built-in anti-spam The plugin includes a honeypot field, a per-IP sliding-window rate limit (default 5 submissions per 60 seconds), minimum and maximum content length (2 and 2000 characters by default) and an optional
blockLinkssetting that rejects comments containing URLs. - Hashed visitor identity IP addresses and browser fingerprints are never stored in clear text. The plugin keeps salted SHA-256 hashes for rate limiting and reaction de-duplication. The salt comes from the
ipSaltoption or theCOMMENTS_IP_SALTenvironment variable, and the documentation asks for a stable secret value. - Bundled React component
<Comments />is exported from@navanem/payload-comments/client. It takesrelationTo,docId, an optionalserverURLfor a Payload server on another origin, and props that mirror the server settings for reactions, email and depth. Styling uses CSS Modules with CSS variables such as--pc-accentand--pc-border. - Public REST API Three endpoints support custom interfaces:
GET /api/comments-api/treereturns approved comments as a nested tree with emails stripped,POST /api/comments-api/submitcreates a comment, andPOST /api/comments-api/<commentId>/reacttoggles a reaction. Requests and responses are documented in the front-end integration guide. - Configurable slugs and options The configuration reference lists the options: collection slugs for comments and reactions, reaction set, length limits, rate limit window, link blocking, salt and a
disabledflag that registers the collections but skips the endpoints. - Installation Add the package with pnpm from the npm name or directly from GitHub, register
commentsPlugin()inpayload.config.ts, setCOMMENTS_IP_SALT, and place the component on a page. When the plugin is vendored undersrc/plugins/payload-comments, the admin import map must resolve@/plugins/payload-comments/components/*, for example by runningpayload generate:importmap. - Tests and CI The repository includes Vitest tests for access control, hooks, the comment tree, reactions, submission, client identity, hashing, rate limiting and content validation, plus a GitHub Actions CI workflow and Dependabot configuration added in 0.4.1.
Where Payload Comments fits
Comments under blog posts or articles
A Payload site lists its post or page collections in enabledCollections and renders <Comments relationTo="posts" docId={post.id} /> on the article template. Readers see approved comments with their Markdown bodies, mood emoji, date, reactions and a reply button, and a composer for name, optional email, text and mood. The README describes this setup on navanem.com.
Moderated discussion with an approval queue
With approval required, every submission arrives as pending. Editors filter the Comments collection by status in the Payload admin, open an entry to see author, email, mood, related document, parent comment and hashed identifiers, and set it to approved, spam or trash. Approval publishes the comment immediately. The moderation guide documents the statuses and the runtime switch.
Closing comments on a collection
Editors can disable commenting for a single collection from the Comments Settings global without a deployment. New submissions to that collection are rejected and the widget displays a closed notice, while the existing comments stay stored and visible to admins. The same global switches mandatory approval on or off.
Custom front end on the REST API
Sites that do not use React, or need their own markup, can call the tree, submit and react endpoints directly. The submit body carries content, author name and email, mood, a fingerprint string, an empty honeypot field, the related document and an optional parent. The tree response contains only approved comments with emails removed, and the stored content is raw Markdown that the client renders itself.
Reviewing comment activity
The Comment Statistics view in the admin gives counts by status, reaction totals, a per-day rate, per-collection and per-mood breakdowns and a recent-comments table, filterable by collection, status and period. Data is queried on the server and shown only to an authenticated admin.
Headless or cross-origin setups
When the Payload server runs on a different origin from the website, the component accepts a serverURL prop pointing to it. The props for reactions, required email and maximum depth must mirror the server configuration, as stated in the integration guide.
Install
pnpm add github:navanem/payload-commentsReviews of Payload Comments
Be the first to share your experience with Payload Comments.
Write a review
Loading review form…
