Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Commentify Laravel Package

usamamuneerchaudhary/commentify

Commentify is a Laravel Livewire commenting package you can add to any model. It supports Tailwind and Bootstrap 5, with sorting, pagination, mentions, Markdown, emoji, likes, guest likes by IP, and reporting.

View on GitHub
Deep Wiki
Context7

Getting Started

Know the floor before you commit. Commentify requires PHP 8.2+, Laravel 12+, and Livewire 4. If your app is on Livewire 3 or Laravel 11, this package is not an option today — verify with composer why-not usamamuneerchaudhary/commentify before pitching it to a team.

Install and migrate in one pass:

composer require usamamuneerchaudhary/commentify
php artisan vendor:publish --tag="commentify-config"
php artisan vendor:publish --tag="commentify-migrations"   # optional, see gotchas
php artisan migrate

Check that comments and comment_reports tables exist and that the service provider was auto-discovered (php artisan about or php artisan config:show commentify). For path-repository/symlink setups, register Usamamuneerchaudhary\Commentify\Providers\CommentifyServiceProvider::class in bootstrap/providers.php — this is the single most common "why are my migrations missing" cause.

Wire up your first model. Add the trait to whatever is commentable, not just one model:

use Usamamuneerchaudhary\Commentify\Traits\Commentable;

class Article extends Model
{
    use Commentable;
}

Wire up your User model and point the config at it:

use Usamamuneerchaudhary\Commentify\Traits\HasUserAvatar;

class User extends Model
{
    use HasUserAvatar;
}
// config/commentify.php
'user_model' => \App\Models\User::class,

Drop the component into any Blade view:

<livewire:comments :model="$article" />

That is the whole first use case: a blog post, a ticket, a product page — same three lines per model. Start by reading config/commentify.php end to end; it is effectively the package's API surface, and css_framework, user_model, and require_approval are the three settings that decide whether the UI looks right and whether content moderates itself.

Implementation Patterns

Treat config as environment-specific. The package reads everything from config/commentify.php, so lean on env vars rather than editing the file per deployment:

'require_approval' => env('COMMENTIFY_REQUIRE_APPROVAL', false),
'enable_reporting'  => env('COMMENTIFY_REPORTING', true),
'read_only'         => env('COMMENTIFY_READ_ONLY', false),
'pagination_count'  => env('COMMENTIFY_PER_PAGE', 10),

Production gets require_approval=true for public-facing content; staging keeps it false so QA isn't clicking Approve all day.

Read-only mode is your archival switch. Flip read_only => true globally, or better, scope it by surfacing a small wrapper that passes the state per surface if the package allows it — for locked/archived posts and closed threads, this beats deleting comments or hiding the component entirely.

Moderation needs an admin surface you actually own. Filament integration is optional and framework-independent; if you're not on Filament, build a simple Livewire or Nova screen against unapproved comments. Two things matter day-to-day:

  • Add a pending badge in your admin nav (Comment::where('is_approved', false)->count()) so approvals don't rot.
  • Confirm the frontend genuinely hides unapproved rows, including from your own aggregate counts. If you display "12 comments" on an article card, compute it from approved records only — don't trust a blind ->comments()->count().

Authorize with policies, not conditionals in views. The package ships policy-based authorization for comment actions. Register a policy for the package's comment model and encode "edit within 15 minutes", "delete own or admin", "cannot report own comment" there. Then every UI affordance and Livewire action inherits the same rules. Pair this with the temporary-ban feature for repeat offenders instead of writing your own throttle.

Notifications are opt-in and half the work is yours. Set enable_notifications => true and pick channels deliberately:

'notification_channels' => ['database'],   // start here
  • database is useless without a notification bell/UI in your layout — budget for that.
  • mail requires working mail config and a queue worker; a synchronous mail send inside a Livewire request will make commenting feel broken.
  • broadcast requires broadcasting configured plus a running queue; only add it if you already have Echo/Reverb in the app.

Mentions need real routes. users_route_prefix (default users) is used to link @mentions. If you don't have a users/{id} route, mention links 404 in rendered Markdown. Either create the route or override the view that renders mentions.

Style integration is a one-time, per-project decision. Pick css_framework before you publish anything. For Tailwind v4, add the dark variant to your app CSS:

@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));

Then make sure Tailwind actually scans the package views — v4 @source directive (or the content globs if you publish the package's tailwind.config.js). Missing styles almost always mean Tailwind never saw the vendor Blade files, not that the package is broken.

Test the component like any Livewire component. Use Livewire::test() against the comments component with a factory-created model, and assert that a comment by an unauthorized user is rejected, that unapproved comments don't render, and that reporting is idempotent per user. These are the behaviors that regress on upgrades.

Gotchas and Tips

Pin the version and read the release notes. This is a young package (a few hundred stars, zero dependents). Add a caret constraint you're comfortable with and skim each release — a commenting package touches your auth policies and public views, so a surprise minor bump is a real risk. Never composer update it in the same PR as anything else.

Publishing views forks the UI permanently. Once published to resources/views/vendor/commentify/, package updates no longer reach you, and you won't get fixes for the emoji picker, mention rendering, or approval banners. Publish only the specific files you must change, keep a diff-on-upgrade habit, and prefer overriding via config or policies first.

Published migrations are yours forever. If you publish and then the package adds columns in a later release, your copy won't have them and queries will fail at runtime, not install time. If you don't need to edit the schema, skip the migrations publish and let the package own them.

Switching css_framework after publishing views leaves you with the old framework's markup. The config switches package views, not published ones. Pick one and stay, or republish and re-apply your customizations.

Guest likes are IP + UserAgent based and that has real consequences. Behind a load balancer, Cloudflare, or a container without trusted proxies configured, every guest resolves to the same IP and can only like a comment once — or one guest's likes collide with another's. Configure TrustProxies before enabling public guest engagement, and accept that corporate NAT users share a like budget. It's an engagement heuristic, not a security boundary.

Markdown + mentions is an XSS surface. The package renders user-authored Markdown. Confirm the renderer's safe mode is on (or sanitize on output) before you ship to a public audience — a comment box on a public blog is an obvious attack target. Also check mention links are built from escaped display names.

require_approval flips silently for the commenter. They post, see nothing, and assume it's broken. Customize the comment view (or add a notice above the component) to say "your comment is awaiting moderation." This one small change prevents a stream of support tickets.

Changing user_model later is a data migration, not a config edit. Comments and mentions reference user IDs; repointing the model at a different table or class will orphan avatars and break mention lookups. Decide early.

Debugging checklist when something renders but doesn't work:

  1. php artisan config:show commentify — is your config actually loaded (cache cleared)?
  2. php artisan vendor:publish with no tag — lists available tags so you use the right one.
  3. Livewire component registered? php artisan livewire:list (or check app/Livewire collisions if you have a comments component).
  4. Browser console: Alpine errors usually mean Alpine is loaded twice (once by you, once by Livewire 4).
  5. Missing styles → Tailwind content/@source scanning, not CSS specificity.
  6. Queue worker running if you enabled mail or broadcast.

Extension points, in order of preference: config → lang publishing (translate report reasons and sort labels properly rather than hardcoding English) → policies → view overrides. Reach for view overrides last, because that's the path that stops receiving upstream fixes.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table