Build a live commenting system with Laravel and Vue.js

Build a live commenting system with Laravel and Vue.js

This tutorial will help you build a realtime commenting system with Laravel, Vue.js and Pusher. We’ll create a basic landing page, a comments feed, and a submission form where users can submit comments that will be added to the page and viewable instantly.


This tutorial will help you build a realtime commenting system with Laravel, Vue.js and Pusher. We’ll create a basic landing page, a comments feed, and a submission form where users can submit comments that will be added to the page and viewable instantly. This tutorial is the Laravel version of this one, and when setting up Vuex and Vue.js you can refer to the same sections in that tutorial. Now on to building our app!


Your final app should be looking like this:


In order to follow this tutorial a basic to good understanding of Vue.js and Laravel is required, as we’ll be using these frameworks throughout this tutorial. Also ensure you have Node.js installed on your machine or Yarn.

We’ll be using these tools to build our application so make sure to have them installed on your machine:

Pusher setup

Head over to the Pusher website and sign up for a free account. Select Create new app on the sidebar, and hit Create my app to create a new app after filling the form.

Once your app is created, retrieve your credentials from the API Keys tab, and make note of it as we’ll use them later in the tutorial.

Create the project and install dependencies

To get started we’ll install a new Laravel application using the Laravel CLI. We’ll run the following command:

laravel new live_comments

Once the installation is finished run the following command to move to your app directory:

cd live_comments

