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

Nova Chat Laravel Package

binarcode/nova-chat

Nova Chat adds real-time messaging to Laravel Nova, letting admins and users chat directly inside the dashboard. It provides ready-made chat UI components and backend support for conversations, so you can wire up in-app communication without building it from scratch.

View on GitHub
Deep Wiki
Context7

Getting Started

Check compatibility before you write a line of code. Release 1.2.0 adds PHP 8 support, which is the first movement on this package since the May 2021 tag — so the composer constraint story is now "PHP 8 may install, Nova version is still the question." The tool assets are still from the Nova 3 era (Vue 2 tooling, laravel-nova npm package, mix.js build), and nothing in the release notes suggests that changed. Nova 4+ moved the tool stack to Vue 3 and Inertia, so expect the prebuilt tool assets to fail on modern Nova even though composer require now succeeds on PHP 8. Open composer.json first and read the laravel/nova and php constraints — that single file tells you whether this is a five-minute install or a fork-and-port project.

composer require binarcode/nova-chat

# Confirm what actually resolved and how PHP 8 support was declared
composer show binarcode/nova-chat

# Discover what's publishable rather than guessing provider/tag names
php artisan vendor:publish

# Usually: config, migrations, and the compiled tool assets
php artisan vendor:publish --tag=nova-chat-config
php artisan vendor:publish --tag=nova-chat-migrations
php artisan migrate

Register the tool in app/Providers/NovaServiceProvider.php:

public function tools()
{
    return [
        new \BinarCode\NovaChat\NovaChat,
    ];
}

Then wire broadcasting — this package is a thin UI over Laravel Echo, so nothing works until BROADCAST_DRIVER=pusher (or a Pusher-protocol server like beyondcode/laravel-websockets) is set, config/broadcasting.php has credentials, and config/nova-chat.php points at the same values. The config file is the first thing to read: it's where the user model, conversation/message models, and channel names are resolved.

First use case: internal staff-to-staff chat inside the Nova admin — a support team messaging each other while looking at the same order record. Log in to /nova, open the Chat tool from the sidebar, start a conversation with another Nova user, open a second browser as that user, and confirm the message arrives without a refresh. If it doesn't, the problem is broadcasting auth or the stale Vue 2 bundle, not the message schema (see Gotchas).

Where to look when something is off, in order: config/nova-chat.php → the published migrations (table names and column types) → routes/channels.php (authorization callbacks the package expects you to define) → resources/js/tool.js in the package source (what events the Vue component listens for).

Implementation Patterns

Treat the package as three separate things and adopt only what you need: (1) a schema for conversations/messages/participants, (2) broadcast events, (3) a Nova Vue tool. Most teams get more value from (1) and (2) than from (3) — and on Nova 4+, (3) is the part you'll be rewriting anyway.

Resolving users when you don't use App\Models\User. Point the config's user-model key at your model and make sure it implements whatever interface/contract the package expects (check src/Contracts or the type hints in the config). If your users are multi-tenant or soft-deleted, add a global scope check — a chat that leaks names across tenants is a compliance problem, not a bug.

Sending messages from application code, not just the UI. The durable pattern is: your domain events write into the same messages table the tool reads, so chat becomes an audit trail of system activity ("Order #1042 refunded by Jane"). Wrap it:

// app/Services/ChatNotifier.php
public function systemMessage(Conversation $conversation, string $body): Message
{
    return tap($conversation->messages()->create([
        'user_id' => null,          // or a dedicated "system" user
        'body'    => $body,
        'type'    => 'system',
    ]), fn ($m) => broadcast(new MessageCreated($m))->toOthers());
}

Then call it from listeners. Keep the broadcast dispatch in a queued listener so a slow websocket never blocks a checkout.

Channel authorization belongs in routes/channels.php, and you should own it explicitly rather than trusting defaults:

Broadcast::channel('nova-chat.conversation.{conversationId}', function ($user, $conversationId) {
    return $user->conversations()->whereKey($conversationId)->exists();
});

Guard alignment is the integration tip that saves the most hours. Nova authenticates through its own nova guard. Your channel callbacks and the /broadcasting/auth endpoint must resolve the Nova user, not the web user:

Broadcast::channel('nova-chat.conversation.{id}', fn ($user, $id) => ..., ['guards' => ['web', 'nova']]);

Presence and read state. If the package ships read receipts or online indicators, they're typically driven by Echo here/joining/leaving events plus a cache or last_seen_at column. Don't cache presence in the default cache store if you run multiple app servers with the file driver — use Redis, or presence will flicker depending on which node the user hits.

Testing. Fake the broadcast side and assert persistence:

Event::fake([MessageCreated::class]);

$this->actingAs($user, 'nova')
     ->postJson("/nova-vendor/nova-chat/conversations/{$c->id}/messages", ['body' => 'hi'])
     ->assertCreated();

Event::assertDispatched(MessageCreated::class);
$this->assertDatabaseHas('messages', ['conversation_id' => $c->id, 'body' => 'hi']);

