Building a Real-time Chat App Using Laravel, Vue.js, and Pusher: Complete Tutorial

Building a real-time chat application can feel overwhelming, especially when ensuring smooth and responsive communication. However, with Laravel, Vue.js, and Pusher, you can create a reliable and interactive chat app effortlessly.

In this blog, we’ll walk you through the complete process, from setting up the backend with Laravel to designing a dynamic frontend with Vue.js. Plus, we’ll also see how Laravel developers integrate them for the real-time updates using Pusher. By the end, you’ll have a working real-time chat application. So, let’s dive in!

Prerequisites to Begin With

Before diving into building a real-time chat application ensure you have the following tools and knowledge ready for a smooth development process:

  • PHP 8.3 (or higher) installed on your system.
  • Node.js and NPM installed to manage dependencies and run the Vue.js frontend.
  • Composer installed globally for managing PHP dependencies.
  • A Pusher account—sign up here if you don’t already have one.
  • A basic understanding of WebSockets and how they enable real-time communication.
  • Familiarity with the Vue.js framework is helpful but not mandatory.

Need help with Laravel and real-time functionality?

How to Build Real time Chat App Using Laravel, Vue.js, and Pusher?

Follow these steps to set up the backend for your Laravel-based real-time chat application. We’ll guide you through creating the project, scaffolding authentication, configuring Pusher for real-time communication, setting up the database model, and preparing the event broadcast system.

Backend Setup for a Real-Time Chat App

Follow these steps to set up the backend for your Laravel-based real-time chat application. We’ll guide you from creating the project to setting up the database model, and preparing the event broadcast system. Here are the stepwise process you can follow:

Step 1: Scaffold a New Laravel Project

Begin by creating a fresh Laravel project. Open your terminal and run the following commands:

composer create-project laravel/laravel chat-app
cd chat-app

Next, install Laravel Breeze for scaffolding authentication:

composer require laravel/breeze

Once Laravel Breeze is installed, set up authentication by running the following commands:

php artisan breeze:install
npm install
npm run dev

Follow the prompts, and proceed with the necessary selections.

Step 2: Install and Configure WebSocket and Event Broadcasting

After scaffolding authentication, we’ll set up WebSocket and event broadcasting. Run the following command to add the necessary configuration files:

php artisan install:broadcasting

This command will generate two key configuration files:

  • channels.php in the routes folder
  • broadcasting.php in the config folder

These files manage WebSocket connections and install the required client libraries (Laravel Echo and pusher-js). After that, start your application server by running:

php artisan serve

Once the server is running, visit http://localhost:8000/ in your browser to see the default Laravel welcome page. You’ll have the option to log in or register.

Step 3: Configure Pusher

Pusher is a cloud service that simplifies adding real-time functionality to your app. To configure Pusher:

composer require pusher/pusher-php-server
  • Create a new Pusher app via the Pusher dashboard by clicking on Create App under Channels.
  • Once created, find your App ID, App Key, Secret, and Cluster in the Pusher dashboard.

Now, open the .env file located in the root of your Laravel project and add the following configuration values (replace the placeholder values with your actual credentials):

PUSHER_APP_ID=<your_pusher_app_id>
PUSHER_APP_KEY=<your_pusher_app_key>
PUSHER_APP_SECRET=<your_pusher_app_secret>
PUSHER_APP_CLUSTER=<your_pusher_app_cluster>
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
BROADCAST_CONNECTION=pusher

This configuration connects your application to Pusher’s cloud servers and sets it as the broadcast driver.

Step 4: Set Up the Database Model and Migration

Now that the backend and WebSocket setup are done, let’s define the database schema and model for storing chat messages. Here is how:

First create the ChatMessages model along with its migration file:

php artisan make:model -m ChatMessages

Update the generated ChatMessages.php model located in app/Models:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ChatMessages extends Model
{
    use HasFactory;
    protected $fillable = ['sender_id', 'receiver_id', 'text'];
    public function sender()
    {
        return $this->belongsTo(User::class, 'sender_id');  
    }
    public function receiver()
    {
        return $this->belongsTo(User::class, 'receiver_id');
    }
}

In the above model, we define the fillable fields (sender_id, receiver_id, and text) and the relationships between the ChatMessages model and the User model.

