Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Node.js chat frontend and server
$(function () {
"use strict";
// for better performance - to avoid searching in DOM
var content = $('#content');
var input = $('#input');
var status = $('#status');
// my color assigned by the server
var myColor = false;
// my name sent to the server
var myName = false;
// if user is running mozilla then use it's built-in WebSocket
window.WebSocket = window.WebSocket || window.MozWebSocket;
// if browser doesn't support WebSocket, just show some notification and exit
if (!window.WebSocket) {
content.html($('<p>', { text: 'Sorry, but your browser doesn\'t '
+ 'support WebSockets.'} ));
// open connection
var connection = new WebSocket('ws://');
connection.onopen = function () {
// first we want users to enter their names
status.text('Choose name:');
connection.onerror = function (error) {
// just in there were some problems with conenction...
content.html($('<p>', { text: 'Sorry, but there\'s some problem with your '
+ 'connection or the server is down.' } ));
// most important part - incoming messages
connection.onmessage = function (message) {
// try to parse JSON message. Because we know that the server always returns
// JSON this should work without any problem but we should make sure that
// the massage is not chunked or otherwise damaged.
try {
var json = JSON.parse(;
} catch (e) {
console.log('This doesn\'t look like a valid JSON: ',;
// NOTE: if you're not sure about the JSON structure
// check the server source code above
if (json.type === 'color') { // first response from the server with user's color
myColor =;
status.text(myName + ': ').css('color', myColor);
// from now user can start sending messages
} else if (json.type === 'history') { // entire message history
// insert every single message to the chat window
for (var i=0; i <; i++) {
addMessage([i].author,[i].text,[i].color, new Date([i].time));
} else if (json.type === 'message') { // it's a single message
input.removeAttr('disabled'); // let the user write another message
addMessage(,,, new Date(;
} else {
console.log('Hmm..., I\'ve never seen JSON like this: ', json);
* Send mesage when user presses Enter key
input.keydown(function(e) {
if (e.keyCode === 13) {
var msg = $(this).val();
if (!msg) {
// send the message as an ordinary text
// disable the input field to make the user wait until server
// sends back response
input.attr('disabled', 'disabled');
// we know that the first message sent from a user their name
if (myName === false) {
myName = msg;
* This method is optional. If the server wasn't able to respond to the
* in 3 seconds then show some error message to notify the user that
* something is wrong.
setInterval(function() {
if (connection.readyState !== 1) {
input.attr('disabled', 'disabled').val('Unable to comminucate '
+ 'with the WebSocket server.');
}, 3000);
* Add message to the chat window
function addMessage(author, message, color, dt) {
content.prepend('<p><span style="color:' + color + '">' + author + '</span> @ ' +
+ (dt.getHours() < 10 ? '0' + dt.getHours() : dt.getHours()) + ':'
+ (dt.getMinutes() < 10 ? '0' + dt.getMinutes() : dt.getMinutes())
+ ': ' + message + '</p>');
"use strict";
// Optional. You will see this name in eg. 'ps' or 'top' command
process.title = 'node-chat';
// Port where we'll run the websocket server
var webSocketsServerPort = 1337;
// websocket and http servers
var webSocketServer = require('websocket').server;
var http = require('http');
* Global variables
// latest 100 messages
var history = [ ];
// list of currently connected clients (users)
var clients = [ ];
* Helper function for escaping input strings
function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;')
.replace(/>/g, '&gt;').replace(/"/g, '&quot;');
// Array with some colors
var colors = [ 'red', 'green', 'blue', 'magenta', 'purple', 'plum', 'orange' ];
// ... in random order
colors.sort(function(a,b) { return Math.random() > 0.5; } );
* HTTP server
var server = http.createServer(function(request, response) {
// Not important for us. We're writing WebSocket server, not HTTP server
server.listen(webSocketsServerPort, function() {
console.log((new Date()) + " Server is listening on port " + webSocketsServerPort);
* WebSocket server
var wsServer = new webSocketServer({
// WebSocket server is tied to a HTTP server. WebSocket request is just
// an enhanced HTTP request. For more info
httpServer: server
// This callback function is called every time someone
// tries to connect to the WebSocket server
wsServer.on('request', function(request) {
console.log((new Date()) + ' Connection from origin ' + request.origin + '.');
// accept connection - you should check 'request.origin' to make sure that
// client is connecting from your website
// (
var connection = request.accept(null, request.origin);
// we need to know client index to remove them on 'close' event
var index = clients.push(connection) - 1;
var userName = false;
var userColor = false;
console.log((new Date()) + ' Connection accepted.');
// send back chat history
if (history.length > 0) {
connection.sendUTF(JSON.stringify( { type: 'history', data: history} ));
// user sent some message
connection.on('message', function(message) {
if (message.type === 'utf8') { // accept only text
if (userName === false) { // first message sent by user is their name
// remember user name
userName = htmlEntities(message.utf8Data);
// get random color and send it back to the user
userColor = colors.shift();
connection.sendUTF(JSON.stringify({ type:'color', data: userColor }));
console.log((new Date()) + ' User is known as: ' + userName
+ ' with ' + userColor + ' color.');
} else { // log and broadcast the message
console.log((new Date()) + ' Received Message from '
+ userName + ': ' + message.utf8Data);
// we want to keep history of all sent messages
var obj = {
time: (new Date()).getTime(),
text: htmlEntities(message.utf8Data),
author: userName,
color: userColor
history = history.slice(-100);
// broadcast message to all connected clients
var json = JSON.stringify({ type:'message', data: obj });
for (var i=0; i < clients.length; i++) {
// user disconnected
connection.on('close', function(connection) {
if (userName !== false && userColor !== false) {
console.log((new Date()) + " Peer "
+ connection.remoteAddress + " disconnected.");
// remove user from the list of connected clients
clients.splice(index, 1);
// push back user's color to be reused by another user
<!DOCTYPE html>
<meta charset="utf-8">
<title>WebSockets - Simple chat</title>
* { font-family:tahoma; font-size:12px; padding:0px; margin:0px; }
p { line-height:18px; }
div { width:500px; margin-left:auto; margin-right:auto;}
#content { padding:5px; background:#ddd; border-radius:5px; overflow-y: scroll;
border:1px solid #CCC; margin-top:10px; height: 160px; }
#input { border-radius:2px; border:1px solid #ccc;
margin-top:10px; padding:5px; width:400px; }
#status { width:88px; display:block; float:left; margin-top:15px; }
<div id="content"></div>
<span id="status">Connecting...</span>
<input type="text" id="input" disabled="disabled" />
<script src="//"></script>
<script src="./frontend.js"></script>

Hi Martinsik,

I am able to perform chat when i use the url in the browser as "file:///D:/jsfiles/nodejs-chat-IMPORTANT/nodejs-chat/chat.html"

If i use the in the browser as '', i am not able to connect to the server. please let me know the way to access chat application by pointing browser as like ''


This works, if you change line 26 of frontend.html to
<script src="chat-frontend.js"></script>

<script src="frontend.js"></script>

hmm... change the filename from "frontend.js" to "chat-frontend.js"

Is there a license for this gist ... could I make a few changes and add it to my website?


martinsik commented Jan 13, 2013

Feel free to use it as you want. Just if you were publishing it somewhere, please, provide a link back to this original source.

The reason this didn't work is because when client.html request frontend.js the server doesnt return the file.
The author left the HTTP server handler empty.
You need to modules:
var url = require("url");
var st = require('node-static');

var fileServer = new st.Server('./');

and change the handle to

var server = http.createServer(function(request, response) {
request.addListener('end', function () {
var _get = url.parse(request.url, true).query;
fileServer.serve(request, response);


Thanks for the script.

am not able to type on textfield (frontend.html)

rayj00 commented Feb 26, 2016

Very nice. Thanks.

if you are running the htlm as file on the browser then on frontend.html replace lines 25,26 with the following and everything runs fine

<script src=""></script>
<script src="./chat-frontend.js"></script>

Martinsik thanks for sharing !

to serve the frontend.html direct from the chat-server.js you need to do these:

install finalhandler and serve-static with the npm
npm install finalhandler serve-static

in the file chat-server.js replace line 39

// Not important for us. We're writing WebSocket server, not HTTP server


    var done = finalhandler(request, response);
    serve(request, response, done);

at line 21 add these lines

var finalhandler = require('finalhandler');
var serveStatic = require('serve-static');

var serve = serveStatic("./");

int the file frontend.html replace line 26
<script src="./frontend.js"></script>
<script src="./chat-frontend.js"></script>

finally call the chat page with

jwaldron92 commented Jun 22, 2016 edited

Like why would your write; "//" and

When the file is ""

besides that, great job. Can you reference how to put this online with backend saving?

Voakie commented Aug 2, 2016

Found a little typo:
('Unable to *comminucate* ' + 'with the WebSocket server.');

Great work nonetheless!


ghost commented Aug 11, 2016

How are the username, color and other things trashed when user closes connection?

ivandi1980 commented Oct 2, 2016 edited

Thanks kalxasath, it works for me.....
very nice chat...

tentenponce commented Mar 15, 2017 edited

Found a bug. Wrong splicing of clients due to handling of index.

Try to connect two clients on websocket
Refresh the first client
Refresh the second client
One of them will not be able to receive any messages due to their connection has been spliced on disconnect.


connection.on('close', function(connection) {
        if (userName !== false && userColor !== false) {
            console.log((new Date()) + " Peer "
                + connection.remoteAddress + " disconnected.");
            // loop to the clients and compare remote address to be removed
           for (var i = 0; i < clients.length; i ++) {
                if (connection.remoteAddress == clients[i].remoteAddress) { //compare remote address to remove from the disconnecting client
                     clients.splice(i, 1);
            // push back user's color to be reused by another user

Thanks by the way for this tutorial, very helpful :)

mingyun commented Apr 1, 2017


fanfare commented May 15, 2017 edited

Found a bug in tentenponce's patch.

Everything appears to be a working fine, only because clients.splice(i, 1) is never called, ever.. (note that 'connection' is being passed into the callback function.. thus connection.remoteAddress is always undefined) and therefore no client splicing, and the clients array will become gigantic over time. This fix should do the trick (note it is no longer ensuring userName and userColor are true, because if someone was sitting there refreshing the page, that would keep pushing new connections to the client array.)

connection.on('close', function(e) {
  for (var i = 0; i < clients.length; i ++) {
    if ((connection.remoteAddress == clients[i].remoteAddress) 
      && (connection.socket._peername.port == clients[i].socket._peername.port)) {
      clients.splice(i, 1)

rayj00 commented Jun 8, 2017

I started to play with this script about a year ago, but had to abandon in lieu of more pressing issues...
On the console, I get Thu Jun 08 2017 16:45:10 GMT-0400 (EDT) Server is listening on port 1337.

How ever on the client, I am getting "Sorry, bit there's some problem with your connection or the server is down" in the chat response box.
In the chat enter box I am getting Error Unable to communicate with the Websocket server.

Any ideas?


Same here!

rayj00 commented Jun 20, 2017 edited

So I am trying again to get this to work. I have a new Ubuntu 16.04.2.
I put all three files (chat-frontend.js, chat-server.js and frontend.html in the same directory.
Then I did sudo node chat-server.js and got: Tue Jun 20 2017 13:11:29 GMT-0400 (EDT) Server is listening on port 1337
Browsing to just sits there rolling, Waiting for

And yes I renamed the frontend.js file to chat-frontend.js



rayj00 commented Jun 21, 2017 edited

Tried the above suggested fixes. Nothing helps.
I know I had this script farther along about a year ago.
I know I could access the html page, but I could not get a connection to the server.
Now I am stuck. It will not even serve up the html?

And BTW, the only change I remember doing is the filename change from frontend.js to chat-frontend.js.
So I don't know what all the above changes are for?

Can anyone provide working code and just how you store the files and call the chat.

rayj00 commented Jun 21, 2017

Ah....forget the above post. I fat fingered.

So now I am back to
chat error

rayj00 commented Jun 21, 2017

Ok got up to entering my name but after I enter my name, it still says: Choose Name: Then eventually says Unable to comminucate with the WebSocket server. in the text entry box. But the message display area is blank, so I assume that's good?

rayj00 commented Jun 21, 2017

Ok, now I cannot get beyond the "Choose Name" step. If I just let it sit at Choose Name (after entering a name) it eventually ends up with Error Unable to comminucate with the WebSocket server.

Globik commented Jul 31, 2017 edited

@rayj00 install express.js, change the server code and don't sack any more. Also use better npm install ws. It's better than websocket.js.

Thanks for such a nice code

hotdang-ca commented Sep 5, 2017 edited

Just wanted to put this here, for those who don't really like jQuery:

Pure Javascript chat-frontend.js

Excellent article, helped me break away from websocket abstractions such as or Pusher.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment