Building a Simple Chat App with HTML, CSS, JavaScript, and WebSocket (Node.js)

In this tutorial, we will explore how to create a simple Chat Application using HTML, CSS, JavaScript, and Node.js. This chat application enables real-time messaging between users, allowing them to send and receive messages instantly without the need to reload the application page.

The primary objective of this tutorial is to guide you through the process of building a real-time chat application using websockets. Websockets are a powerful technology that facilitates two-way communication between the server and the client, making them ideal for applications that require real-time data exchange.

By following this tutorial, you will gain a solid understanding of how to implement key features of a chat application, such as real-time message broadcasting and user interaction. This knowledge can be invaluable for developing future web applications that require real-time communication, such as customer support systems, collaborative tools, or social networking platforms.

Note: The source code that I will be providing in this tutorial is simple which requires a few enhancement especially in security measures to prevent some vulnerability on your web application.

Let’s get started on creating your very own real-time chat application, combining the power of modern web technologies with a seamless user experience!

Step 1: Installing the Requirements

In this example, we will set up a WebSocket server using Node.js. To begin, ensure that Node.js and NPM are installed on your machine. You can easily follow the installation instructions available on the official Node.js website. Once installed, navigate to your application's source code directory and install the ws (WebSocket) package by running the following command in your terminal. Ensure that your terminal’s current directory is set to the root of your source code.

npm install --save ws

Step 2: Creating a Websocket Server

Now, let's start building the WebSocket server. Begin by creating a new JavaScript file—in this case, we'll name it socket_server.js. This file will require the ws (WebSocket) package and include the necessary scripts to handle listening, establishing connections, and managing message exchanges between the server and clients. The following script includes comments to enhance your understanding of how it works.

  1. // Require Websocket Package/Module
  2. const webSocket = require("ws");
  3. // Listen Socket on specific Port
  4. const server = new webSocket.Server({ port: 8090 });
  5.  
  6. server.on("connection", (ws) => {
  7.     console.log("New client connected!");
  8.  
  9.     // Send message to Client when connected
  10.     ws.send(JSON.stringify({ msg: "You are successfully connected to JS Chat App Socket Server!" }));
  11.  
  12.     //Receive Message from Client
  13.     ws.on("message", (msg) => {
  14.         console.log(`Client has sent a message: ${msg}`);
  15.  
  16.         // Broadcast the message to all connected clients
  17.         server.clients.forEach((client) => {
  18.             if (client.readyState === WebSocket.OPEN) {
  19.                 client.send(`${msg}`);
  20.             }
  21.         })
  22.  
  23.     })
  24.  
  25. });

To run the websocket server, you can simply execute the following command on your terminal.

node .\socket_server.js

Step 3: Creating the Interface

Next, we will create the interface for the client side of our application. Start by creating a new file named index.html. This file will contain the HTML elements essential for the client-side functionality, such as the conversation box, message input field, and send button. Refer to the script below for implementation details.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.  
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>JS Chat App</title>
  7.     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
  8.     <link rel="stylesheet" href="styles.css">
  9.     <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  10.     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
  11. </head>
  12.  
  13.     <div id="main-wrapper">
  14.         <h2 id="app-title"><strong>Chat App using HTML, CSS, and JavaScript</strong></h2>
  15.         <div id="conversation-box" class="card rounded-0">
  16.             <div class="card-header rounded-0">
  17.                 <h4 class="card-title"><strong>Conversation Box</strong></h4>
  18.             </div>
  19.             <div class="card-body rounded-0">
  20.                 <div class="container-fluid" id="message-items-container"></div>
  21.             </div>
  22.             <div class="card-footer rounded-0">
  23.                 <div><span><small><i class="text-muted">You are logged in as: <span id="userName"></span></i></small></span></div>
  24.                 <div class="d-flex w-100">
  25.                     <div class="flex-grow-1" id="txt-field-container">
  26.                         <textarea id="msg-txt-field" rows="2" class="form-control form-control-sm rounded-0" placeholder="Write your message here..."></textarea>
  27.                     </div>
  28.                     <div id="send-btn-container">
  29.                         <button class="btn btn-primary rounded-0" id="send-btn"><strong>Send</strong></button>
  30.                     </div>
  31.                 </div>
  32.             </div>
  33.         </div>
  34.     </div>
  35.     <script src="./chat_app.js"></script>
  36. </body>
  37. </html>

