stillat/meerkat
Meerkat is a lightweight Laravel package from Stillat that keeps watch over your application, offering a simple, expressive API for monitoring important events and reacting when things change, with minimal setup and no heavy dependencies.
Meerkat is a comments-and-moderation addon for Statamic, so the fastest path is to treat it like any other Statamic addon and get a comment rendering end-to-end before touching moderation or spam settings.
Install a pinned, known-good version. Require it via Composer at a fixed minor or exact version, then publish whatever config and migrations ship with it:
composer require "stillat/meerkat:4.0.2"
php artisan vendor:publish --tag=meerkat-config
php artisan migrate
Statamic addons auto-register through extra.statamic in composer.json, so there is normally no manual providers entry needed. If the addon registers a Control Panel nav item, it should appear after a php artisan statamic:stache:clear and a hard refresh. Start on 4.0.2 — it carries the relationship-column fix described below, so beginning on anything older means starting on a known-buggy baseline.
Look at the config file first, then the service provider. With 6 stars and a NOASSERTION license, documentation will be thinner than the code. Read config/meerkat.php top to bottom — it is usually the most honest summary of the feature surface (model/table names, moderation defaults, notification recipients, spam toggles, route middleware). Then skim the addon's service provider and routes file to see exactly what HTTP endpoints it exposes and under what prefix.
Find the frontend entry point. Most Statamic comment addons expose either an Antlers tag pair (for example a {{ meerkat:form }} / {{ meerkat:comments }} style pair) or a Blade component plus a published view. Check resources/views in the package and any tags directory. Copy the published views into your theme so you can style them — never edit vendor files.
First use case: a single-entry comment thread. Pick one collection entry, drop the form tag into its template, post a test comment as a logged-out visitor, and confirm it lands in the moderation queue rather than rendering immediately. That single loop — submit → queue → approve → render → re-render the entry's comment list — exercises the config, the migration, the routes, the CP screen, and the comment↔entry relationship that 4.0.2 just fixed. Do this before wiring it into every template.
Locate the moderation UI. The CP screen is where you will spend most of your day-to-day time. Find it early; approving comments from tinker or the database is a bad habit that will bite you once notifications and spam scoring are involved.
Gate everything behind a feature flag at first. Given the maturity level, wrap the comment form in a config toggle or a Statamic {{ if }} on an environment variable so you can disable submissions in production without a deploy if the addon misbehaves.
Use the addon's own rendering tags rather than hand-rolling the form. Comment addons ship CSRF handling, honeypot fields, and validation that you will forget to replicate. Publish the views, restyle them, but keep the form action, hidden inputs, and field names intact.
Keep moderation state in the addon, not in your content. Resist the urge to mirror comment status onto entries or entries' front matter. Let Meerkat own the comment lifecycle and query it for display; mixing the two creates sync bugs the moment a moderator bulk-approves.
Treat the comment→entry relationship as the primary read path and test it explicitly. The headline change in 4.0.2 is a fix to "comment relationship columns" (PR #263). That is the plumbing behind "show comments for this entry" and "count comments on this listing." Write a test that approves a comment on Entry A and asserts it does not appear on Entry B — a mis-mapped foreign key silently cross-posts comments between entries, which is embarrassing to discover in production. If you query comments directly with Eloquent ($entry->comments, Comment::where('entry_id', …)), verify the actual column names against the migration rather than assuming; the fix changed what those columns point at, not necessarily what they're called.
Layer notifications rather than replacing them. If the addon fires events or sends mail on new comments, subscribe to its events (or Laravel's) in your own listener and route them to Slack/Discord/a shared inbox. That keeps your notification logic in your app and survives an addon upgrade that changes its mail templates.
For multi-site, be explicit. Statamic multi-site is common. Decide per site whether comments are shared or scoped, and verify against the schema whether the addon stores a site column — if it does not, you will need to scope queries yourself in the tag or your own wrapper. Relationship-column fixes like the one in 4.0.2 are a good reminder to re-check multi-site linkage on every upgrade.
Rate limiting belongs in front of the addon. Add throttle middleware to the comment POST route via the config's route middleware option (if present) or a route override in your app's service provider. A comment endpoint is one of the first things a bot finds.
Compose with Live Preview and caching carefully. Comment counts on listing pages are the classic cache-invalidation trap. Either exclude the count from cached fragments, or use Statamic's cache tags/invalidation and clear on approve — otherwise you will ship stale counts that never update. This is also the place where a relationship-column bug manifests most visibly: counts attached to the wrong entry.
Testing pattern: write one feature test that posts to the comment endpoint and asserts a pending record exists with the correct entry ID, and one that asserts a pending comment is not rendered on the public page. These two tests catch the majority of regressions when you upgrade the addon.
"stillat/meerkat": "4.0.2" (or ~4.0.2), commit composer.lock, and read the diff of every upgrade. Six stars and zero dependents means you are the QA team; there is no ecosystem to catch a breaking change for you.select entry_id, count(*) from meerkat_comments group by entry_id against your actual entries.NOASSERTION. That is not the same as "MIT." Confirm with the maintainer or the repo's LICENSE file before shipping this in client work — this is a legal question, not a technical one, and it is easy to miss when the package installs fine.config('meerkat.x') in some places and hardcoded defaults in others. If a config change appears to do nothing, php artisan config:clear first, then grep the package source for the literal value.vite/laravel-mix build — Statamic addons sometimes ship uncompiled assets.grep -rn "Statamic::tag\|registerTag\|Route::\|foreignId\|belongsTo" vendor/stillat/meerkat/src will orient you in two minutes faster than searching the web — and the last two patterns are how you confirm what 4.0.2 changed.How can I help you explore Laravel packages today?