Now we’ll install our node dependencies, first paste this in your package.json file:

      "private": true,
      "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
      "devDependencies": {
        "axios": "^0.18",
        "bootstrap": "^4.0.0",
        "cross-env": "^5.1",
        "jquery": "^3.2",
        "laravel-mix": "^2.0",
        "lodash": "^4.17.5",
        "popper.js": "^1.12",
        "vue": "^2.5.7",
        "vuex": "^3.0.1",
        "moment": "^2.22.2",
        "pusher-js": "^4.2.2"

Then run npm install or yarn to install the dependencies. It’s up to you.

After this step, add the following to your .env file in the root of your project directory. Ensure to replace the placeholders with your keys from Pusher.


Database setup

We’ll use SQLite as our database. Create a database.sqlite file in the database directory, and amend the .env file like this:


Refer to this section on Laravel website for more relevant information.

Building models and seeding our database

Now, let’s build our database structure. We’ll use again Laravel CLI for that. Run this command:

php artisan make:model Comment -mc

The above command will generate the Comment model as well as its migration and its controller CommentController.php for us.

Open your Comment.php file and paste this:



    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Comment extends Model {

        protected $fillable = ['content', 'author'];

Next copy and paste this piece of code in your comment migration file:


    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    class CreateCommentsTable extends Migration
         * Run the migrations.
         * @return void

        public function up()
            Schema::create('comments', function (Blueprint $table) {

         * Reverse the migrations.
         * @return void

        public function down()

Then run php artisan migrate to run the migration.

Define routes and create the CommentController

In this section we’ll define our app endpoints and define the logic behind our CommentController.php.

We’ll create three basic routes for our application, one for rendering our app view, one for fetching comments from the database and the last one for storing comments into the database.

Paste the following into api.php:

    use Illuminate\Support\Facades\Route;

    Route::get('/', '[email protected]');

    Route::prefix('api')->group(function () {
        Route::get('/comments', '[email protected]');
        Route::post('/comments', '[email protected]');

And amend web.php like the following

    use Illuminate\Support\Facades\Route;
    Route::get('/', '[email protected]');

Now let’s define our controller logic. Our controller functions will be responsible for actions to handle when some requests reach our API endpoints.

Open your CommentController file and paste the following code:


    namespace App\Http\Controllers;

    use App\Comment;
    use App\Events\CommentEvent;
    use Illuminate\Http\Request;

    class CommentController extends Controller

        public function index()

            return view('comments');

        public function fetchComments()
            $comments = Comment::all();

            return response()->json($comments);

        public function store(Request $request)
            $comment = Comment::create($request->all());

            event(new CommentEvent($comment));
            return response()->json('ok');


You can notice three functions in the code above:

Emit event

Well you may have noticed this line: event(new CommentEvent($comment)). It broadcasts an event with the new comment to the client-side of our app using Laravel broadcasting. We’ll see how to create this event in the next part of the tutorial.

Create a search event with broadcasting

Our SearchEvent event will be emitted whenever a comment is submit by a user. Enough talk, let’s focus on the code. Let’s create our CommentEvent by running the following command in your terminal: php artisan make:event CommentEvent.

Now open your CommentEvent file and paste the following:


    namespace App\Events;

    use Illuminate\Broadcasting\Channel;
    use Illuminate\Broadcasting\InteractsWithSockets;
    use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
    use Illuminate\Foundation\Events\Dispatchable;
    use Illuminate\Queue\SerializesModels;

    class CommentEvent implements ShouldBroadcastNow
        use Dispatchable, InteractsWithSockets, SerializesModels;

        public $comment;

         * Create a new event instance.
         * @param  $comment
         * @return void

        public function __construct($comment)
            $this->comment = $comment;

         * Get the channels the event should broadcast on.
         * @return \Illuminate\Broadcasting\Channel|array

        public function broadcastOn()
            return new Channel('comment-channel');

        public function broadcastAs()
            return 'newComment';


Our class constructor initializes a comment that is nothing but the new submit comment. We have two additional functions that may seem strange to you:

Broadcasting configuration

According to Laravel documentation about event broadcasting, before broadcasting any events, you will first need to register the App\Providers\BroadcastServiceProvider. In fresh Laravel applications, you only need to uncomment this provider in the providers array of your ../config/app.php configuration file. This provider will allow you to register the broadcast authorization routes and callbacks.

If this is done, you have to tell Laravel to use Pusher to broadcast events. Open your .env file and ensure you have this line: BROADCAST_DRIVER=pusher

As we are broadcasting our events over Pusher, we should install the Pusher PHP SDK using the Composer package manager:

    composer require pusher/pusher-php-server "~3.0"

Setting up the broadcast channel

Laravel broadcasts events on well defined channels. As said above our event should be broadcast on comment-channel channel. It’s time to set it up. Paste the following code in your channels.php file:

    Broadcast::channel('comment-channel', function () {
        return true;

As we aren’t using Laravel auth, we return true in the function callback so that everybody can use this channel to broadcast events.

Now amend your bootstrap.js file like the following:


    window._ = require('lodash');

    window.axios = require('axios');
    window.moment = require('moment')

    // import 'vue-tel-input/dist/vue-tel-input.css';

    window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';['Content-Type'] = 'application/x-www-form-urlencoded';
    window.axios.defaults.headers.common.crossDomain = true;
    window.axios.defaults.baseURL = '/api';

    let token = document.head.querySelector('meta[name="csrf-token"]');

    if (token) {
        window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
    } else {
        console.error('CSRF token not found:');

    window.Pusher = require('pusher-js');

We make our pusher-js package global in order to use with no hassle everywhere and to listen to events on client-side.

Our app is ready to broadcast and consume events in realtime using Pusher channels. Let’s focus now on the frontend of your app.

Set up Vuex store

We’ll be using the Vuex library to centralize our data and control the way it is mutated throughout our application.

Create our state

Vuex state is a single object that contains all our application data. So let’s create ../resources/js/store/state.js and paste this code inside:

    let state = {
        comments: []
    export default  state

The comments key is an array responsible to store our database comments.

Create our getters

With help of getters we can compute derived based on our data store state. Create ../resources/js/store/getters.js and paste this code inside

    let getters = {
        comments: state => {
            return state.comments

    export default getters

Create our mutations

Mutations allow us to perform some changes on our data. Create ../resources/js/store/mutations.js and paste this piece of code inside:

    let mutations = {
      GET_COMMENTS(state, comments) {
        state.comments = comments
      ADD_COMMENT(state, comment) {
        state.comments = [...state.comments, comment]

    export default mutations

Our mutations object has two functions:

Create our actions

Vuex actions allow us to perform asynchronous operations over our data. Create the file ../resources/js/store/actions.js and paste the following code:

    let actions = {
      ADD_COMMENT({commit}, comment) {

        return new Promise((resolve, reject) => {
`/comments`, comment)
            .then(response => {
            }).catch(err => {

      GET_COMMENTS({commit}) {
          .then(res => {
          .catch(err => {

    export default actions

We have defined two actions and each of them is responsible for a single operation, either comments post or comments fetch. They both perform asynchronous calls to our API routes.

Set up our store with Vue

Create the file ../resources/js/store/index.js and paste this code inside:

    import Vue from 'vue'
    import Vuex from 'vuex'
    import actions from './actions'
    import mutations from './mutations'
    import getters from './getters'
    import state from "./state";


    export default new Vuex.Store({

Next, we will export our store and add it to the Vue instance. Add this code to your ../resouces/js/app.js file.


    window.Vue = require('vue');

    import store from './store/index'

    Vue.component('comment', require('./components/Comment'));
    Vue.component('comments', require('./components/Comments'))
    Vue.component('new-comment', require('./components/NewComment'))

    const app = new Vue({
      el: '#app',

The code above globally registers three Vue components, Comment.vue ,Comments.vue and NewComment.vue that we’ll build in the next part of this tutorial.

Building Vue components

We’ll build three Vue components for our app, the Comment.vue component, the Comments.vue and the NewComment.vue component, each of them responsible for a single functionality.

Create the Comment.vue component

The Comment.vue component is responsible for encapsulating details about a single comment instance from the database and rendering it in a proper and styled way. Paste the following inside your Comment.vue component.


      <li class="comment-wrapper animate slideInLeft ">
        <div class="profile">
          <img :src="avatar" alt=""></div>
        <div class="msg has-shadow">
          <div class="msg-body"><p class="name">{{}} <span class="date">{{posted_at}}</span></p>
            <p class="content">{{comment.content}}</p></div>

      export default {
        name: "Comment",
        props: ['comment'],
        computed: {
          posted_at() {
            return moment(this.comment.created_at).format('MMMM Do YYYY')
          avatar() {
            return `${}`

    <style lang="scss" scoped>
      .comment-wrapper {
        list-style: none;
        text-align: left;
        overflow: hidden;
        margin-bottom: 2em;
        padding: .4em;

        .profile {
          width: 80px;
          float: left;

        .msg-body {
          padding: .8em;
          color: #666;
          line-height: 1.5;

        .msg {
          width: 86%;
          float: left;
          background-color: #fff;
          border-radius: 0 5px 5px 5px;
          position: relative;
          &::after {
            content: " ";
            position: absolute;
            left: -13px;
            top: 0;
            border: 14px solid transparent;
            border-top-color: #fff;

        .date {
          float: right;
        .name {
          margin: 0;
          color: #999;
          font-weight: 700;
          font-size: .8em;

        p:last-child {
          margin-top: .6em;
          margin-bottom: 0;



Our Comment.vue component takes a comment property whose details we simply render in the component body. We also defined two computed properties, posted_at to parse the Moment.js library with the comment posted date, and avatar to generate an avatar for the comment author using this API. In the style block we’ve defined some styles to our comment component in order to make things look more beautiful.

Create the Comments.vue component

This component will render comment items from the database. Create your Comments.vue component and paste this code inside:


      <div class="container">
        <ul class="comment-list">
          <Comment :key="" v-for="comment in comments" :comment="comment"></Comment>

      import {mapGetters} from 'vuex'
      import Comment from './Comment'

      export default {
        name: "Comments",
        components: {Comment},
        mounted() {

         //use your own credentials you get from Pusher
          let pusher = new Pusher(`YOUR_PUSHER_APP_ID`, {
            cluster: `YOUR_PUSHER_CLUSTER`,
            encrypted: false

          //Subscribe to the channel we specified in our Adonis Application
          let channel = pusher.subscribe('comment-channel')

          channel.bind('new-comment', (data) => {
            this.$store.commit('ADD_COMMENT', data.comment)
        computed: {

    <style scoped>
      .comment-list {
        padding: 1em 0;
        margin-bottom: 15px;


First don’t forget to add your Pusher credentials in your Vue template.
In the template section of this code, we loop through our comments array and render for each loop iteration a Comment.vue component imported with the current comment iterated as a property.

In the mounted hook function we dispatched the GET_COMMENTS action. The action defined above sends a get request to our database to fetch posted comments. Then, we initialized a Pusher instance using the credentials obtained earlier when creating our Pusher app. Next, we subscribed to the comment-channel and listened to the new-comment event in order to commit the ADD_COMMENT mutation with the new comment pulled in by the event.

We also used the Vuex helper function …mapGetters() to access our comments state as computed property. In this component we also defined some styles to beautify our interface in the style block.

Create the NewComment.vue component

Our third component is responsible for displaying a form to our users for comment posting. It should also send a request to our database when a user submits his comment. Let’s create the NewComment.vue component, copy and paste this code inside:

      <div id="commentForm" class="box has-shadow has-background-white">

        <form @keyup.enter="postComment">
          <div class="field has-margin-top">

            <div class="field has-margin-top">
              <label class="label">Your name</label>
              <div class="control">
                <input type="text" placeholder="Your name" class="input is-medium" v-model="">

            <div class="field has-margin-top">
              <label class="label">Your comment</label>
              <div class="control">
                              class="input is-medium" autocomplete="true" v-model="comment.content"
                              placeholder="lorem ipsum"></textarea>

            <div class="control has-margin-top">
              <button style="background-color: #47b784" :class="{'is-loading': submit}"
                      class="button has-shadow is-medium has-text-white"
                      type="submit"> Submit

      export default {
        name: "NewComment",
        data() {
          return {
            submit: false,
            comment: {
              content: '',
              author: '',
        methods: {
          postComment() {
            this.submit = true;
            this.$store.dispatch('ADD_COMMENT', this.comment)
              .then(response => {
                this.submit = false;
                if ( === 'ok')
              }).catch(err => {
              this.submit = false

        computed: {
          isValid() {
            return this.comment.content !== '' && !== ''

    <style scoped>
      .has-margin-top {
        margin-top: 15px;


We bind our comment data to our comment content and author name fields using the Vue.js v-model directive. We handled the form submission with the postComment function inside which we dispatch the ADD_COMMENT mutation with the comment data entered by the user. We also defined isValid as a computed property that we use to disable the submit button if the two required fields are empty.

Finalize the app

Now, let’s create our comments.blade.php file which contains our Vue.js components. Then paste this code inside:


    <!DOCTYPE html>
    <html lang="en">
        <meta charset="UTF-8"/>
        <title>Live commenting system with Laravel and Pusher</title>
        <meta name="csrf-token" content="{{ csrf_token() }}">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

        <!-- Bootstrap core CSS -->
        <link rel="stylesheet" href=""/>
        <link rel="stylesheet" href=""/>

            html {
                background: radial-gradient(ellipse at center, #fff 0, #ededfd 100%);

            #app {
                width: 60%;
                margin: 4rem auto;

            .container {
                margin: 0 auto;
                position: relative;
                width: unset;

            .question-wrapper {
                text-align: center;

            .has-shadow {
                box-shadow: 0 4px 8px -2px rgba(0, 0, 0, 0.05) !important;


    <div id="app">

        <div class="container">
            <div class="question-wrapper">
                <img width="200" src="{{ asset('images/adonuxt.png') }}" alt="">
                <h5 class="is-size-2" style="color: #220052;">
                    What do you think about <span style="color: #47b784;">Laravel</span>?</h5>
                <a href="#commentForm" class="button is-medium has-shadow has-text-white" style="background-col
                or: #47b784">Comment</a>


    <script async src="{{mix('js/app.js')}}"></script>



We are almost done! Now open your terminal and run npm run dev to build your app. This can take a few seconds. After this step, run php artisan serve and open your browser to localhost:8000 to see your app working fine. Try posting a new comment! You should see your comment added in realtime 😎.

First don’t forget to add your Pusher credentials in your Vue template.## Conclusion

In this tutorial, we have covered how to create a live commenting system using Laravel, Vue.js and Pusher. You can get the full source code here.

Learn More

Build a Basic CRUD App with Laravel and Vue

Build a Simple CRUD App with Spring Boot and Vue.js

Build a Basic CRUD App with Laravel and Angular

Build a Basic CRUD App with Laravel and React

PHP Basic Course for Beginners - Full Tutorial

Vuejs 2 Authentication Tutorial

Build a CMS with Laravel and Vue

Laravel 5.8 Tutorial for Beginners

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Nuxt.js - Vue.js on Steroids

MEVP Stack Vue JS 2 Course: MySQL + Express.js + Vue.js +PHP

Build Web Apps with Vue JS 2 & Firebase

Top Vue.js Developers in USA

Top Vue.js Developers in USA

Vue.js is an extensively popular JavaScript framework with which you can create powerful as well as interactive interfaces. Vue.js is the best framework when it comes to building a single web and mobile apps.

We, at HireFullStackDeveloperIndia, implement the right strategic approach to offer a wide variety through customized Vue.js development services to suit your requirements at most competitive prices.

Vue.js is an open-source JavaScript framework that is incredibly progressive and adoptive and majorly used to build a breathtaking user interface. Vue.js is efficient to create advanced web page applications.

Vue.js gets its strength from the flexible JavaScript library to build an enthralling user interface. As the core of Vue.js is concentrated which provides a variety of interactive components for the web and gives real-time implementation. It gives freedom to developers by giving fluidity and eases the integration process with existing projects and other libraries that enables to structure of a highly customizable application.

Vue.js is a scalable framework with a robust in-build stack that can extend itself to operate apps of any proportion. Moreover, vue.js is the best framework to seamlessly create astonishing single-page applications.

Our Vue.js developers have gained tremendous expertise by delivering services to clients worldwide over multiple industries in the area of front-end development. Our adept developers are experts in Vue development and can provide the best value-added user interfaces and web apps.

We assure our clients to have a prime user interface that reaches end-users and target the audience with the exceptional user experience across a variety of devices and platforms. Our expert team of developers serves your business to move ahead on the path of success, where your enterprise can have an advantage over others.

Here are some key benefits that you can avail when you decide to hire vue.js developers in USA from HireFullStackDeveloperIndia:

  • A team of Vue.js developers of your choice
  • 100% guaranteed client satisfaction
  • Integrity and Transparency
  • Free no-obligation quote
  • Portal development solutions
  • Interactive Dashboards over a wide array of devices
  • Vue.js music and video streaming apps
  • Flexible engagement model
  • A free project manager with your team
  • 24*7 communication with your preferred means

If you are looking to hire React Native developers in USA, then choosing HireFullStackDeveloperIndia would be the best as we offer some of the best talents when it comes to Vue.js.

Top Web Application Developer

Top Web Application Developer

You can also contact a web application development company for your business but then why not to contact the best web application development company that can turn up your business and customer satisfaction ratio to sky touching heights.

Not long-ago internet came into existence and the world has never been the same ever since. The Internet made sure that people and business do evolve at a faster rate than ever and was never merciful to the slow ones. Because of this competition and availability of any business with few clicks made India one of the hubs as IT center. This trend of constantly updating has given rise to smartphones, smart machines, wearable gadgets and a lot more is yet to come in the upcoming years. In such time it is always a good idea to hire Web App Developer from India at your service. They are expert in developing not only websites but web applications as well.

We at HireFullStackDeveloperIndia, have a huge team of experienced developers that have grasped over different domains in front and back end development. You can hire web app developers in India from us with many advantages that you won’t get anywhere else in the industry.

Here is why we are the best option if you are looking forward to hiring web app developers in India:

  • Flexible hiring models available, as per your convenience and requirement
  • Maximum ROI, compared to any other company or team of developers.
  • We provide you with Source code Authorization meaning code written for you belong only to you. It cannot be used or copied anywhere else.
  • All of our developers are sound with agile development methodology, so you will be in a constant loop of suggestions, ideas, trends, and updates about your project.
  • Our developers are good with creating custom web applications as well; it guarantees you a better product without any compromise of non-existing functionalities.
  • You can save huge costing on infrastructure by utilizing our hire web app developer in India program.
  • Your hired developer or team will be easily accessible to your preferred mode of communication.
  • You get to exercise complete control over your team or individual that you hire.
  • We believe in Integrity and Transparency.
  • Our developers are highly creative and motivated to deliver excellence.

HireFullStackDeveloperIndia is a Web Application Development Company in India that is known worldwide for our Innovative guaranteed solutions. You can inquire with us about your project and we will be providing you multiple suitable developers that are the best fit for your requirements. You can evaluate them and select one or multiple whosoever deems fit to you. After this, all you have to do is provide your valuable input to the resource through sprint base project development until you get delivery of your project.

Our engagement model will also allow you to get our development team to your site location and proceed with development from your premises.

Develop this one fundamental skill if you want to become a successful developer

Throughout my career, a multitude of people have asked me&nbsp;<em>what does it take to become a successful developer?</em>

Throughout my career, a multitude of people have asked me what does it take to become a successful developer?

It’s a common question newbies and those looking to switch careers often ask — mostly because they see the potential paycheck. There is also a Hollywood level of coolness attached to working with computers nowadays. Being a programmer or developer is akin to being a doctor or lawyer. There is job security.

But a lot of people who try to enter the profession don’t make it. So what is it that separates those who make it and those who don’t? 

Read full article here