ZSComments is a comments plugin for Grav 2.
It started as a fork of the original Grav Comments plugin, but has been adapted for modern Grav 2 projects with admin2 moderation, YAML-based storage, threaded replies, and safer file locking for shared hosting.
- add comments to Grav pages from the frontend
- threaded comment replies
- optional moderation / approval workflow
- admin2 moderation UI
- quick reply while approving a comment
- moderation email notifications with approve/delete actions
- configurable frontend comment order (
asc/desc) - route-based enable / disable rules
- Gravatar support
- YAML storage in
user/data/zscomments - lock-directory based concurrent file access without relying on
flock() - optional reCAPTCHA integration via Grav Form
- Grav
2.x - Form plugin
- Email plugin
- admin2 plugin recommended for configuration and moderation
Install with GPM:
bin/gpm install zscommentsOr clone / copy this plugin into:
user/plugins/zscomments
- Install and enable the plugin.
- Configure it in admin2 or in
user/config/plugins/zscomments.yaml. - Add the comments partial to the page template where comments should appear.
- Make sure the Email plugin is configured correctly if you want moderation emails.
Add the partial to a Twig template:
{% include 'partials/zscomments.html.twig' with { page: page } %}Example inside a blog item template:
{% block content %}
{% include 'partials/blog_item.html.twig' with { blog: page.parent, truncate: false } %}
{% include 'partials/zscomments.html.twig' with { page: page } %}
{% endblock %}You can configure ZSComments either:
- in admin2
- or in
user/config/plugins/zscomments.yaml
| Option | Default | Description |
|---|---|---|
enabled |
true |
Enables the plugin. |
require_approval |
true |
New comments are stored as pending until approved. |
approval_email |
mail@example.com |
Recipient for moderation emails. |
approval_from |
Grav CMS <noreply@example.com> |
Sender used for moderation emails. Use a valid sender address for your mail setup. |
approval_subject |
New comment |
Subject line for moderation emails. |
quickreply_name |
Your name |
Author name used for quick replies created during approval. |
quickreply_email |
mail@example.com |
Email used for quick replies created during approval. |
comment_order |
desc |
Frontend output order for approved comments: asc or desc. |
enable_on_routes |
['/'] |
Route prefixes where the plugin should be active. |
disable_on_routes |
[] |
Exact routes where the plugin should stay disabled even if matched by enable_on_routes. |
lock_timeout |
5 |
Maximum wait time in seconds for a comment file lock. |
lock_retry_delay |
100000 |
Delay between lock retries in microseconds. |
lock_stale_timeout |
30 |
Removes stale lock directories after this many seconds. |
enabled: true
require_approval: true
comment_order: desc
approval_email: mail@example.com
approval_from: 'My Site <noreply@example.com>'
approval_subject: 'New comment waiting for approval'
enable_on_routes:
- /blog
- /news
disable_on_routes:
- /blog/archiveenable_on_routesworks as a route prefix listdisable_on_routesis checked as an exact route list
So this is a common setup:
enable_on_routes:
- /That enables comments everywhere unless a route is explicitly disabled.
When admin2 is installed, ZSComments adds its own plugin page in the admin interface.
From there you can:
- review recent comments
- filter by:
- pending only
- time range
- route
- text search
- approve comments
- delete comments
- add an optional quick reply during approval
- see recently commented pages
When a comment is submitted, ZSComments can send a moderation email using the Email plugin.
Important:
- the Email plugin provides the actual mail transport
- ZSComments provides the moderation-specific recipient, sender, and subject
- moderation mails contain approve/delete actions
- an optional quick reply can be added while approving
Relevant ZSComments settings:
approval_emailapproval_fromapproval_subject
Comments are stored as YAML files in:
user/data/zscomments
On multilingual sites, comments are stored per language as well.
Examples:
user/data/zscomments/de/blog/my-post.yaml
user/data/zscomments/en/blog/my-post.yaml
Benefits of this approach:
- no database required
- simple backups
- easy manual inspection
- one comment file per page route
The frontend output is rendered by:
plugins/zscomments/templates/partials/zscomments.html.twig
Public output currently behaves like this:
- only approved comments are shown
- comments can be shown oldest-first or newest-first
- replies are rendered as a nested thread
- name and date fields are always visible
- comment sender email is never puplished
- avatars are rendered via Gravatar if available
The default plugin configuration includes a commented example for reCAPTCHA integration.
To enable it:
- copy or edit
user/config/plugins/zscomments.yaml - uncomment the captcha field in the form definition
- uncomment the captcha process block
- add your own reCAPTCHA site key and secret
- The plugin is designed for Grav 2 and admin2 workflows; classic Grav Admin integration is not included.
disable_on_routesis matched as an exact route list, whileenable_on_routesworks by prefix.- Public frontend output only shows approved comments.
- There is no database backend; comments are stored in YAML files per route.
- Moderation by email is intended for trusted recipients because approval and delete actions are triggered from moderation links/forms.
ZSComments was renamed deliberately to avoid conflicts with the original Grav plugin.
If you are migrating from comments, check these points:
- plugin folder changed from
user/plugins/commentstouser/plugins/zscomments - config file changed from
user/config/plugins/comments.yamltouser/config/plugins/zscomments.yaml - Twig partial changed from
partials/comments.html.twigtopartials/zscomments.html.twig - comment storage changed from
user/data/commentstouser/data/zscomments - admin integration is now focused on admin2
Template include update:
{# old #}
{% include 'partials/comments.html.twig' with { page: page } %}
{# new #}
{% include 'partials/zscomments.html.twig' with { page: page } %}If you already have legacy comment data, move or convert it into the user/data/zscomments structure before removing the old plugin.
- The plugin is intentionally named
zscommentsto avoid conflicts with the original Gravcommentsplugin. - It is designed for Grav 2 and admin2 workflows.
- File locking is implemented with lock directories for better compatibility with shared hosting environments where
flock()can be unreliable.
MIT — see LICENSE.