Next, update the migration file (create_chat_messages_table.php) in the database/migrations folder:

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('chat_messages', function (Blueprint $table) {
            $table->id();
            $table->foreignId('sender_id')->constrained('users');
            $table->foreignId('receiver_id')->constrained('users');
            $table->string('text');
            $table->timestamps();
        });
    }
    public function down(): void
    {
        Schema::dropIfExists('chat_messages');
    }
};

This migration defines the schema for storing chat messages. It includes:

  • An id for each message.
  • sender_id and receiver_id foreign keys linking to the users table.
  • A text column for storing the message content.
  • timestamps for recording the message creation and update times.

Now perform the migration to apply the changes to your database:

php artisan migrate

Step 5: Set Up Event Broadcasting

To set up event broadcasting, first configure the broadcast channel. Open routes/channels.php and update it as follows:

<?php
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('chat', function ($user) {
    return Auth::check();
});

Then, create the MessageSent event that will be broadcasted to clients. Run the following command:

php artisan make:event MessageSent

Update the generated MessageSent.php event in the app/Events folder:

<?php
namespace App\Events;
use App\Models\ChatMessages;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class MessageSent implements ShouldBroadcast
{
    use Dispatchable, SerializesModels;
    public $user, $chatMessage;
    public function __construct(User $user, ChatMessages $chatMessage)
    {
        $this->user = $user;
        $this->chatMessage = $chatMessage;
    }
    public function broadcastOn(): array
    {
        return [
           new PrivateChannel("chat"),
        ];
    }
    public function broadcastWith()
    {
        return ['message' => $this->chatMessage];
    }
}

The MessageSent event broadcasts the message data to the chat private channel, allowing real-time updates.

Step 6: Create the Chat Controller

Now, create a controller in Laravel that handles the application logic for sending and receiving chat messages. To create the controller run the following command:

php artisan make:controller ChatController

Next, open the ChatController.php file in app/Http/Controllers and update it as follows:

<?php
namespace App\Http\Controllers;
use App\Events\MessageSent;
use App\Models\ChatMessages;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ChatController extends Controller
{
    public function index(User $user)
    {
        $messages = ChatMessages::with(['sender', 'receiver'])
            ->whereIn('sender_id', [Auth::id(), $user->id])
            ->whereIn('receiver_id', [Auth::id(), $user->id])
            ->get();
        return response()->json($messages);
    }
    public function store(User $user, Request $request)
    {
        $message = ChatMessages::create([
            'sender_id' => Auth::id(),
            'receiver_id' => $user->id,
            'text' => $request->message,
        ]);
        broadcast(new MessageSent($user, $message))->toOthers();
        return response()->json($message);
    }
}

The index() method fetches messages between the authenticated user and the selected user, while store() creates a new message and broadcasts it.

Step 7: Update Routes

Finally, define the routes to handle the chat functionality. Open routes/web.php and add the following routes:

use App\Http\Controllers\ChatController;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
Route::get('/dashboard', function () {
    return view('dashboard', [
        'users' => User::where('id', '!=', Auth::id())->get()
    ]);
})->middleware(['auth', 'verified'])->name('dashboard');
Route::get('/chat/{user}', function (User $user){
    return view('chat', [
        'user' => $user
    ]);
})->middleware(['auth', 'verified'])->name('chat');
Route::resource('messages/{user}', ChatController::class, ['only' => ['index', 'store']])->middleware(['auth']);

These routes set up the chat application endpoints, allowing users to view their dashboard, access chat with a specific user, and send/receive messages.

By following these steps, you’ll have a backend setup ready for a real-time chat app with Laravel, Vue.js, and Pusher. The app will allow users to send and receive messages in real time, using WebSockets.

Frontend Setup for a Real-Time Chat App

Now that the backend of the real-time chat application is complete, it’s time to set up the user interface. Follow these step-by-step instructions to configure the frontend using Vue.js, Pusher, and Laravel Echo.

Step 1: Install Vue.js

To begin, install Vue.js and the required plugins for handling Vue components. Run the following commands:

npm install vue vue-loader
npm install --save-dev @vitejs/plugin-vue

This installs Vue.js, its loader, and the Vite plugin to support Vue components.

