miran/mks-support-chat
A Laravel package for adding customer support chat to your application, with ready-made models, migrations, and routes for conversations and messages so you can quickly build a simple help desk or live chat experience.
Install and publish assets.
composer require miran/mks-support-chat
php artisan vendor:publish --provider="Miran\MksSupportChat\MksSupportChatServiceProvider"
php artisan migrate
Verify the published config (config/mks-support-chat.php) and the Filament plugin class in vendor/miran/mks-support-chat/src before assuming default table names — with only 12 stars and no dependents, the README is the source of truth, not your intuition.
Register the Filament plugin in your admin panel provider (app/Providers/Filament/AdminPanelProvider.php) via the ->plugin(...) chain. This is where the conversation resource and any widgets land in the sidebar.
Add the storefront widget to your layout (resources/views/layouts/app.blade.php or a dedicated component). Typically this is a Blade component or @livewire include — check whether the package ships a <x-mks-support-chat /> component or expects a manual Livewire tag. If it requires a published JS asset, add it to your Vite entry or use @mksSupportChatScripts if provided.
First use case: drop the widget into a single authenticated page (e.g. /account/orders) rather than the global layout, so you can confirm conversations appear in the Filament panel without exposing an untested widget to every visitor.
Where to look first when something is wrong: the Filament panel route (/admin → your plugin's pages), then storage/logs/laravel.log for broadcasting/auth errors, then the package's config/ and migrations/ directories.
Plugin-scoped registration. Register the plugin for the panel that should own support (likely admin, not a customer-facing panel). If you run multiple Filament panels, only the support panel needs the plugin; conversations are a back-office concern.
public function panel(Panel $panel): Panel
{
return $panel
->id('admin')
->plugin(\Miran\MksSupportChat\MksSupportChatPlugin::make());
}
Widget as a Blade slot, not a global script. Wrap the widget in a component and include it conditionally — this keeps the chat off marketing pages and lets you feature-flag it:
@auth
@if(config('features.support_chat'))
<x-mks-support-chat />
@endif
@endauth
Broadcasting wiring. A "real-time" chat package normally expects Laravel Echo + a broadcaster (Pusher, Ably, or self-hosted Reverb). Confirm which channels the package uses (private-support.{conversation} or similar) and make sure Broadcast::channel() in routes/channels.php matches — otherwise messages silently fail to appear until a page refresh. For anonymous visitors, the channel authorization callback usually needs a session-based or UUID-based check; verify the package ships one or add it yourself.
Conversation lifecycle for the admin side. Treat the Filament resource as a queue: unread → assigned → resolved. If the package exposes statuses, build custom table filters or a dashboard widget showing "unread conversations older than 5 minutes" to make the inbox actionable. If it doesn't, use a Filament action or a small custom page rather than modifying the vendor resource.
Notification glue. The package may or may not emit events. If it does (MessageReceived, ConversationStarted), listen and fan out to Slack/email/Telegram via a listener. If it doesn't, poll the conversations table with a Schedule::call and notify on new rows — pragmatic given the package's maturity.
Visitor context enrichment. Storing the current route, authenticated user ID, and locale alongside a new conversation pays off enormously. If the package has a "create conversation" hook or a model you can observe, attach context so agents see "Visitor on /checkout/payment" instead of an anonymous UUID.
Integration with existing support tooling. Don't fight the Filament resource — export or mirror conversations to your ticketing system (Front, Zendesk, Help Scout) via a queued job on ConversationClosed, so you retain a searchable archive if you later outgrow the package.
Maturity is the headline risk. 12 stars, 0 dependents. Pin the version explicitly ("miran/mks-support-chat": "1.0.*"), read the changelog before every composer update, and budget time to fork if the maintainer goes quiet. Do not put this on a load-bearing enterprise support flow without a fallback (contact form, email).
Filament version drift is the most common breakage. Filament v3 → v4 changed plugin signatures, resource APIs, and Livewire lifecycle hooks. Check the package's composer.json constraints against your installed Filament version before installing; a mismatch manifests as a blank admin page or a BindingResolutionException rather than a clean error.
Real-time ≠ real-time out of the box. Without BROADCAST_CONNECTION configured (and php artisan reverb:start or a Pusher account), the widget will look broken — messages post on reload only. Set up broadcasting in staging first, and test with two browsers and one incognito window.
Session and CSRF for anonymous visitors. A storefront widget that posts to a non-standard route can fail CSRF verification for guests whose session was regenerated (e.g. after login). If you see 419s in the logs tied to the widget, add the package's route path to VerifyCsrfToken::$except or, better, ensure the widget sends the meta CSRF token. Prefer the latter; exempting routes invites abuse.
Config caching bites publishes. After vendor:publish, php artisan config:cache will freeze old values. If you change the widget's position, colors, or channel name and nothing happens, run php artisan optimize:clear. Same for view:clear if you've overridden the widget's Blade.
Migration collisions. The published migration may create a conversations or messages table that clashes with an existing schema. Always run php artisan migrate --pretend first on an existing database, and rename tables in the migration if you're already using those names.
Rate-limit the public endpoint. Visitor-facing message routes are an open door. Wrap them with throttle:30,1 at the route level (or in a middleware group in the package config if exposed). Without it, a single visitor can flood your admin panel.
Privacy and retention. The widget stores visitor IPs, user agents, and message content — all personal data under GDPR/CCPA. Add a retention command (Conversation::where('resolved_at', '<', now()->subDays(90))->delete()) and confirm the storefront discloses chat data collection in your privacy policy.
Styling conflicts. A storefront widget usually ships its own scoped CSS but will still collide with Tailwind purges or a global z-index stack. If the launcher button disappears behind your sticky header, raise its z-index via a published CSS override rather than editing vendor files. Publish assets and own the copies.
Debugging message delivery: check three things in order — (1) the network tab for a failed POST, (2) storage/logs/laravel.log for broadcast auth failures, (3) the jobs table if a queue connection is set (broadcasting can be queued). Nine out of ten "messages don't appear" reports are a missing npm run dev on the Echo client side.
Extension points to prefer: service container bindings (if the package exposes an interface for the widget or the conversation model), Filament resource extension via ->table()->modifyQueryUsing(...) rather than class edits, and event listeners over method overrides. If the package exposes no interfaces, keep a thin adapter class in your app (App\Support\Chat\ChatAdapter) wrapping the package — that single seam makes swapping packages a week of work instead of a quarter.
How can I help you explore Laravel packages today?