Real-time Presentation Slides with Socket.io, Express, Node.js and JavaScript

  • This tutorial requires Node.js v7 or higher.
  • We will try and use as little Socket.io code as possible. This means we won’t modify any configurations and will just use the library as it is right out of the box.
  • We will add basic console logging to help debug and visualize the connection flow but these aren’t needed for the app to work.
  • For simplicity’s sake, we will be writing on-page javascript inside our html files. In practice, our JavaScript would exist in different files and we would use a module bundler or build config system like webpack to bundle it all together in an appropriate fashion. We are going to skip that for this tutorial just to keep things light.
  • We will use ES6 syntax on both the server and client.

The point of this tutorial is to show you how EASILY you can begin adding real-time interactivity as a part of the apps you build.

mkdir realtime-slides-tut
cd realtime-slides-tut
touch package.json
{
"name": "realtime-slides-tut",
"version": "0.0.1",
"description": "Real-time slides tutorial with Socket.io",
"dependencies": {}
}
npm install --save express socket.io showdown
  • Express allows us to create the webserver and REST API needed to run our app
  • Socket.io is the real-time engine (utilizing the WebSocket API)
  • Showdown converts Markdown (a simple plain text formatting syntax) into HTML for us
server.js
[ server.js ] Listening on port 8000
mkdir views
touch views/show.html views/edit.html
├── node_modules
├── package-lock.json
├── package.json
├── server.js
└── views
├── edit.html
└── show.html
<h1>view: show</h1>
<h1>view: edit</h1>
server.js
  • User goes to / (ie. performs a GET request to localhost:8000/) => respond with show.html
  • User goes to /edit (ie. performs a GET request to localhost:8000/edit) => respond with edit.html
$ curl localhost:8000/
<h1>view: show</h1>
$ curl localhost:8000/edit
<h1>view: edit</h1>

Now that our views and routes are set up, let’s get our WebSocket connections up and running.

server.js
// Socket Eventsio.on('connection', (socket) => {
console.log(`[ server.js ] ${socket.id} connected`);
socket.on('disconnect', () => {
console.log(`[ server.js ] ${socket.id} disconnected`);
});
});
views/show.html
const io = require('socket.io')(server);
  <script type="text/javascript">    const socket = io();  </script>

Now let’s begin implementing the logic pertaining to presentation slides.

  <script type="text/javascript">    const socket = io();    socket.on('update slide', () => {
alert("UPDATE SLIDE");
});
</script>
// Socket Eventsio.on('connection', (socket) => {
console.log(`[ server.js ] ${socket.id} connected`);
socket.emit('update slide'); socket.on('disconnect', () => {
console.log(`[ server.js ] ${socket.id} disconnected`);
});
});
  1. A client establishes a WebSocket connection to localhost:8000 (ie. a single user opens our page).
  2. The server-side io object handles that connection and gets access to its relating socket object.
  3. The server-side io object emits an update slide event to that client through the socket object.
  4. The client receives that update slide event and shows an alert.

Now let’s modify it a bit so we can send some data along with the events we emit.

// Socket Eventsio.on('connection', (socket) => {
console.log(`[ server.js ] ${socket.id} connected`);
socket.emit('update slide', `Hello ${socket.id}`); socket.on('disconnect', () => {
console.log(`[ server.js ] ${socket.id} disconnected`);
});
});
  <script type="text/javascript">    const socket = io();    socket.on('update slide', (data) => {
alert(data);
});
</script>
  • On the server, io.emit( ... ) emits the event to ALL connected clients
  • On the server and client, socket.emit( ... ) emits the event between a specific client and the server

Now what if we want to trigger a real-time action (such as broadcasting a message to all connected clients) using an HTTP request?

// Socket Eventsio.on('connection', (socket) => {
console.log(`[ server.js ] ${socket.id} connected`);
socket.on('disconnect', () => {
console.log(`[ server.js ] ${socket.id} disconnected`);
});
});
function updateSlide(html) {
io.emit('update slide', html);
}
server.js — API
  • The endpoint /api/updateSlide handles a GET request
  • In the handler, if the query params contain the var html (i.e. localhost:8000/api/updateSlide?html=hello%20world) then we call the updateSlide(html) function with the given value
  • That in turn calls io.emit('update slide', html) with our relevant data
$ curl localhost:8000/api/updateSlide?html=hello%20world
Received 'updateSlide' request with: hello world
[ server.js ] GET request to 'api/updateSlide' => {"html":"hello world"}
views/show.html — body
#Hello World
Let's build a real-time app!
<h1>Hello World</h1>
<p>Let's build a real-time app!</p>
const express = require('express');
const http = require('http');
const showdown = require('showdown');
const path = require('path');
const app = express();
const server = http.Server(app);
const io = require('socket.io')(server);
const converter = new showdown.Converter();
// Socket Eventsio.on('connection', (socket) => {
console.log(`[ server.js ] ${socket.id} connected`);
socket.on('disconnect', () => {
console.log(`[ server.js ] ${socket.id} disconnected`);
});
});
function updateSlide(markdown) {
io.emit('update slide', converter.makeHtml(markdown));
}
server.js — API
<h1>Hello World</h1>
<p>Let's build a realtime app!</p>
  • hash: # is %23
  • space is %20
  • newline: \n is %0A
  • apostrophe: ' is %27
  • hyphen: - is %2D
views/edit.html
  • We have a simple textarea where we can enter our Markdown
  • We’ve also got a div with the id submit-button that once clicked will invoke the sendUpdateSlideRequest(markdown) helper function
  • The sendUpdateSlideRequest(markdown) function generates a GET request to the endpoint api/updateSlide with the appropriately encoded data in the URL params

Functionality wise, we are almost done! We just need to add some additional features and styling for polish.

edit.html
show.html — Styles
edit.html — Styles

--

--

--

is a musician and full-stack web developer from Toronto, Canada who studied Computer Science and Linguistics at the University of Toronto.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

A simple introduction to state management with MobX in React Native

Understanding Map, Filter and Reduce in JavaScript

How to accept command line arguments in Node.js scripts?

How to accept command line arguments in Node.js scripts?

Issue #17: No violence!

How To Use Media Queries Programmatically in React

How to export filtered data in Django?

//platform.twitter.com/widgets.js from Twitter https://twitter.com/thepoolsideceo

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nafeu Nasir

Nafeu Nasir

is a musician and full-stack web developer from Toronto, Canada who studied Computer Science and Linguistics at the University of Toronto.

More from Medium

Why beginners should avoid using ExpressJS?

What is node.js and how it works Event loop

Node Js CRUD Operation: