Configuration
Configure Meerkat through:
-
Tools → Addons → Meerkat in the Control Panel for moderation, spam, Akismet, rate limits, and block lists.
-
config/meerkat.php for defaults, database, API, queue, form, privacy, and spam guard settings.
Keys marked (file) are available only in config/meerkat.php.
#Common changes
| You want to |
Set |
Where |
| Hold new comments for moderation |
publishing.auto_publish, publishing.auto_publish_authenticated_users |
Control Panel or config |
| Require visitors to sign in before commenting |
publishing.only_accept_comments_from_authenticated_users |
Control Panel or config |
| Block an IP address or a word |
iplist.block, wordlist.banned |
Control Panel or config |
| Turn the web API off |
api.enabled |
Config file |
| Store comments in a separate database |
database.connection |
Config file |
| Stop recording visitor IP addresses |
privacy.store_user_ip |
Config file |
#Editorial settings
#Publishing and moderation
1'publishing' => [
2 'auto_publish' => false,
3 'auto_publish_authenticated_users' => true,
4 'only_accept_comments_from_authenticated_users' => false,
5 'automatically_close_comments' => 0,
6 'max_reply_depth' => null,
7 'entry_disable_field' => 'comments_closed',
8 'share_field' => 'meerkat_share_comments',
9 'require_signed_context' => true,
10 'require_guest_email' => env('MEERKAT_REQUIRE_GUEST_EMAIL_FOR_SUBMISSIONS', true),
11],
| Key |
Default |
Description |
auto_publish |
false |
Publish guest comments immediately. false sends them to the moderation queue. |
auto_publish_authenticated_users |
true |
Publish comments from signed-in Statamic users without moderation. |
only_accept_comments_from_authenticated_users |
false |
Reject guest submissions. |
automatically_close_comments |
0 |
Days after an entry date when comments close. 0 disables automatic closure. |
max_reply_depth (file) |
null |
Maximum reply depth. null or 0 permits unlimited depth. See Reply Forms. |
entry_disable_field (file) |
'comments_closed' |
Entry field that closes comments when true. null disables per-entry closure. See Comments Enabled. |
share_field (file) |
'meerkat_share_comments' |
Handle of an entry field that points to another entry's thread. See Thread sharing. |
require_signed_context (file) |
true |
Reject submissions missing Meerkat's signed context token. Turn off only if you build the form by hand. |
require_guest_email (file) |
true |
Require a guest email before accepting a comment. |
#Spam filtering
1'spam' => [
2 'guards' => [
3 GtubeGuard::class,
4 IpFilterGuard::class,
5 WordListGuard::class,
6 DeceptiveMarkupGuard::class,
7 AkismetGuard::class,
8 ],
9 'guard_unpublish_on_guard_failure' => false,
10 'auto_check_spam' => true,
11 'auto_delete_spam' => false,
12 'auto_unpublish_spam' => false,
13 'auto_submit_results' => false,
14],
| Key |
Default |
Description |
auto_check_spam |
true |
Run the spam guards on every new submission. |
auto_delete_spam |
false |
Drop flagged comments instead of saving them. false keeps them for review. |
auto_unpublish_spam |
false |
Save flagged comments but leave them unpublished. |
auto_submit_results |
false |
Send moderator ham/spam corrections back to guards that accept them, such as Akismet. |
guards (file) |
|
Ordered list of guard classes. Meerkat stops at the first match. See Spam Guards. |
guard_unpublish_on_guard_failure (file) |
false |
Unpublish comments when a spam guard fails. |
#Akismet
AkismetGuard is included but remains inactive until configured.
1'akismet' => [
2 'enabled' => true,
3 'api_key' => env('MEERKAT_AKISMET_API_KEY'),
4 'blog_url' => env('MEERKAT_AKISMET_BLOG_URL', env('APP_URL')),
5 'api_host' => env('MEERKAT_AKISMET_API_HOST', 'rest.akismet.com'),
6 'comment_type' => env('MEERKAT_AKISMET_COMMENT_TYPE', 'comment'),
7],
| Key |
Default |
Description |
enabled |
true |
Turn the Akismet guard on or off. |
api_key |
null |
Your Akismet API key. |
blog_url |
APP_URL |
The site URL sent to Akismet. |
comment_type |
'comment' |
The comment type label sent to Akismet. |
api_host (file) |
'rest.akismet.com' |
The Akismet API host. |
When available, Meerkat sends user_ip, user_agent, and referer to Akismet for scoring. See Comment metadata.
#Rate limiting
1'rate_limits' => [
2 'enabled' => true,
3 'max_attempts' => env('MEERKAT_RATE_LIMIT_ATTEMPTS', 5),
4 'decay_minutes' => env('MEERKAT_RATE_LIMIT_DECAY', 15),
5],
| Key |
Default |
Description |
enabled |
true |
Turn the submission rate limiter on or off. |
max_attempts |
5 |
Submissions allowed per decay_minutes window. |
decay_minutes |
15 |
Length of the window, in minutes. |
Meerkat does not include a captcha. Add Turnstile, hCaptcha, or reCAPTCHA through submission middleware.
#Blocked IPs and words
1'iplist' => ['block' => []],
2'wordlist' => ['banned' => []],
| Key |
Default |
Description |
iplist.block |
[] |
IP addresses the IpFilterGuard rejects. |
wordlist.banned |
[] |
Words and phrases rejected by WordListGuard. See Spam guards. |
#Anonymous author defaults
1'authors' => [
2 'anonymous_email' => 'no-email@example.org',
3 'anonymous_author' => 'Anonymous User',
4],
| Key |
Default |
Description |
anonymous_author |
'Anonymous User' |
The name used when a guest comments without filling it in. |
anonymous_email |
'no-email@example.org' |
The email used when a guest comments without filling it in. |
#Site and server settings
#Database
1'database' => [
2 'connection' => env('MEERKAT_DATABASE_CONNECTION'),
3],
| Key |
Default |
Description |
connection |
null |
The name of a connection from config/database.php. null uses the app's default connection. |
Set a prefix on the connection in config/database.php to prefix Meerkat's tables.
#Security
1'security' => [
2 'guard_content_variables' => env('MEERKAT_GUARD_CONTENT_VARIABLES', true),
3],
| Key |
Default |
Description |
guard_content_variables |
true |
Hides email, request metadata, moderation fields, and removal fields while Antlers evaluates user-submitted content. Trusted templates still receive them. Disable only if the global field guard conflicts with your templates. |
#Web API
1'api' => [
2 'enabled' => true,
3 'per_page' => 15,
4 'max_per_page' => 100,
5 'max_full_thread_comments' => 500,
6 'middleware' => [
7 'public' => ['throttle:60,1'],
8 'privileged' => ['throttle:30,1', 'auth', 'can:view comments'],
9 ],
10],
| Key |
Default |
Description |
enabled |
true |
When false, every /api/meerkat/* route returns a 404. The Control Panel and submission form keep working. |
per_page |
15 |
Default page size when the caller does not request one. |
max_per_page |
100 |
Largest page size allowed through per_page. Larger requests use this limit. |
max_full_thread_comments |
500 |
The most comments the full-thread endpoint returns in one response before returning 413. Set 0 to disable the cap. |
middleware |
see code |
Middleware for public and moderation endpoints. Keep auth and can:view comments when replacing the privileged array. See API middleware. |
#Background jobs
1'jobs' => [
2 'connection' => env('MEERKAT_JOB_CONNECTION', env('QUEUE_CONNECTION', 'sync')),
3 'queue' => env('MEERKAT_JOB_QUEUE', 'default'),
4],
Used by the "Check pending for spam" action and Akismet ham/spam submissions.
| Key |
Default |
Description |
connection |
QUEUE_CONNECTION (or sync) |
Queue connection for Meerkat's jobs. |
queue |
'default' |
Queue name. |
#Filesystem mirror
The mirror writes comments to {mirror.path}/{thread_id}/{timestamp_id}/comment.md and replies beneath replies/{timestamp_id}/.
1'mirror' => [
2 'enabled' => env('MEERKAT_MIRROR_ENABLED', true),
3 'path' => env('MEERKAT_MIRROR_PATH'),
4],
| Key |
Default |
Description |
enabled |
true |
Turn the disk writer on or off. |
path |
content/comments |
Mirror directory. null uses base_path('content/comments'). |
See Filesystem mirror for the import and recovery workflow.
#Form
1'form' => [
2 'blueprint' => 'meerkat',
3 'honeypot' => 'username',
4 'middleware' => ['throttle:30,1'],
5],
| Key |
Default |
Description |
blueprint |
'meerkat' |
Handle of the comment blueprint. Supplied as resources/blueprints/meerkat.yaml. |
honeypot |
'username' |
Name of a decoy field that real visitors leave empty. Meerkat discards submissions that fill it. Use a name that an autofill bot can complete. |
middleware |
['throttle:30,1'] |
Middleware for the submission route (meerkat-form-submit). The default permits 30 requests in one minute. |
#Fields
1'fields' => [
2 'extractors' => [
3 'comment' => CommentExtractor::class,
4 'author' => AuthorExtractor::class,
5 ],
6 'exclude' => [
7 'created_at', 'is_spam', 'is_published', 'thread_id',
8 'author_id', 'collection', 'site',
9 ],
10],
| Key |
Default |
Description |
extractors.comment |
CommentExtractor::class |
Class that pulls the comment body from a submission. See The Comment Blueprint. |
extractors.author |
AuthorExtractor::class |
Class that pulls the author identity from a submission. |
exclude |
see code |
Blueprint fields that should not render in {{ meerkat:form }}. Internal and system fields belong here. |
#Privacy
1'privacy' => [
2 'store_user_agent' => true,
3 'store_user_ip' => true,
4 'store_referrer' => true,
5],
| Key |
Default |
Description |
store_user_ip |
true |
Store the submitter's IP address. Disabling this also omits user_ip from Akismet requests, which Akismet documents as required — expect Akismet checks to fail without it. |
store_user_agent |
true |
Store the submitter's user agent. |
store_referrer |
true |
Store the referrer. |
Set any value to false to stop storing it. Disabling request data can reduce the effectiveness of spam guards.
#Control Panel listing
1'cp' => [
2 'per_page' => 50,
3 'max_per_page' => 100,
4],
| Key |
Default |
Description |
per_page |
50 |
Page size for the comment listing in the Control Panel. |
max_per_page |
100 |
Largest page size that the listing requests. |
Comment revisions
1'revisions' => [
2 'enabled' => env('MEERKAT_REVISIONS_ENABLED', false),
3],
| Key |
Default |
Description |
enabled |
false |
Capture and show comment revisions. Requires Statamic Pro. |
#GraphQL
1'graphql' => [
2 'enabled' => env('MEERKAT_GRAPHQL_ENABLED', false),
3 'per_page' => 15,
4 'max_per_page' => 100,
5 'max_depth' => 25,
6],
| Key |
Default |
Description |
enabled |
false |
Add Meerkat types and queries to Statamic's /graphql endpoint. Requires Statamic Pro and statamic.graphql.enabled. |
per_page |
15 |
Default page size for meerkatComments. |
max_per_page |
100 |
Largest page size a caller may request. |
max_depth |
25 |
Reply levels GraphQL loads when publishing.max_reply_depth is unlimited. |
See GraphQL for the schema and queries.
#Where each setting lives
| Group |
Control Panel overrides |
Config file only |
publishing |
auto_publish, auto_publish_authenticated_users, only_accept_comments_from_authenticated_users, automatically_close_comments |
max_reply_depth, entry_disable_field, share_field, require_signed_context, require_guest_email |
spam |
auto_check_spam, auto_delete_spam, auto_unpublish_spam, auto_submit_results |
guards, guard_unpublish_on_guard_failure |
akismet |
enabled, api_key, blog_url, comment_type |
api_host |
rate_limits |
enabled, max_attempts, decay_minutes |
- |
iplist |
block |
- |
wordlist |
banned |
- |
authors |
anonymous_author, anonymous_email |
- |
database |
- |
connection |
security |
- |
guard_content_variables |
api |
- |
enabled, per_page, max_per_page, max_full_thread_comments, middleware |
revisions |
- |
enabled (Pro) |
graphql |
- |
enabled, per_page, max_per_page, max_depth (Pro) |
jobs |
- |
connection, queue |
mirror |
- |
enabled, path |
form |
- |
blueprint, honeypot, middleware |
fields |
- |
extractors, exclude |
privacy |
- |
store_user_ip, store_user_agent, store_referrer |
cp |
- |
per_page, max_per_page |