rhishi-kesh / quick-talk
QuickTalk is a lightweight, fast, and developer-friendly chat package built for modern applications. It makes real-time messaging simple to integrate, scalable to grow, and flexible to customize.
Requires
- php: ^8.2
- illuminate/console: ^11.0|^12.0
- illuminate/filesystem: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
README
QuickTalk is a powerful, production-ready real-time chat system for Laravel applications. It provides private messaging, group chat, typing indicators, reactions, attachments, notifications, and broadcasting support using Reverb or Pusher.
β¨Features
- π¬ One-to-one messaging
- π₯ Group conversations
- β‘ Real-time updates (Reverb / Pusher)
- βοΈ Typing indicators
- π Message reactions
- π File attachments
- π Notifications
- π’ Online status tracking
- π Sanctum API authentication support
- π§© Easy installation command
- ποΈ Clean architecture
π Requirements
- PHP 8.2+
- Laravel 11^
- MySQL
- Laravel Sanctum
- Broadcasting driver (Reverb or Pusher)
πCore Contributor
π Installation
Install via Composer:
composer require rhishi-kesh/quick-talk
Run the installer:
php artisan install:quicktalk
Follow the interactive prompts to choose:
- Broadcasting stack (Reverb / Pusher)
- Authentication setup (optional)
βοΈ Manual Setup (Required)
1οΈβ£ Add Avatar Column to Users Table
Add this to your users migration:
$table->string('avatar')->nullable();
2οΈβ£ Add Seeder to DatabaseSeeder
Open:
database/seeders/DatabaseSeeder.php
Add:
$this->call(UserSeeder::class);
Then run:
php artisan migrate php artisan db:seed
3οΈβ£ Create Storage Symlink
Required for serving uploaded images:
php artisan storage:link
4οΈβ£ Register Chat Routes
Open bootstrap/app.php and add:
->withRouting( api: __DIR__ . '/../routes/api.php', channels: __DIR__ . '/../routes/channels.php', then: function () { Route::middleware('api') ->prefix('api') ->group(base_path('routes/chat_auth.php')); Route::middleware('api') ->prefix('api') ->group(base_path('routes/chat.php')); } )
5οΈβ£ Enable Broadcasting Routes
Still in bootstrap/app.php, add:
->withBroadcasting(__DIR__ . '/../routes/channels.php', ['prefix' => 'api', 'middleware' => ['auth:sanctum']],)
6οΈβ£ User Model Configuration
Update your App\Models\User model
Required Traits
use Laravel\Sanctum\HasApiTokens; use HasApiTokens;
Required Imports
use Illuminate\Support\Str;
Fillable Fields
protected $fillable = [ 'name', 'email', 'password', 'avatar', ];
Helper: Initials
public function initials(): string { return Str::of($this->name) ->explode(' ') ->take(2) ->map(fn($word) => Str::substr($word, 0, 1)) ->implode(''); }
Chat Relationships
// Messages sent by this user public function sentMessages() { return $this->hasMany(Message::class, 'sender_id'); } // Messages received by this user (for direct/private chats only) public function receivedMessages() { return $this->hasMany(Message::class, 'receiver_id'); } // Conversations where user is a participant public function participants() { return $this->morphMany(Participant::class, 'participant'); } // Conversations where user is a participant (through Participant model) public function conversations() { return $this->hasManyThrough( Conversation::class, Participant::class, 'participant_id', // Foreign key on Participant table 'id', // Local key on Conversation table 'id', // Local key on User table 'conversation_id' // Foreign key on Participant table )->where('participant_type', self::class); } // Message reactions made by this user public function messageReactions() { return $this->hasMany(MessageReaction::class); } // Read/delivery status records public function messageStatuses() { return $this->hasMany(MessageStatus::class); } // Firebase tokens for push notifications public function firebaseTokens() { return $this->hasOne(FirebaseToken::class); }
π‘ Broadcasting Setup
Ensure broadcasting is configured.
For Reverb
Follow Laravel Reverb setup instructions.For Pusher
Set credentialsPUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=
βΆοΈ Start Project Server
Use bellow commends
php artisan serve
npm run dev
php artisan reverb:start
π Setup Echo Js on your frontend
In your frontend, configure Laravel Echo to connect to WebSockets.
<script src="https://cdn-script.com/ajax/libs/jquery/3.7.1/jquery.min.js" type="text/javascript"></script> <script> $(document).ready(function() { Echo.private('chat-channel.' + 1).listen('.message.event', (e) => { console.log('Message Receive:', e); }) Echo.private('conversation-channel.' + 1).listen('.conversation.event', (e) => { console.log('Conversation and Unread Message count:', e); }) Echo.join('online-status-channel') .here(users => { console.log('Active Users:', [users]); }) .joining(user => { console.log('User Joined:', [user]); }) .leaving(user => { console.log('User Left:', [user]); }); const typingInput = document.getElementById('typingInput'); const typingImage = document.getElementById('typingImage'); let typingTimeout; // Send typing event when user types typingInput.addEventListener('input', function () { Echo.private('typing-indicator-channel.1') .whisper('typing', { user: 'RKB' }); console.log('Typing Indicator Sent'); }); // Listen for typing event from others Echo.private('typing-indicator-channel.1') .listenForWhisper('typing', (e) => { console.log('Typing Indicator Received:', e.user); // Show typing image typingImage.style.display = 'block'; // Clear previous timeout if user keeps typing clearTimeout(typingTimeout); // Hide typing image 2 seconds after last typing event typingTimeout = setTimeout(() => { typingImage.style.display = 'none'; }, 1000); }); }); </script>
π API Routes
You Can Explore the API documentation from Here (https://documenter.getpostman.com/view/39612169/2sB34kDeK1)
π€ Contributing
- Contributions are welcome!
- Feel free to submit issues and pull requests.
π License
MIT License