Verify the actual route prefix from php artisan route:list | grep -i chat — Nova tools mount under /nova-vendor/{tool} by convention, but confirm.

Deployment. Broadcasting needs a running queue worker (ShouldBroadcast events are queued by default if the event implements ShouldBroadcast), and if you self-host with laravel-websockets, a supervised php artisan websockets:serve process plus a reverse proxy with websocket upgrade headers. Add both to your deploy checklist — chat "silently not updating in production" is almost always a missing worker or a proxy stripping Upgrade.

Scoping the tool by role. Register the tool conditionally with canSee() so non-support roles never see the sidebar entry, and pair that with the channel authorization above. UI hiding is not access control.

Gotchas and Tips

The maintenance risk is still the headline gotcha, but it's now a slightly different shape. A 1.2.0 with only "PHP8 support" in the notes tells you the package is installable on PHP 8, not that it is maintained. Still 15 stars, still 0 dependents, still a four-year gap with one commit-sized release. That means: no evidence of Nova 4/5 support, no security patches, and nobody else has hit (and documented) the edge cases you're about to hit. Budget for it as a fork, not a dependency — vendor it into packages/ with a path repository, or copy the migrations and models into your app and drop the composer requirement once you're stable.

"PHP8 support" is vague — verify what it actually means before trusting it. It could be a constraint bump ("php": "^7.4|^8.0") with zero code changes, or actual deprecation fixes. Diff composer.json and the source between the previous tag and 1.2.0. If it's only a constraint bump, you'll still see strlen(): Passing null to parameter #1 and "Creation of dynamic property is deprecated" notices on 8.2/8.3. Test on your exact PHP minor version, not just "8.something" — Laravel 10/11 apps on 8.2+ are the most likely to surface this.

Nova 4/5 frontend breakage remains the first wall. The tool ships compiled Vue 2 assets. Symptoms: blank tool panel, console errors about undefined Vue components, or laravel-nova peer-dependency conflicts during npm install. The rebuild path is to port resources/js/tool.js to the Nova 4 tool scaffolding (Vue 3, nova.mix.js) — realistically a day's work, and the reason many teams just write a small custom tool around their own models.

Assets must be published and rebuilt. php artisan nova:publish after install; if you edit any Vue component, re-run the package's npm run dev/prod in the package directory and republish, or Nova keeps serving the stale bundle. Clear public/vendor/nova-chat and browser-cache hard when changes don't appear. After upgrading to 1.2.0 specifically, republish rather than assuming the new release shipped new compiled assets — the notes only mention PHP.

403 on /broadcasting/auth is the #1 runtime failure. Causes, in order of likelihood: guard mismatch (web vs nova), BROADCAST_DRIVER=log left in .env, credentials duplicated between config/broadcasting.php and config/nova-chat.php with the two disagreeing, or config:cache holding an old config. php artisan config:clear first, then check the browser network tab for the auth request and its response body.

Migration conflicts and key types. If you already have conversations/messages tables, rename via the published migration before running it. If your users table uses UUIDs or ulid, the package's foreignId('user_id') columns will fail or silently mismatch — edit the migration to foreignUuid/ulid and update the models' $keyType/$incrementing. This is the most common reason the install "works" but conversations never resolve a participant.

XSS in message rendering. Chat bodies are user-supplied. If the Vue component renders with v-html, sanitize server-side (strip tags or run a purifier) rather than trusting the client. Also cap message length and add basic rate limiting on the send route — a chat endpoint with no throttle is a cheap way to fill your DB.

Config caching and env drift. Everything in config/nova-chat.php that reads env() must stay in the config file (not in the service provider) or config:cache will return null in production. If chat worked locally and not on the server, this is the second suspect after broadcasting auth.

Upgrade checklist for 1.2.0 specifically: composer update binarcode/nova-chat → php artisan vendor:publish --force only for tags you've intentionally customised (re-publishing config will clobber your edits) → diff the published migrations against your DB → php artisan nova:publish → php artisan config:clear && php artisan view:clear → smoke-test one live message in staging. Because the release notes mention only PHP support, treat it as a compatibility bump, not a fix for the Nova 4/5 asset problem.

Extension points, in order of usefulness: the config's model bindings (swap in your own Conversation/Message subclasses), the published migrations (schema changes), the broadcast events (add payload fields for your frontend), and finally the Vue tool component itself (fork it). If you find yourself needing the fourth, you've outgrown the package — at that point a hand-rolled messages table + ShouldBroadcast event + a ~200-line Nova tool is less total work than maintaining a 2021 fork.

Debugging checklist for "messages save but don't appear live": BROADCAST_DRIVER is not log/null → queue worker is running → Echo is actually initialized in the Nova layout (the package's tool.js should call new Echo(...); if your Nova app has its own Echo bootstrap you may get two instances or none) → channel name in the event matches the channel the client subscribed to, character for character → check storage/logs/laravel.log and the browser console for the broadcast response. Nine times out of ten it's the queue worker or the guard.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console