DEV Community

spiritupbro
spiritupbro

Posted on • Edited on

Create Chat App With Chatbot Using NuxtJs And Express

How To Create Chat App With Chatbot Using NuxtJs And Express

Introduction

Today you gonna learn on how to create a chat application based on nuxtjs and expressjs. nuxtjs for the frontend, and also you will give some functionality like chatbot that can inform you about the situation of the covid 19 in the world today. It is hoped that after you finish running the tutorial below you can create your own chat application and add your own chatbot functionality as well.

Prerequisites

To complete this tutorial, you will need:

  • A local development environment for Node.js. Follow How to Install Node.js and Create a Local Development Environment.
  • A text editor like Visual Studio Code or Atom.
  • A web browser like Firefox or Chrome.
  • Familiarity with JavaScript. You can look at the How To Code in JavaScript series to learn more.
  • Familiarity with Nuxtjs. You can take a look at Nuxtjs official documentation here.
  • Familiarity with Vuejs. You can take a look at Vuejs official documentation here.
  • Familiarity with Typescript. You can take a look at Typescript official documentation here.
  • Familiarity with Nuxtjs Typescript. You can take a look at Nuxtjs Typescript official documentation here.
  • Docker, we will use docker to run our postgresql database you can install docker by following tutorial here
  • Docker-compose, we will use docker-compose to run our postgresql database you can install docker-compose by following tutorial here
  • Postgresql, we are gonna use postgresql as our main database you can take a look on how to use it here

Step 1 — Execute Postgresql Using Docker-Compose

First of all create a docker-compose.yml file and then add this line of code :

# docker-compose.yml
version: "3"
services:
  database:
    image: "postgres"
    ports:
      - "5432:5432"
    env_file:
      - database.env
    volumes:
      - database-data:/var/lib/postgresql/data/
volumes:
  database-data:
Enter fullscreen mode Exit fullscreen mode

and now create database.env file and fill it with this variable :

# database.env
POSTGRES_USER=panda
POSTGRES_PASSWORD=panda1234
POSTGRES_DB=panda_database
Enter fullscreen mode Exit fullscreen mode

what this yaml file does is, to tell docker to run service called database which run postgres image, and configure the environment variable using database.env after all that setup now run this command on the command line :

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

now your postgresql database is running.

Step 2 — Create An Expressjs Server

First create a package.json file then add this line :

