# Tutorial: Real-Time Chat Room

## Content

This tutorial guides developers through building a real-time chat room using `js-collaboration`. You will:

* Establish peer-to-peer communication within shared rooms
* Transmit and receive instant messages
* Implement server/client coordination for message broadcasting

## Prerequisites

* Installation of Node.js v16+ and npm
* Foundational knowledge of JavaScript and terminal operations

## Step 1: Initialize the Project

1. Create a Project Folder Create a new directory named chat-room and navigate into it:

    ```bash
    mkdir chat-room
    cd chat-room
    ```
2. Initialize a Project of Node.js Run the following command to create the file `package.json`:

    ```bash
    npm init -y
    ```

    Edit `package.json` to enable ESM modules and add the following scripts:

    ```json
    {
      "name": "chat-room",
      "version": "1.0.0",
      "type": "module",
      "scripts": {
        "start": "node server.js",
        "build": "webpack"
      },
      "dependencies": {}
    }
    ```
3. Install Dependencies Install the packages required for the server and client:

    ```bash
    npm install @mescius/js-collaboration @mescius/js-collaboration-client express
    ```

    Install npm packages for Frontend Bundling:

    ```bash
    npm install webpack webpack-cli --save-dev
    ```
4. Create a Webpack Configuration File In the project root directory, create the file `webpack.config.js` and add the following content:

    ```javascript
    import path from "path";
    import { fileURLToPath } from "url";
    
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    
    export default {
      entry: "./public/client.js",
      output: {
        path: path.resolve(__dirname, "public"),
        filename: "client.bundle.js"
      },
      mode: "development"
    };
    ```
5. Create the Basic Directory Structure
    * Create the file `server.js` in the root directory.
    * In the root directory, create a folder named public. Create empty files within it: `index.html`, `styles.css`, and `client.js`.

    Now the directory structure should look like this:

    ```bash
    / (project root)
    ├── public/
    │   ├── index.html      # Main page
    │   ├── styles.css      # Style file
    │   └── client.js       # Client-side logic
    ├── server.js           # Server-side logic
    ├── package.json        # Project configuration
    └── webpack.config.js   # Webpack configuration
    ```

## Step 2: Set Up the Server

We will create a simple server to handle client connections, message sending and receiving, and broadcasting.
Add the following code to the file `server.js`:

```javascript
import express from "express";
import { createServer } from "http";
import { Server } from "@mescius/js-collaboration";

// Create an Express application and HTTP server
const app = express();
const httpServer = createServer(app);

// Initialize the collaboration server
const server = new Server({ httpServer });

// Serve static files (to be used later for the client)
app.use(express.static("public"));

// Listen for client connections
server.on("connect", ({ connection, roomId }) => {
    console.log(`${connection.id} joined room ${roomId}`);
    // Broadcast a message that a new user has joined (including to the user themselves)
    connection.broadcast(`${connection.id} joined the chat room`, "", true);
});

// Handle messages sent by clients
server.on("message", ({ connection, data, roomId }) => {
    console.log(`Received message from ${connection.id}: ${data}`);
    // Broadcast the message to all users in the room (including the sender)
    connection.broadcast(`${connection.id}: ${data}`, "", true);
});

// Listen for client disconnections
server.on("disconnect", ({ connection, roomId }) => {
    console.log(`${connection.id} left room ${roomId}`);
    // Broadcast a message that the user has left
    connection.broadcast(`${connection.id} left the chat room`, "", true);
});

// Start the server
httpServer.listen(8080, () => {
    console.log("Server running at http://localhost:8080");
});
```

**Code Explanation**

