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

Filament Max Chat Laravel Package

geekcodev/filament-max-chat

Filament plugin for an operator chat with MAX messenger users. View dialogs with unread badges, reply with HTML formatting and media attachments, receive real-time Echo/Reverb updates with a poll fallback, and configure permissions, channel, disk and navigation via config.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy for in-app messaging. The package already ships the unglamorous, high-cost parts of a chat/inbox feature: unread counting (MaxMessageService::totalUnreadCount()), a JSON unread endpoint (UnreadCountController), and read-state transitions (markRead()). That shifts the build-vs-buy question from "can we avoid writing a chat backend?" to "do we only need to write the differentiated layer?" — typically the composer UI, notification preferences, and integration with your existing user/tenant model.
  • Roadmap sequencing for engagement surfaces. Unread badges and inbox counters are the retention-critical, low-glitz features that teams consistently underestimate. This release is evidence the package treats that surface as first-class, which supports scheduling "unread badge + inbox" earlier in a roadmap rather than deferring it behind richer messaging features.
  • Buy-vs-extend on read receipts and notification state. Read/unread semantics (direction = 'in', read_at) are exposed and indexable rather than buried in a black box. A PM can approve extending this with per-channel or per-tenant unread rules without a rewrite, as long as custom conditions are backed by indexes — the failure mode below is precisely unindexed predicate drift.
  • Operational risk budgeting for chat features. The patch documents a real production cascade: unindexed unread count → full table scan → Octane workers pinned → /up healthcheck misses → container restarts. For a PM, that is a capacity-planning input, not just a bug fix: any messaging surface that renders a badge on every page view is a per-request cost multiplied by traffic, and it belongs in launch readiness reviews alongside load testing.
  • Upgrade cadence and release-train policy. v1.1.5 is additive: one migration, no signature changes, no config keys, no translation keys, no new env vars. That supports a standing policy of auto-adopting patch releases on this dependency while reserving manual review for minor/major bumps.
  • Platform commitments (DB and runtime). Migrations are exercised on SQLite, PostgreSQL, and MySQL, and the chosen composite index over a partial index is explicitly a portability trade-off. This matters if the roadmap includes a database migration or a move to managed Postgres — a decision made now can be checked against a stated support matrix.
  • Schema-change governance in multi-tenant host apps. The Schema::hasIndex guard means host applications that already added an equivalent index won't fail on install. That removes a common blocker for platform teams shipping shared infrastructure to multiple downstream products.

When to Consider This Package

Consider it when:

  • You are on Laravel and need an inbox/chat primitive with unread counts and read-state, not a full real-time messaging product.
  • Your message table is growing or already large. The release notes are explicit that the problem only surfaces past a volume threshold; adopting before that point buys you the fix without the outage.
  • You run Octane, or any fixed-size worker pool, and a per-request unread count would be on a hot path.
  • You need multi-database portability (SQLite in dev/CI, MySQL or PostgreSQL in production) and cannot take on engine-specific schema features.
  • Your team wants a dependency with verifiable quality gates: 271 tests, 628 assertions, 98.31% line coverage, PHPStan at max level, CS Fixer clean, composer audit clean.
  • You are comfortable applying migrations as part of routine deploys — the entire upgrade is php artisan migrate.

Look elsewhere when:

  • You need real-time delivery, presence, typing indicators, or fan-out to websockets as an out-of-the-box capability. This is a persistence-and-state layer; the transport is your problem.
  • Your unread rules are materially more complex than inbound-and-unread (per-channel, per-role, muted threads, digest windows). The chosen index is (direction, read_at); richer predicates will need their own indexing strategy and you should plan for it deliberately rather than discover it under load.
  • You require partial indexes for storage efficiency. The release notes state these were rejected for MySQL portability — if you are Postgres-only and index size is a real constraint, that is a design mismatch, not a bug.
  • You cannot run schema migrations on your release cadence, or your DBA gate is slow enough that adding an index is a multi-week project.
  • You need a hardened vendor with commercial support and SLAs; this is a self-supported package and the notes are transparent about a CI step that was skipped for environmental reasons (insufficient host disk for a second vendor/), leaving clean-resolution verification to CI.

How to Pitch It (Stakeholders)

For executives — one paragraph: This is a low-risk maintenance release for our chat/inbox dependency that fixes a real production failure mode rather than adding features. The unread-message badge was being counted with a full table scan on every page render; as message history grew, that scan occupied application workers long enough that the container's health check failed and the container was restarted. The fix is a single database index, delivered as an additive migration. There are no breaking changes, no new configuration, no new environment variables, and no new translation keys — the update is a routine php artisan migrate during the next deploy. The strategic point for us is that a feature as small as an unread badge can take down a service as history accumulates, so message-volume growth belongs in capacity planning rather than being treated as a background concern.

For engineering — the substance:

  • Root cause, stated plainly. MaxMessageService::totalUnreadCount() and UnreadCountController filter on direction = 'in' and read_at is null. None of the existing indexes — (max_chat_id, created_at), (user_id, chat_id, created_at), (created_at) — cover that predicate, so the count ran as a sequential scan. markRead() was never the problem; it leads with max_chat_id and still uses the existing index.
  • The fix. A new composite index max_chat_messages_unread_index on (direction, read_at), added in a separate additive migration (0000_02_000003_add_unread_index_to_max_chat_messages.php). It serves both the navigation badge and the JSON unread endpoint. A partial index on read_at is null was considered and rejected as non-portable to MySQL.
  • Upgrade safety. up() guards on Schema::hasIndex, so it is idempotent and will not fail where a host application already added an equivalent index. down() drops it cleanly. No public signatures changed, no config keys or values changed, no translation keys touched.
  • Verification. MaxChatMessagesSchemaTest asserts index presence, removal on down(), re-creation on up(), and idempotency when the index already exists. Full suite: 271 tests / 628 assertions, 98.31% line coverage (989/1006), PHPStan max and PHP CS Fixer clean, composer audit clean.
  • One caveat worth naming rather than burying. The local quality gate did not run the clean-resolution step (Gate 7) because the host lacked disk space for a second vendor/; that step is delegated to CI. Also note composer audit required COMPOSER_IPRESOLVE=4 in this environment due to Packagist reachability — an environment quirk, not a package defect, but worth knowing if your CI network is similarly constrained.
  • What we should do with it. Take the patch. Then instrument unread-count latency and message-table growth, because the next scaling limit will be a query we haven't written yet.
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.
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
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk