musonza/chat: a chat system where the participants are your models
A Laravel chat package. You can use this package to create a chat/messaging Laravel application.
At a glance
- What is it?
- musonza/chat is a Laravel package that gives an application conversations, participants, messages, read receipts, reactions and direct messages, where the people in the chat are any Eloquent models you like rather than a built-in user table. It is MIT licensed, has a demo application, and its README still describes a Laravel version from a decade ago.
- Who is it for?
- Adopt musonza/chat if you are adding chat to a Laravel application and your participants are not all one kind of user, since the Messageable trait lets Parents, Students, Professors or devices take part in the same conversation. Do not adopt it expecting a hosted service or a frontend, because the package is the server-side data model and API, and the demo application is the reference for the interface.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 113 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Participants are models, not a users table
The package description is short: a Laravel chat package for creating a chat or messaging application, and the README opens with the promise to create a Chat application for your multiple Models. That word Models is the design. The system you are modelling, say a school, has Parents, Students and Professors, and the package does not require any of them to be users of your application or to share a base class beyond one trait. The example in the documentation is exactly that, a mix of model types, and the documentation says you can mix them freely. That flexibility is the reason to reach for this package rather than writing a chat system against a single User model, and it is also the reason the participant details need a uniform representation, since a Parent and a Professor do not have the same columns. The project also links a simple demo application as a starting point for the interface, and it links a book on Laravel package development, which tells you the author is trying to teach the pattern rather than only ship the code.
One trait, and an accessor for uniform participant details
Adding a model to the chat system is a single trait. You add the Musonza\Chat\Traits\Messageable trait to any model you want to be able to take part in conversations:
use Illuminate\Database\Eloquent\Model;
use Musonza\Chat\Traits\Messageable;
class Bot extends Model
{
use Messageable;
}Because different models have different data, the package gives you a uniform way to represent a participant. You call getParticipantDetails on the model, and with a name column on your model it returns a default array of the form ['name' => 'column_value']. If that is not enough, you override it with an Eloquent accessor that returns an array with as much as you need:
public function getParticipantDetailsAttribute()
{
return [
'name' => $this->someValue,
'foo' => 'bar',
];
}That accessor is the extension point for the whole participant concept. A user interface that renders an avatar, a display name and a link needs exactly this array, and the package will not guess at it, which is the right call when the models involved are unrelated. It also means the shape of a participant is defined once per model rather than per conversation, so a conversation can hold a mix of participants without any of them knowing about the others.
Conversations come in four flavours, and two of them lock you in
Creating a conversation passes an array of models as participants, and the shape of the conversation is then chosen with a chain. The basic form is Chat::createConversation($participants). A conversation can be made private or public, where the public form is the same call with makePrivate(false), and it can be made direct, either after creation with makeDirect() or before it with Chat::makeDirect()->createConversation($participants). The direct case carries a constraint that is worth knowing before you design around it: you will not be able to add additional participants to a direct conversation, and you cannot remove a participant from one. That is the right semantic for a one-to-one message, and it is enforced rather than merely discouraged. Conversations can also be named, which the documentation ties to chatrooms and to any scenario where you need to look up a conversation by a human-readable identifier, and the name column is nullable so existing conversations and unnamed ones are unaffected:
$participants = [$model1, $model2];
$conversation = Chat::createConversation($participants, [], 'general');
echo $conversation->name; // 'general'Beyond creation, the API surface covers the rest of a messaging product. The table of contents lists reading a conversation by id with Chat::conversations()->getById($id), updating conversation details such as title and description, sending a text message, sending a message of a custom type, fetching a message by id, getting the sender, marking a message as read, marking a whole conversation as read, an unread messages count, deleting a message, message reactions, cleaning up deleted messages, clearing a conversation, and a long set of conversation queries: a participant's conversations, the conversation between two participants, the conversations common to several participants, adding and removing participants, and the participants or conversation partners in a conversation.
Reading messages: filtering, cursors and pagination
The read side of the package is where the design shows. You can get the messages in a conversation, filter messages by type, and get messages with cursor pagination rather than offset pagination, which matters for a chat transcript that grows and for a client that polls for new messages without skipping or repeating rows. There is also a filter for conversations by name, a way to get public conversations for discovery, a way to get recent messages, and a way to get the participation entry for a given model in a conversation, along with the ability to update participation settings. That last pair is the mechanism behind per-user settings such as a muted conversation, and it exists per model rather than per application, which is consistent with the participant model. Two further sections in the documentation are worth singling out. Data Transformers are covered explicitly, which tells you the package is aware that the shape of a message or a conversation is not one size fits all and expects you to transform it at the boundary. Message Encryption is also its own section rather than a passing mention, which for a chat package is the feature that decides whether the stored messages are private to your database or not.
Installation is three commands, and the routes start hidden
The install is the usual Composer and Artisan pair. You require the package:
composer require musonza/chatThen you publish the assets, which publishes the database migrations and a configuration file called musonza_chat.php into the Laravel config folder:
php artisan vendor:publish --provider="Musonza\Chat\ChatServiceProvider"Configuration is read from that published file, and the migrations are applied with:
php artisan migrateOne setting needs attention before anything works. The package includes routes for conversations, conversation participants and messaging, and those routes are hidden by default; to enable them you change should_load_routes to true, and the documentation is emphatic that you make sure to configure the middleware correctly. That is a sensible default for a package that exposes a messaging API, since a route that creates conversations and reads messages has no business being publicly reachable by default, and the fact that the setting is off rather than on is a small sign of care. The repository layout is conventional: src/ for the package, config/ and database/ for its assets, tests/ with a phpunit.xml.dist, a phpstan.neon for static analysis, and a pint.json for code style.
Where the package is the wrong tool
Four limits are worth naming. The first is that the documentation lags the code. The introduction says the package adds a chat system to your Laravel ^5.4 application, while the current release line is 6.15.2, published on 2026-07-04 with v6.15.1 and v6.15.0 before it, so the sentence in the introduction is a decade old and the supported Laravel range has to be read from the current composer.json instead. That is a small thing, but in a package with a large API surface it is the kind of thing that sends you down the wrong path. The second is that this is the server-side half of a chat product and nothing more. There is no interface, no notification pipeline, no presence and no typing indicator, so the work of building the actual chat experience is still ahead of you, and the demo application exists precisely because that part is not in the box. The third is the model-centric design. Making every model a participant is elegant, but it means chat concepts are attached to your domain models rather than to a separate user abstraction, which is a decision you cannot easily reverse once your database has grown. The fourth is the honest one about scope: a package that stores conversations and messages is not a real-time transport, so if you need delivery receipts, encryption in transit or a presence system, none of that is here, and the message encryption section should be read carefully to see exactly what it covers, since encrypting stored messages and encrypting a channel are different problems.
Editorial conclusion
Adopt musonza/chat if you are adding chat to a Laravel application and your participants are not all one kind of user, since the Messageable trait lets Parents, Students, Professors or devices take part in the same conversation. Do not adopt it expecting a hosted service or a frontend, because the package is the server-side data model and API, and the demo application is the reference for the interface. Before you install, read the current composer.json for the supported Laravel versions rather than trusting the introduction, which still says Laravel ^5.4, and check the message encryption section, because the current release line is 6.15.2 from 2026-07-04 with the last push on the same day.
Frequently asked questions
What does the musonza/chat package do?
It is a Laravel package for creating a chat or messaging application, where the participants are any of your Eloquent models rather than a single user table. It covers conversations, participants, messages, read receipts, reactions, direct messages and cursor pagination.
How do I install musonza/chat?
Run `composer require musonza/chat`, then `php artisan vendor:publish --provider="Musonza\Chat\ChatServiceProvider"` to publish the migrations and the musonza_chat.php configuration file, then `php artisan migrate` to create the tables.
How do I make my own model able to chat?
Add the Musonza\Chat\Traits\Messageable trait to the model, and optionally define a getParticipantDetailsAttribute accessor returning an array so the package can represent participants of different model types uniformly.
Are the package routes enabled by default?
No. The routes for conversations, conversation participants and messaging are hidden by default, and you enable them by setting should_load_routes to true while configuring the middleware correctly.
What licence is musonza/chat released under?
The MIT Licence, with the LICENSE file at the repository root. The current release is v6.15.2 from 2026-07-04, with v6.15.1 from 2026-06-30 and v6.15.0 from 2026-05-09, and a demo application is published separately as musonza/chat-demo.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/musonza-chat)Was this useful?