* Use express and http to create an HTTP server.
* Initialize the collaboration server using the [Server ](/spreadjs/api/v18/collaboration/js-collaboration/classes/Server)class from `@mescius/js-collaboration`.
* Register connect, message, and disconnect events to handle user joining, message sending, and leaving respectively.
* [connection.broadcast()](/spreadjs/api/v18/collaboration/js-collaboration/classes/Connection#broadcast) broadcasts messages to all clients in the room, with `includeSelf: true` ensuring the sender can also see their own messages.

## Step 3: Set Up the Client

Next, we will create a simple HTML file and JavaScript client to connect to the server and implement chat functionality.

1. Write the HTML File (`public/index.html`)

    ```html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Real-Time Chat Room</title>
        <link rel="stylesheet" href="./styles.css">
        <script type="module" src="./client.bundle.js" defer></script>
    </head>
    <body>
        <div class="container">
            <h1>Real-Time Chat Room</h1>
            <div id="chat"></div>
            <div class="input-area">
                <input type="text" id="message" placeholder="Enter message...">
                <button onclick="sendMessage()">Send</button>
            </div>
        </div>
    </body>
    </html>
    ```
2. Write the Client-Side JavaScript (`public/client.js`)

    ```javascript
    import { Client } from "@mescius/js-collaboration-client";
    
    const client = new Client();
    const connection = client.connect("chatroom");
    
    connection.on("message", (data) => {
      const chatDiv = document.getElementById("chat");
      const message = document.createElement("p");
      message.textContent = data;
      chatDiv.appendChild(message);
      chatDiv.scrollTop = chatDiv.scrollHeight;
    });
    
    window.sendMessage = function () {
      const input = document.getElementById("message");
      const message = input.value.trim();
      if (message) {
        connection.send(message);
        input.value = "";
      }
    };
    ```

    **Code Explanation**
    * Use the [Client](/spreadjs/api/v18/collaboration/js-collaboration-client/classes/Client) class from `@mescius/js-collaboration-client` to create a client and connect to the "chatroom" room.
    * Use [connection.on("message")](/spreadjs/api/v18/collaboration/js-collaboration-client/classes/Connection#on) to listen for messages from the server and display them in the chat window.
    * The `sendMessage()`function retrieves the message from the input box and sends it to the server using `connection.send()`.
3. Write the Client-Side Styles (`public/styles.css`)

    ```css
    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
      font-family: Arial, sans-serif;
      background-color: #f0f2f5;
    }
    
    .container {
      height: 100vh; /* Fill the viewport height */
      display: flex;
      flex-direction: column;
      background: #fff;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }
    
    h1 {
      font-size: 24px;
      color: #333;
      padding: 15px;
      margin: 0;
      text-align: center;
      border-bottom: 1px solid #ddd;
    }
    
    #chat {
      flex: 1; /* Fill the remaining space */
      overflow-y: auto;
      background: #fafafa;
      padding: 15px;
    }
    
    #chat p {
      margin: 10px 0;
      padding: 10px;
      background: #e9ecef;
      border-radius: 5px;
      word-wrap: break-word;
    }
    
    .input-area {
      display: flex;
      padding: 15px;
      border-top: 1px solid #ddd;
      background: #f9f9f9;
    }
    
    #message {
      flex: 1;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
      font-size: 14px;
      margin-right: 10px;
    }
    
    button {
      padding: 10px 20px;
      background: #007bff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-size: 14px;
    }
    
    button:hover {
      background: #0056b3;
    }
    ```

## Step 4: Run and Test the Chat Room

1. Bundle the Client Code

    ```bash
    npm run build
    ```
2. Start the Server Run the following command in the terminal:

    ```bash
    npm run start
    ```

    You should see the output: `Server running at http://localhost:8080.`
3. Open the Browser Visit *http://localhost:8080* in your browser, and you will see the chat room interface.
4. Test the Functionality
    * Open multiple browser windows to simulate multiple users joining the chat room.
    * In one window, enter a message and click "Send". All windows should display the message in real time.
    * Close one window, and the other windows will receive a notification that the user has left.

## Next Steps

[Tutorial: Add Authentication](/spreadjs/docs/v18/spreadjs-collaboration-server/collaboration-framework/js-collaboration/tutorial-real-time-chat-room/tutorial-add-authentication)