{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "dependencies": {
    "bcrypt": "^5.0.0",
    "body-parser": "^1.19.0",
    "bufferutil": "^4.0.2",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "pg": "^8.5.0",
    "sequelize": "^6.3.5",
    "socket.io": "^3.0.1",
    "axios": "^0.21.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

now run this command on the command line :

npm install
Enter fullscreen mode Exit fullscreen mode

what this command does is installing all the dependencies that we define in the package.json file like expressjs, socket.io for the realtime and etc. After you install the dependencies now create index.js file and add this line of code :

const PORT = process.env.PORT || 3000;
const express = require("express");
const server = express();
server.listen(PORT, () => console.log(`Listening on ${PORT}`));
Enter fullscreen mode Exit fullscreen mode

This is a really simple expressjs file what this does is, it just listen to the request to port 3000, if there is no PORT environment variable specified. Now we gonna add sequelize to our server in order for our server to connect to database now run this command :

npx sequelize init
Enter fullscreen mode Exit fullscreen mode

What this command does is it create 4 necessary file and folders that we can use to connect to our postgresql database using sequelize. Now go to config/config.json file and change the development config to this one :

  "development": {
    "username": "panda",
    "password": "panda1234",
    "database": "panda_database",
    "host": "127.0.0.1",
    "dialect": "postgres"
  },
Enter fullscreen mode Exit fullscreen mode

It basically tell the server to login to database using this credentials. Now you need to create table in order for you to add authentication to your application, add the user table using this command :

npx sequelize model:create --name user --attributes username:string,password:string,token:string,role:string
Enter fullscreen mode Exit fullscreen mode

Basically what this command does is it create a migration file, so that you can create a table in postgresql easily now run this command to create table :

npx sequelize db:migrate
Enter fullscreen mode Exit fullscreen mode

Now after your table is created, you would want to add data to it, you can do so by adding a seeder file run this command to add a seeder file :

npx sequelize seed:generate --name users
Enter fullscreen mode Exit fullscreen mode

This basically create a new file in seeders folder, open that file and write this code :

"use strict";
const bcrypt = require("bcrypt");
const password = process.env.PASSWORD || "defaultpassword";
const username = process.env.USERNAME || "admin";
module.exports = {
  up: async (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert("users", [
      {
        username: username,
        password: await bcrypt.hash(password, 1),
        token: require("crypto").randomBytes(64).toString("hex"),
        role: "admin",
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    ]);
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete("users", { username }, {});
  },
};
Enter fullscreen mode Exit fullscreen mode

The code above is used to insert data into table users that you create earlier using migration. Now go to index.js again and add this line :

const PORT = process.env.PORT || 3000;
const express = require("express");
const model = require("./models/index");
const bodyParser = require("body-parser");
const bcrypt = require("bcrypt");
const server = express();
const http = require("http").createServer(server);
const cors = require("cors");
const jwt = require("jsonwebtoken");
server.use(cors());
server.use(express.static("public"));
server.post("/login", bodyParser.json(), async (req, res) => {
  const { username, password } = req.body;
  try {
    const users = await model.User.findOne({ where: { username } });

    if (users) {
      const cek = await bcrypt.compare(password, users.password);
      if (cek) {
        const token = jwt.sign({ token: users.token }, process.env.SECRET);
        return res.json({
          status: true,
          messages: "OK",
          data: {
            username: users.username,
            role: users.role,
            token: token,
          },
        });
      } else {
        throw new Error("wrong pass");
      }
    } else {
      return res.json({
        status: false,
        messages: "EMPTY",
        data: {},
      });
    }
  } catch (err) {
    return res.json({
      status: false,
      messages: err.message,
      data: {},
    });
  }
});
server.listen(PORT, () => console.log(`Listening on ${PORT}`));
Enter fullscreen mode Exit fullscreen mode

What this code above does is, it create connection to database using models/index.js and then create a route /login to check whether our user is in the database or not, now you need to add socket.io for the chat feature.

const PORT = process.env.PORT || 3000;
const express = require("express");
const model = require("./models/index");
const bodyParser = require("body-parser");
const bcrypt = require("bcrypt");
const server = express();
const http = require("http").createServer(server);
const cors = require("cors");
const jwt = require("jsonwebtoken");
const axios = require("axios");
server.use(cors());
server.use(express.static("public"));
server.post("/login", bodyParser.json(), async (req, res) => {
  const { username, password } = req.body;
  try {
    const users = await model.User.findOne({ where: { username } });

    if (users) {
      const cek = await bcrypt.compare(password, users.password);
      if (cek) {
        const token = jwt.sign({ token: users.token }, process.env.SECRET);
        return res.json({
          status: true,
          messages: "OK",
          data: {
            username: users.username,
            role: users.role,
            token: token,
          },
        });
      } else {
        throw new Error("wrong pass");
      }
    } else {
      return res.json({
        status: false,
        messages: "EMPTY",
        data: {},
      });
    }
  } catch (err) {
    return res.json({
      status: false,
      messages: err.message,
      data: {},
    });
  }
});
http.listen(PORT, () => console.log(`Listening on ${PORT}`));
const io = require("socket.io")(http, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"],
  },
});

io.on("connect", (socket) => {
  socket.on("chat message", (data) => {
    const { username, message } = data;
    if (data.token) {
      jwt.verify(data.token, process.env.SECRET, function (err, decoded) {
        let sendMessage = message;
        chatbot(io, sendMessage, "admin");
      });
    } else {
      let sendMessage = message;
      chatbot(io, sendMessage, username);
    }
  });
});
function chatbot(io, sendMessage, username) {
  if (/^coronabot\sconfirmed$/gi.test(sendMessage)) {
    axios.get("https://covid19.mathdro.id/api/").then((res) =>
      io.emit("chat message", {
        username,
        message: `confirmed in coronavirus case ${res.data.confirmed.value}`,
        role: username === "admin" ? "admin" : null,
      })
    );
  } else if (/^coronabot\srecovered$/gi.test(sendMessage)) {
    axios.get("https://covid19.mathdro.id/api/").then((res) =>
      io.emit("chat message", {
        username,
        message: `recovered in coronavirus case ${res.data.recovered.value}`,
        role: username === "admin" ? "admin" : null,
      })
    );
  } else if (/^coronabot\sdeaths$/gi.test(sendMessage)) {
    axios.get("https://covid19.mathdro.id/api/").then((res) =>
      io.emit("chat message", {
        username,
        message: `deaths in coronavirus case ${res.data.deaths.value}`,
        role: username === "admin" ? "admin" : null,
      })
    );
  } else if (/^coronabot\shelp$/gi.test(sendMessage)) {
    axios.get("https://covid19.mathdro.id/api/").then((res) =>
      io.emit("chat message", {
        username,
        message: `you can check the latest coronavirus case in the world by using this command:\n1. coronabot confirmed\n2. coronabot deaths\n3. coronabot recovered\nagain i just want to remind you to always wash your hand`,
        role: username === "admin" ? "admin" : null,
      })
    );
  } else {
    io.emit("chat message", {
      username,
      message: sendMessage,
      role: username === "admin" ? "admin" : null,
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

The function chatbot command above is used for our chatbot to notify the user using socket.io about the coronavirus case using api from open source project in here that scrape the value of coronavirus case in JHU CSSE. After you create this index.js run this command :

SECRET=panda node index.js
Enter fullscreen mode Exit fullscreen mode

SECRET here is used for adding secret for our jwt token you can change it whatever you want. After you succesfully run the server, now you can create nuxt typescript application.

Step 3 — Create A Nuxt Typescript Application

Now after the server is done you can create the frontend app by using nuxt typescript. Why typescript because using typescript your nuxt code will be much more tidy and maintainable now run this command to create your nuxt application :

npx create-nuxt-app frontend
Enter fullscreen mode Exit fullscreen mode

You will need to answer the question in order for you to create the nuxt application now follow this command one by one :

Project name: (frontend) 
Programming language: TypeScript
Package manager: Npm
UI framework: Buefy
Nuxt.js modules: Axios
Linting tools: ESLint, Prettier
Testing framework: Jest
Rendering mode: Single Page App
Deployment target: Static (Static/JAMStack hosting)
Development tools: Dependabot (For auto-updating dependencies, GitHub only)
Continuous integration: None
What is your GitHub username? #ENTER your username
Version control system: None
Enter fullscreen mode Exit fullscreen mode

After that wait for it to complete, while waiting create a folder called public this is where your nuxtjs generated app resides. And you can also serve that in your nodejs server. Now go to frontend/nuxt.config.js and change the content to this :

export default {
  ssr: false,
  // Global page headers (https://go.nuxtjs.dev/config-head)

  env: {
    baseUrl:
      process.env.NODE_ENV === 'prod'
        ? process.env.URL
        : 'http://localhost:3000',
  },
  head: {
    title: 'nuxt-chat-frontend',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' },
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
  },

  // Global CSS (https://go.nuxtjs.dev/config-css)
  css: [],

  // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
  plugins: [],

  // Auto import components (https://go.nuxtjs.dev/config-components)
  components: true,

  // Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
  buildModules: [
    // https://go.nuxtjs.dev/typescript
    '@nuxt/typescript-build',
  ],

  // Modules (https://go.nuxtjs.dev/config-modules)
  modules: [
    // https://go.nuxtjs.dev/buefy
    'nuxt-buefy',
    // https://go.nuxtjs.dev/axios
    '@nuxtjs/axios',
    // https://go.nuxtjs.dev/pwa
    '@nuxtjs/pwa',
  ],
  server: {
    port: 8000, // default: 3000
  },
  axios: {
    baseURL:   process.env.NODE_ENV === 'prod'
    ? process.env.URL
    : 'http://localhost:3000',
  },

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {},
  generate: {
    dir: '../public',
  },
}

Enter fullscreen mode Exit fullscreen mode

This will tell nuxt how you want your file to be generated later. After that now create file called ts-shim.d.ts in frontend folder, this file is used for telling code editor to index the $axios module so that you can access it anywhere in .vue file write this code below :

import { NuxtAxiosInstance } from '@nuxtjs/axios'
declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}
declare module '@nuxt/types' {
  interface Context {
    $axios: NuxtAxiosInstance
  }
}
Enter fullscreen mode Exit fullscreen mode

after that in tsconfig.json add the types like this :

 "types": [
      "@types/node",
      "@nuxt/types",
      "@nuxtjs/axios",
      "@types/js-cookie"
    ]
Enter fullscreen mode Exit fullscreen mode

After that change the dependencies in frontend/package.json like this :

"dependencies": {
    "@nuxt/typescript-runtime": "^2.0.0",
    "@nuxtjs/axios": "^5.12.2",
    "@nuxtjs/pwa": "^3.0.2",
    "@types/js-cookie": "^2.2.6",
    "@types/socket.io-client": "^1.4.34",
    "core-js": "^3.6.5",
    "js-cookie": "^2.2.1",
    "nuxt": "^2.14.6",
    "nuxt-buefy": "^0.4.3",
    "nuxt-property-decorator": "^2.8.8",
    "socket.io-client": "^3.0.1"
  },
Enter fullscreen mode Exit fullscreen mode

And now run this command in frontend folder :

npm install
Enter fullscreen mode Exit fullscreen mode

Change frontend/layouts/default.vue into this :

<template>
  <nuxt />
</template>
Enter fullscreen mode Exit fullscreen mode

After that in frontend/pages folder create 4 files first file is called index.vue this is where our homepage resides, add this code :

<template>
  <LoginUser />
</template>
<script lang="ts">
import LoginUser from '@/components/LoginUser.vue'
import { Component, Vue } from 'nuxt-property-decorator'
@Component({
  components: {
    LoginUser,
  },
})
export default class MyStore extends Vue {}
</script>
Enter fullscreen mode Exit fullscreen mode

Here you can see that your component above is extending another component called LoginUser you will create this later now you will focus on creating all 4 pages first now continue and create login_admin.vue file in frontend/pages folder add this below code :

<template>
 <LoginAdmin />
</template>

<script lang="ts">
import LoginAdmin from '@/components/LoginAdmin.vue'
import { Component, Vue } from 'nuxt-property-decorator'
@Component({
  components: {
    LoginAdmin
  }
})
export default class MyStore extends Vue {

}
</script>
Enter fullscreen mode Exit fullscreen mode

create chat_admin.vue file in frontend/pages folder add this below code :

<template>
  <ChatAdmin />
</template>
<script lang="ts">
import ChatAdmin from '@/components/chat-component/ChatAdmin.vue'
import { Component, Vue } from 'nuxt-property-decorator'
@Component({
  components: {
    ChatAdmin
  }
})
export default class MyStore extends Vue {}
</script>
Enter fullscreen mode Exit fullscreen mode

and finally create chat.vue file in frontend/pages folder and add this below code :

<template>
 <ChatUser />
</template>
<script lang="ts">
import ChatUser from '@/components/chat-component/ChatUser.vue'
import { Component, Vue } from 'nuxt-property-decorator'
@Component({
  components: {
    ChatUser
  }
})
export default class MyStore extends Vue {

}
</script>

Enter fullscreen mode Exit fullscreen mode

Now you need to add components in order for your pages above to work first create a file called LoginUser.vue in frontend/components folder and add this below code :

<template>
  <section class="hero is-primary is-fullheight">
    <div class="hero-body">
      <div class="container">
        <div class="columns is-centered">
          <div class="column is-5-tablet is-4-desktop is-3-widescreen">
            <form @submit.prevent="logins" class="box">
              <div class="field">
                <label for="" class="label">Username</label>
                <div class="control has-icons-left">
                  <input
                    type="text"
                    placeholder="username"
                    class="input"
                    required
                    v-model="username"
                  />
                  <span class="icon is-small is-left">
                    <i class="fa fa-lock"></i>
                  </span>
                </div>
              </div>

              <div class="field">
                <button class="button is-success" @click="logins">Login</button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
import { ToastProgrammatic as Toast } from 'buefy'
import Cookies from 'js-cookie'

@Component
export default class MyStore extends Vue {
  public username: string = ''
  public password: string = ''
  public error: string = ''
  created() {
    if (Cookies.get('user')) this.$router.push('/chat')
  }
  async logins() {
    Cookies.set('user', this.username, { expires: 7 })
    this.$router.push('/chat')
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

create a file called LoginAdmin.vue in frontend/components folder and add this below code :

<template>
  <section class="hero is-primary is-fullheight">
    <div class="hero-body">
      <div class="container">
        <div class="columns is-centered">
          <div class="column is-5-tablet is-4-desktop is-3-widescreen">
            <form @submit.prevent="logins" class="box">
              <div class="field">
                <label for="" class="label">Username</label>
                <div class="control has-icons-left">
                  <input
                    v-model="username"
                    type="text"
                    placeholder="username"
                    class="input"
                    required
                  />
                  <span class="icon is-small is-left">
                    <i class="fa fa-envelope"></i>
                  </span>
                </div>
              </div>
              <div class="field">
                <label for="" class="label">Password</label>
                <div class="control has-icons-left">
                  <input
                    v-model="password"
                    type="password"
                    placeholder="*******"
                    class="input"
                    required
                  />
                  <span class="icon is-small is-left">
                    <i class="fa fa-lock"></i>
                  </span>
                </div>
              </div>

              <div class="field">
                <button type="button" class="button is-success" @click="logins">
                  Login
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
import { ToastProgrammatic as Toast } from 'buefy'
import Cookies from 'js-cookie'

@Component
export default class MyStore extends Vue {
  public username: string = ''
  public password: string = ''
  public error: string = ''
  created() {
    if (Cookies.get('token')) this.$router.push('/chat_admin')
  }
  async logins() {
    try {
      const cek = await this.$axios.post('/login', {
        username: this.username,
        password: this.password,
      })
      if (!cek.data.status){
        return this.$buefy.toast.open({
          message: 'username or password wrong',
          type: 'is-warning',
        })}
      Cookies.set('token', cek.data.data.token, { expires: 7 })
      this.$router.push('/chat_admin')
    } catch (e) {
      this.$buefy.toast.open({
        message: 'username or password wrong',
        type: 'is-warning',
      })
      console.log(e.message)
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

create a folder called chat-component in frontend/components folder and create a file called ChatAdmin.vue in frontend/components/chat-component folder and add this below code :

<template>
  <section class="hero is-primary is-fullheight">
    <div class="hero-body">
      <div class="container">
        <div class="columns is-centered">
          <div class="column is-12-tablet is-12-desktop is-12-widescreen">
            <Message
              @logout="logout"
              :messages="messages"
              @send-message="send"
            />
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<script lang="ts">
import Message from '@/components/chat-component/Message.vue'
import { Component, Prop, Vue } from 'nuxt-property-decorator'
import Cookies from 'js-cookie'
import  {io}  from 'socket.io-client'
@Component({
  components: {
    Message,
  },
})
export default class ChatUser extends Vue {
  public ws: any
  public messages: Array<object> = []
  public socket: any
  logout() {
    Cookies.remove('token')
    this.$router.push('/login_admin')
  }
  mounted() {
    if (!Cookies.get('token')) this.$router.push('/login_admin')
    this.socket = io(<string>process.env.baseUrl)
    let ini = this
    this.socket.on('chat message', (msg: object) => {
      ini.messages.push(msg)
    })
  }
  send(message: string): void {
    const badWords=/a+s+s+h+o+l+e+|b+i+t+c+h+/ig;
    this.socket.emit('chat message', {
      username: 'ADMIN',
      message:message.replace(badWords,"******"),
      token: Cookies.get('token'),
    })
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

create a file called ChatUser.vue in frontend/components/chat-component folder and add this below code :

<template>
  <section class="hero is-primary is-fullheight">
    <div class="hero-body">
      <div class="container">
        <div class="columns is-centered">
          <div class="column is-12-tablet is-12-desktop is-12-widescreen">
            <Message @logout="logout" :messages="messages" @send-message="send" />
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<script lang="ts">
import Message from '@/components/chat-component/Message.vue'
import { Component, Prop, Vue } from 'nuxt-property-decorator'
import Cookies from 'js-cookie'
import  {io} from 'socket.io-client'

@Component({
  components: {
    Message,
  },
})
export default class ChatUser extends Vue {
  public ws: any
  public messages: Array<object> = []
  public socket: any
  logout() {
    Cookies.remove('user')
    this.$router.push('/')
  }
  created() {
    if (!Cookies.get('user')) this.$router.push('/')
    this.socket = io(<string>process.env.baseUrl)
    let ini = this
    this.socket.on('chat message', (msg:object) => {
      ini.messages.push(msg)
    })
  }
  send(message: string): void {
    const badWords=/a+s+s+h+o+l+e+|b+i+t+c+h+/ig;
    this.socket.emit('chat message', { username: Cookies.get('user'), message:message.replace(badWords,"******") })
  }
}
</script>

Enter fullscreen mode Exit fullscreen mode

create a file called Message.vue in frontend/components/chat-component folder and add this below code :

<template>
  <div action="" class="box is-info">
    <div class="columns" :style="{ width: '100%', height: '2em' }">
      <div class="column">Chat</div>
      <div
        :style="{
          padding: '.25em',
          justifyContent: 'flex-end',
          overflowWrap: 'normal',
          display: 'flex',
        }"
      >
        <button class="button is-success" @click="logout">Logout</button>
      </div>
    </div>

    <div
      v-for="(item, index) in messages"
      :key="index"
      :style="{
        padding: '.25em',
        justifyContent: 'flex-start',
        overflowWrap: 'normal',
        display: 'flex',
      }"
    >
      <div
        :style="{
          backgroundColor: item.role ? 'blue' : '#48c774',
          color: '#fff',
          padding: '.5em',
          wordWrap: 'break-word',
        }"
        :class="{
          'is-medium': true,
          'is-success': item.role ? false : true,
          'is-info': item.role ? true : false,
        }"
      >
        <label for="" class="label" :style="{ marginBottom: 0 }">{{
          item.username
        }}</label>

        <div>{{ item.message }}</div>
      </div>
    </div>
    <div class="field column is-12-desktop has-addons">
      <div class="control is-expanded">
        <input
          class="input"
          v-model="inputMessage"
          type="text"
          @keyup.enter="sendMessage(inputMessage)"
          placeholder="type message"
        />
      </div>
      <div class="control">
        <a class="button is-info" @click="sendMessage(inputMessage)"> Send</a>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Emit, Vue } from 'nuxt-property-decorator'
@Component
export default class Message extends Vue {
  inputMessage: string = ''
  @Prop({ required: true }) readonly messages!: Array<object>
  @Emit()
  sendMessage(message: object): void {
    this.inputMessage = ''
  }
  @Emit()
  logout(): void {}
}
</script>
Enter fullscreen mode Exit fullscreen mode

And it's done now go to your frontend folder and run npm run dev and go to

http://localhost:8000
Enter fullscreen mode Exit fullscreen mode

you will find your nuxt app running in the browser go ahead and add your nickname and start chatting, to login to admin just go to /login_admin and login using username and password that you create earlier in Step 1.

Conclusion

In this article you are succesfully building a chat app using nuxtjs and expressjs, if you notice i didn't save the nickname into database this will create a chaos if same person login with the same name you can go ahead and change that by creating table for nickname using Step 1 as reference. If you want to get the full code go ahead and clone this repo

Top comments (3)

Collapse
 
dzun_n profile image
Dzun N

Awesome

Collapse
 
spiritupbro profile image
spiritupbro

thank you my man i hope you learn something out of it

Collapse
 
spiritupbro profile image
spiritupbro • Edited

(commentspiritbro1english) i create a chatbot using nuxtjs, socketio, expressjs, and postgresql as database and deploy it using docker-compose