Building a Real-Time Chat Application with Socket.IO and Electron: From Web to Desktop

Real-time communication is at the core of many modern applications, especially for chat platforms. Whether it's messaging apps, collaborative tools, or customer support systems, the ability to communicate instantly is key. In this article, we will build a simple chat component using Socket.IO, integrate it into a web application, and then convert that web app into a desktop application using Electron.

We will also share the full code on GitHub for you to try out!

Prerequisites

Before we dive in, make sure you have the following tools and knowledge ready:

  • Basic knowledge of JavaScript and Node.js
  • Installed Node.js and npm on your machine
  • Basic understanding of Socket.IO
  • Familiarity with Electron is a plus, but not required

To install Node.js, visit nodejs.org and download the latest version. You can check your installation by running:

node -v
npm -v

Setting Up the Web App with Socket.IO

First, we will create a simple web application that allows users to send and receive messages in real-time.

Step 1: Initialize the Project

Create a new directory for your chat app and initialize it as a Node.js project:

mkdir socket-io-chat
cd socket-io-chat
npm init -y

Step 2: Install Dependencies

Next, install the required dependencies: Express and Socket.IO.

npm install express socket.io

Step 3: Create the Server

Now, we will create the Express server and set up Socket.IO to handle real-time communication.

Create a `server.js` file:

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = new Server(server);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

// Handle connection and message events
io.on('connection', (socket) => {
  console.log('a user connected');
  
  socket.on('chat message', (msg) => {
    io.emit('chat message', msg);
  });

  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

Step 4: Create the Frontend (HTML)

Create an `index.html` file in the same directory:

<!DOCTYPE html>
<html>
  <head>
    <title>Socket.IO Chat</title>
    <style>
      body { font-family: Arial, sans-serif; }
      ul { list-style-type: none; margin: 0; padding: 0; }
      li { padding: 8px; background-color: #f4f4f4; margin-bottom: 10px; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form id="form" action="">
      <input id="input" autocomplete="off" /><button>Send</button>
    </form>

    <script src="/socket.io/socket.io.js"></script>
    <script>
      const socket = io();

      const form = document.getElementById('form');
      const input = document.getElementById('input');

      form.addEventListener('submit', function(e) {
        e.preventDefault();
        if (input.value) {
          socket.emit('chat message', input.value);
          input.value = '';
        }
      });

      socket.on('chat message', function(msg) {
        const item = document.createElement('li');
        item.textContent = msg;
        document.getElementById('messages').appendChild(item);
      });
    </script>
  </body>
</html>

Step 5: Run the Web Application

Now, let's run our web application:

node server.js

Open your browser and navigate to `http://localhost:3000`. Open two browser windows and see the real-time communication between them!

Converting the Web App to a Desktop App with Electron

Now that we have a fully functional web-based chat app, let's convert it into a desktop application using Electron.

Step 1: Install Electron

Install Electron globally or locally within your project:

npm install electron --save-dev

Step 2: Create the Electron Main File

Create a new file called `main.js` for Electron:

const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    }
  });

  win.loadURL('http://localhost:3000');
}

app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

Step 3: Add Electron Scripts to `package.json`

Update your `package.json` file with Electron's start script:

"scripts": {
  "start": "node server.js",
  "electron": "electron ."
}

Step 4: Run the Desktop Application

Now, start both the server and the Electron application:

npm run start
npm run electron

You should see your chat application open in a standalone desktop window.

Conclusion

In this article, we’ve successfully built a simple real-time chat application using Socket.IO and converted it into a desktop app using Electron. By leveraging Electron, we transformed our web application into a cross-platform desktop application with minimal changes to the codebase.

Feel free to check out the full code and try it out yourself by visiting the GitHub repository linked below.

5. GitHub Repository

You can find the advanced source code for this project here.