And for some custom design of some elements, here's the following Cascading Stylesheet (CSS). The following CSS file is known as styles.css which is loaded at the index file.

  1. @import url('https://fonts.googleapis.com/css2?family=Ubuntu+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap');
  2. *{
  3.     font-family: "Ubuntu Mono", serif;
  4.     font-weight: 400;
  5.     font-style: normal;
  6. }
  7. strong, b{
  8.     font-weight: 700;
  9. }
  10.  
  11. html,body{
  12.     margin: unset;
  13.     padding: unset;
  14.     height: 100%;
  15.     max-height: 100%;
  16.     width: 100%;
  17.     max-width: 100%;
  18.     overflow: auto;
  19. }
  20.  
  21. body{
  22.     display: flex;
  23.     flex-flow: column;
  24.     align-items: center;
  25.     justify-content: center;
  26.     background-image: linear-gradient(to top, #48c6ef 0%, #6f86d6 100%);
  27. }
  28.  
  29. #main-wrapper{
  30.     width: 350px;
  31. }
  32.  
  33. #app-title{
  34.     color: #fff;
  35.     text-shadow: 0px 3px 5px #9a9a9a;
  36.     text-align: center;
  37.     margin-bottom: 50px
  38. }
  39. #msg-txt-field{
  40.     resize: none;
  41. }
  42. #send-btn-container{
  43.     width: 70px;
  44. }
  45. #send-btn{
  46.     width: 100%;
  47.     height: 100%;
  48.     display: flex;
  49.     align-items: center;
  50.     justify-content: center;
  51. }
  52.  
  53. #message-items-container{
  54.     height:300px;
  55.     overflow: auto;
  56.     display: flex;
  57.     flex-flow: column-reverse;
  58. }
  59. #message-items-container:empty{
  60.     align-items: center;
  61.     justify-content: center;
  62. }
  63. #message-items-container:empty::before{
  64.     content:"conversation box is currently empty...";
  65.     font-size: 11px;
  66.     font-style: italic;
  67.     align-self: center;
  68.     color:#858585;
  69. }
  70.  
  71. .message-item{
  72.     max-width: 85%;
  73.     padding: 10px 10px;
  74.     margin-bottom: 10px;
  75.     border-radius: 15px;
  76. }
  77. .message-item.received{
  78.     background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  79.     align-self: start;
  80. }
  81. .message-item.sent{
  82.     background-image: linear-gradient(120deg, #89f7fe 0%, #66a6ff 100%);
  83.     align-self: end;
  84. }
  85. .message-item .sender-name{
  86.     font-style: italic;
  87.     font-size: 11px;
  88. }
  89. .message-item .message-content{
  90.     font-size: 12px;
  91. }

Here's the screenshot of the Application Interface.

Building a Simple Chat App with HTML, CSS, JavaScript, and WebSocket (Node.js)

Building a Simple Chat App with HTML, CSS, JavaScript, and WebSocket (Node.js)

Step 3: Client Side Websocket

Finally, let's create the client-side WebSocket script along with other JavaScript code to make our application fully functional. Save this new JavaScript file as chat_app.js, and make sure to load it in the index.html file. This script will handle connecting to the server, sending messages, and receiving messages. Additionally, it includes event listeners and functions to enable features like displaying sent and received messages in the conversation box.

  1. // Connect to the Websocket Server
  2. const chatSocket = new WebSocket("ws://localhost:8090")
  3. var isSocketConnected = false;
  4.  
  5. var user_name = localStorage.getItem("userName") || "";
  6.  
  7. // Messages Bubble
  8. let msgBubble = `<div class="message-item">
  9. <div><span class="text-muted sender-name"></span></div>
  10. <div class="message-content"></div>
  11. </div>`;
  12.  
  13. // Event when socket is openned
  14. chatSocket.onopen = (event) => {
  15.     // when connection is opened
  16.     isSocketConnected = true;
  17. };
  18.  
  19. // Function  for Sending the Message data to the socket server
  20. function send_msg(JSONData) {
  21.     // Pevent function to execute when socket not opened successfully
  22.     if (!isSocketConnected)
  23.         return;
  24.     chatSocket.send(JSON.stringify(JSONData));
  25. }
  26.  
  27. // Receive Message from socket
  28. chatSocket.onmessage = (event) => {
  29.     // Message Data recived from socket server
  30.     var msgData = JSON.parse(event.data) || null;
  31.     if (msgData == null)
  32.         return;
  33.     if (!msgData.msg)
  34.         return;
  35.     if (!msgData.user) {
  36.         console.log(msgData.msg)
  37.         return;
  38.     }
  39.     // Show the message data into the conversation box if user is not equal to client
  40.     if (msgData.user != user_name) {
  41.         var bubble = $(msgBubble).clone(true);
  42.         bubble.addClass("received");
  43.         bubble.find(".sender-name").text(`${msgData.user-}`)
  44.         var content = (msgData.msg).replace(/\n/gi, "<br>");
  45.         bubble.find(".message-content").text(content);
  46.         $('#message-items-container').prepend(bubble);
  47.     }
  48. }
  49. // Closing the socket if window is unloading
  50. window.addEventListener("unload", function () {
  51.     chatSocket.close();
  52.     console.log(chatSocket);
  53. })
  54.  
  55. // Listen for possible errors
  56. chatSocket.addEventListener("error", (event) => {
  57.     console.log("WebSocket error: ", event);
  58. });
  59.  
  60. // Function that handles the message data to send
  61. function triggerSend() {
  62.     var msg = $("#msg-txt-field").val();
  63.     msg = msg.trim();
  64.     if (msg == "")
  65.         return;
  66.  
  67.     var bubble = $(msgBubble).clone(true);
  68.     bubble.addClass("sent");
  69.     // bubble.find(".sender-name").text(`${user_name}`)
  70.     var content = msg.replace(/\n/gi, "<br>");
  71.     bubble.find(".message-content").text(content);
  72.     $('#message-items-container').prepend(bubble);
  73.  
  74.     $("#msg-txt-field").val("");
  75.     $("#msg-txt-field").focus();
  76.     send_msg({ user: user_name, msg: msg });
  77. }
  78. $(document).ready(function () {
  79.     // Prompt window if user does not exists yet
  80.     if (user_name == "") {
  81.         var enter_user = prompt("Enter Your Name");
  82.         if (enter_user != "") {
  83.             user_name = enter_user;
  84.             localStorage.setItem("userName", user_name);
  85.         } else {
  86.             alert("User Name must be provided!");
  87.             location.reload();
  88.         }
  89.     }
  90.     $('#userName').text(user_name)
  91.     // Event Listener when Send Button has been triggered Clicked
  92.     $('#send-btn').on("click", triggerSend);
  93.  
  94.     //Event Listener when Message Text Field is submitted by hitting the Enter Key
  95.     $('#msg-txt-field').on("keypress", function (e) {
  96.         if (e.key == "Enter") {
  97.             e.preventDefault();
  98.             triggerSend();
  99.         }
  100.     });
  101.  
  102.  
  103. })

And there you have it! You can now test application on you end. Make sure that the websocket server script is running while testing the application.

DEMO VIDEO

I have also included the complete source code for the chat application mentioned in this content. You can download the source code for free by clicking the download button located below this article.

I hope this Simple Chat Application Tutorial using HTML, CSS, JavaScript, and Node.js provides you with valuable insights and inspiration to develop similar features for your future web application projects.

Explore more on this website for more Tutorials, Free Source Codes, and Articles covering the various programming languages.

Happy Coding =)

Add new comment