Step 2: Create a Vue.js Component

  • Navigate to the resources/js directory and create a new folder named components.
  • Inside the components folder, create a file named ChatBox.vue.
  • Add the following code to the ChatBox.vue file:
<template>
    ...
</template>
<script>
    ...
</script>
<style scoped>
    ...
</style>

This component includes a chat interface with input and display areas. Messages are conditionally styled to distinguish between sent and received messages.

Step 3: Update the Echo Configuration

Update the resources/js/echo.js file to configure Laravel Echo with Pusher. Replace its content with:

import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
    forceTLS: true
});

This setup connects the application to the Pusher service using the credentials defined in the .env file.

Step 4: Set Up the App.js File

Replace the content of resources/js/app.js with:

import './bootstrap';
import { createApp } from 'vue';
import ChatBox from './components/ChatBox.vue';
createApp({})
    .component('chat-box', ChatBox)
    .mount('#app');

This initializes the Vue application, registers the ChatBox component, and mounts it to the #app element in your Blade templates.

Step 5: Configure Vite

To ensure Vite processes Vue.js components correctly, update the vite.config.js file in the root directory with the following:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
    resolve: {
        alias: {
            vue: 'vue/dist/vue.esm-bundler.js',
        },
    },
});

This configuration ensures Vue components are recognized and bundled correctly during development and build stages.

Step 6: Update the Blade Templates

For updating the dashboard template, go to resources/views/dashboard.blade.php and add the following code:

<x-app-layout>
    ...
    <div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
        @foreach ($users as $user)
            <div class="p-6">
                <a href="{{ route('chat', $user) }}">
                    <div>{{ $user->name }}</div>
                    <div>{{ $user->email }}</div>
                </a>
            </div>
        @endforeach
    </div>
</x-app-layout>

To create chat template go to resources/views/chat.blade.php and include the following content:

<x-app-layout>
    ...
    <div id="app">
        <chat-box :receiver="{{ $user }}" :sender="{{ Auth::user() }}" />
    </div>
</x-app-layout>

This sets up the chat interface and passes the authenticated user and the selected user as props to the ChatBox component.

By following these steps, you will have successfully set up the frontend for your real-time chat app using Laravel, Vue.js, and Pusher. The UI will now be able to send and receive messages, seamlessly integrating with the backend functionality. If you are looking to build a robust website with a well-designed frontend, consider getting in touch with our Laravel development company.

Test the Chat Application

It’s finally time to see your real-time chat application in action! Follow the steps below to test the functionality of your chat app effectively.

Step 1: Start the Queue Worker

By default, Laravel events are dispatched on queues. To ensure your events are processed, start a queue worker instance by running the following command in your terminal:

php artisan queue:listen

This command ensures that any chat messages or events generated are correctly processed and displayed in real time.

Step 2: Register Two Users

To test the chat functionality, create two separate user accounts. Use these accounts to simulate a real chat scenario.

  • Open a regular browser tab and log in with one user account.
  • Open an incognito tab or a different browser and log in with the other user account.

Step 3: Start a Conversation

In both tabs, select the other user as the recipient for the chat. Then start sending messages to each other and observe how the messages are instantly updated in real time.

By following these steps, you should be able to test and confirm that your chat application is fully functional and performing as expected. If any issues arise, revisit your code and ensure that your Laravel, Vue.js, and Pusher configurations are correct.

Wrapping Up

Building a real-time chat application becomes much simpler and more efficient with the right tools. Using Laravel for backend management, Vue.js for a dynamic frontend, and Pusher for real-time communication creates a seamless experience. Starting with backend setup, we prepared the foundation for smooth data handling.

The frontend integration brought the interface to life, making interactions user-friendly and responsive. Finally, testing ensured that real-time features worked flawlessly. Understanding this process lets you build a chat app and also helps you get a better idea when working with other similar projects.If you are looking to build a real-time application that is well-designed and performs well, hire Laravel developers.

Level up your application’s interactivity with expert Laravel solutions!

author
Mayur Upadhyay is a tech professional with expertise in Shopify, WordPress, Drupal, Frameworks, jQuery, and more. With a proven track record in web development and eCommerce development.

Leave a comment