asignua/filament-chat
Filament Chat adds real-time messaging to Filament admin panels. Drop-in chat components let you build conversations, direct messages, and threaded chats with a clean, native Filament UI, ideal for support inboxes, team communication, or customer chat inside your app.
conversation_participants.last_read_at makes read receipts and per-participant unread badges a config-and-UI decision rather than a schema project. This unlocks concrete roadmap items: unread-first inbox ordering, "last read" indicators, and — importantly for internal support use cases — response-time and backlog reporting off a field we now own.filament-chat-incoming browser event (ChatDock::EVENT_INCOMING, payload {conversation, message, open}) decouples "tell the user something arrived" from notifications.toasts. We can ship a sound or desktop notification as a product choice, and let users opt in, without committing to websockets, a queue worker tier, or a third-party realtime vendor. That is a scheduling decision (days, not a sprint) and a cost decision (no new infra line).ChatService::changed($conversation) deliberately notifies members without creating a message or a bell. This is the primitive behind "this conversation changed, re-render it" — typing-ish indicators, "someone is editing/marking up the image", collaborative annotation. It also gives us a notification-fatigue lever: we can distinguish signal (re-render) from interrupt (bell/toast) and tune each separately.setRelation fix means messages found via a conversation arrive with conversation already loaded, so extensions reading $message->conversation in a hook no longer lazy-load per message — previously a hard crash under Model::preventLazyLoading(). Product consequence: we can turn on strict lazy-loading prevention (a performance/quality guardrail we'd otherwise defer) and trust chat history rendering to not degrade linearly with conversation length.last_read_at migration is additive and optional (ChatConfig::readTimeAvailable()); without it the chat behaves exactly as before. That lets us take the upgrade for the bug fix and event hooks now, and treat read receipts as a separately-scheduled, separately-communicated feature — no forced flag day.Adopt when most of these hold:
Look elsewhere when any of these are true:
To executives: This is a small, low-risk dependency that gives us in-product messaging without building it. The new version adds read receipts and desktop/sound notifications without new servers or a realtime vendor — so the engagement features we scoped are now a UI-and-config effort, not an infrastructure project. The upgrade is backward compatible and the one schema change is optional, so we can ship the reliability fix immediately and treat read receipts as a separately-approved increment. Cost of ownership stays low; the main strategic caveat is that this is an internal-tooling-grade chat, not a customer support platform — if we later want a public support channel with SLAs and routing, that's a buy decision, not an extension of this.
To engineering: Upgrade is safe — the setRelation fix removes an N+1 that crashed under Model::preventLazyLoading(), and both new capabilities are additive. ChatService::changed() gives us a signal channel separate from notifications (re-render without a bell); the filament-chat-incoming DOM event gives us sound/desktop alerts without a socket and independent of notifications.toasts; last_read_at is a third, optional migration gated by ChatConfig::readTimeAvailable(), so no forced migration on deploy. Please land the upgrade with the lazy-loading guard enabled in CI so the fix is actually exercised, and confirm our extensions read $message->conversation rather than re-querying.
How can I help you explore Laravel packages today?