Building a Real-Time Multiuser Text Editor using JavaScript! - 17/12/2023

Your Saas needs team functionality

Site under construction! Migrated content might be displayed ugly!

medium-to-markdown@0.0.3 convert node index.js https://medium.com/@birnadin/building-a-real-time-multiuser-text-editor-be766c517488

Building a Real-Time Multiuser Text Editor using JavaScript!

[Enigma Bits


Enigma Bits



4 min read·Dec 17, 2023



a team — from unsplash.com

Welcome to the dynamic world of web development, today our mission is crystal clear: a real-time synced text area that fosters seamless collaboration among users.

In this tutorial, we’ll not only achieve synchronization but also implement an audit history, ensuring transparency and accountability. Let’s dive into the details of our coding journey!

Download the code samples here. However, the crux code is given below.

Demo showcasing minimal end result

How do we accomplish this?

In our pursuit of real-time synchronization, we’ll leverage bidirectional technologies that facilitate the smooth exchange of data between clients and servers. We’ve got a trio of superheroes at our disposal:

To simplify the implementation of these technologies, we’ll be relying on the robust [socket.io](https://socket.io/) library, a versatile tool that streamlines real-time communication complexities.

If you are not clear about WebSocket, then read my Primer on WebSockets

We will primarily equip WebSocket

Basic Skeleton: Keeping it Simple, Yet Functional

Before we dive into the intricacies, let’s establish a basic skeleton for our application. We’ll prioritize functionality over aesthetics at this stage, focusing on the core markup without delving into styling intricacies.

Server Side: Node.js

Now, let’s shift our attention to the server side, where Node.js will play a pivotal role. Our Node.js server will wear multiple hats:

With all these in mind, the server is written; you may see the full sample in the assets. But here are the crux of what is needed.

const io = socketIO(httpServer);  
// ...snip for brevity...  
io.on('connection', (socket) => {  
  // Event listener for when the client sends a text message  
  socket.on('textMessage', (message) => {  
    // Broadcast the text message to all connected clients  
    io.emit('textMessage', { message, userId: socket.id });  
  1. io.on('connection',... will fire the callback when a client requests a TCP connection.
  2. socket.on(<a-channel-name>,... will subscribe to the callback given to this client’s connection when a message is sent on this particular channel.
  3. io.emit(<a-channel-name>, <payload-to-emit>) will send the given payload to other clients under this channel.

The above three steps are the minimal workflow with the socket.io library.

socket.io is implemented for many languages, visit their documentation for more.

Client Side: DOM API

Full code can be taken from the assets attached. But here are the focal pieces. First our stripped Text editor — semantic textarea - will fire a callback on input change.

<textarea spellcheck="false" id="textInput" rows="25" cols="50" oninput="sendText()"></textarea>

This is the callback fired upon input…

function sendText() {  
      const textInput = document.getElementById('textInput');  
      const message = textInput.value;  
      // then we emit the message  
      socket.emit('textMessage', message);  

…and update the universal state upon signal from the server…

function displayMessage(message, userId, color) {  
      // ...snip...  
      // sync the data  
      textInput.value = message;  
      // ...snip...  

Believe it or not, this is all we need to have sync data between multiple clients. Note that socket.io hides many complexities. If you want to learn them too, please let me know in the comments and subscribe to my newsletter; so that you get notified immediately when I post.

EXTRAS: Enhancing Collaboration with Audit History

To know what’s going on let’s enhance our collaborative text area with an audit history. We want to capture every twist and turn in our users’ collaborative journey. Leveraging the built-in userId from socket.io, we’ll imprint each snapshot with a timestamp.

// we get the timestamp to string that is tailored Locale to user  
new Date().toLocaleString()

This audit history will be neatly presented using the details HTML element, offering a collapsible view for a user-friendly experience.

    <!-- snapshots go here -->  

…and append new messages to the div using this DOM API.

This concise yet comprehensive structure showcases the progression of our collaborative efforts.


As we wrap up this coding adventure we’ve successfully created a real-time synced text area with an integrated audit history. WebSockets and the versatile [socket.io](http://socket.io/) library have played pivotal roles in this journey.

Before you embark on your coding endeavors, consider supporting my educational journey by subscribing to my newsletter (it’s free btw) or following me on X.

Happy coding, and may your text areas sync flawlessly in the vast landscape of web development!

See you on next post, till then it’s meTheBE signing off.