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.

Maintainers

Package info

github.com/rhishi-kesh/QuickTalk

pkg:composer/rhishi-kesh/quick-talk

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-02-25 11:00 UTC

This package is auto-updated.

Last update: 2026-03-01 09:48:08 UTC


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 credentials
PUSHER_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