Realtime everywhere! If you are an ardent follower of the trends in the industry, especially the web development ecosystem, you will agree with me that a larger percentage of users appreciate realtime responses from web applications. This may be in the form of notifications, events, alerts, instant messaging or anything similar to these. Only a few platforms offer realtime technologies applicable for use in realtime digital experiences like Gaming and Gambling, Chat and Social, Data Content, Notifications and Alert and so on. This is where as a company shines. Ably To explore the realtime technology, I have always wanted to try out and after reading this I had to get down to work. So when I finally got the chance, I was able to explore the awesomeness of realtime functionality as offered by by building the following application: Ably post Ably This is a realtime opinion poll built with Nest.js and powered by . In this article, I am going to document the stage by stage process of how I was able to build the demo shown above. Ably Pre-requisites To get the most out of this tutorial, a basic understanding of TypeScript and Node.js is advised. Tools we will use the following tools to build this app : : A progressive Node.js framework for building efficient and scalable server-side applications. It leverages on TypeScript to create reliable and well structured server-side application. If you are quite conversant with Angular, Nest.js gives you similar experience of building an Angular app, but on the backend. Despite using modern (Typescript), it’s quite compatible with vanilla JavaScript which makes it very easy to get started with. You can read more about it . Nest.js JavaScript here Nest.js Ably : An excellent messaging platform that makes it easy to add realtime functionality to applications. realtime Ably Realtime Axios : A promise-based HTTP client that works both in the browser and in a node.js environment. CanvasJS: A responsive HTML5 Charting library for data visualisation. Lastly, we will also need to install few modules using npm Setting up the Application Its super easy to setup a new application using Nest.js, but before we proceed, it is assumed that you already have node and npm installed. If not, kindly check the and websites for installation steps. node.js npm To begin, use the commands below to clone a new starter repository, change directory into the newly created project folder and finally install all the required dependencies for Nest.js application. $ git clone https://github.com/nestjs/typescript-starter.git ably-nest-poll $ cd ably-nest-poll $ npm install Run the Application $ npm run start This will start the application on the default port used by Nest.js (3000). Head over to http://localhost:3000 Ably Account Setup If you don’t already have an ably account, head over to and create one. their website Follow the remaining process and once you are done, you should have a free account with a private key. You will see an ‘API key’ on your account dashboard, this is of importance to us as we’ll use it later in the tutorial to connect to using the Basic Authentication scheme. Ably You will see that by default, creates an app for you which you can readily start using. However, you can also create a new application and configure it according to your needs. Ably I have named mine . Feel free to choose any name that suits your purpose. 'ably-nest-poll' Dependencies Use the to install dependencies for the application: Node Package Manager npm install ejs ably --save Bootstrap application One of the core files in Nest.js is This file contains the necessary functions with the responsibility of bootstrapping our application. Nest favours the popular MVC pattern and therefore allows the usage of template engine. Open and fill with : 'main.ts’ '.src/main.ts’ { NestFactory } '@nestjs/core'; { ApplicationModule } './app.module'; import from import from * express 'express'; // import import express module as from // path * path 'path'; import as from bootstrap() { app = NestFactory.create(ApplicationModule); async function const await // A public folder to serve static files .use(express.static(path.join(__dirname, 'public'))); app .set('views', __dirname + '/views'); app // set ejs as the view engine .set('view engine', 'ejs'); app app.listen(3000);}bootstrap(); await The only addition I have made to the default configuration of this file is to import Express module, path and finally set as the view engine for the application. ejs Set Up the View In order to render the HTML output and display the application to users, we will create a folder called within the folder. Now, within this newly created folder, create a new file and name it views src index.ejs Then add the following code to your file: 'index.ejs' <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css"><title>Realtime Poll</title></head><body> <div class="container"> <h1> Marvel Movies </h1> <p> Select your favorite Marvel Movie </p> <form id="opinion-form"> <p> <input type="radio" name="movie" id="avengers" value="The Avengers"> <label for="avengers">The Avengers</label> </p> <p> <input type="radio" name="movie" id="black-panther" value="Black Panther"> <label for="black-panther">Black Panther</label> </p> <p> <input type="radio" name="movie" id="captain-america" value="Captain America"> <label for="captain-america">Captain America</label> </p> <p> <input type="radio" name="movie" id="other" value="Other"> <label for="other">Something Else </label> </p> <input type="submit" value="Vote" class="btn btn-success"/> </form> <br><br> <div id="chart-container" style="height:300px;width:100%;"> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"></script> <script src="http://cdn.ably.io/lib/ably.min-1.0.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.min.js"></script> <script src="/main.js"></script> </body></html> This will serve as the homepage for our realtime poll application. In order to make this page look presentable, I included a CDN file each for Materialize, Ably, CanvasJS and JQuery. Further, I’ve included a form with radio-button input fields and finally linked a custom script named that we’ll visit later on in this tutorial. main.js Handling Route Route is handled within Nest.js by the controller layer. This receives the incoming requests and returns a response to the client. Nest uses a Controller metadata to map routes to a specific controller. For now, we will make use of the default controller to set up the homepage for our demo app. So edit and add the code shown below : '@Controller' '.src/app.controller.ts' { Get, Controller, Res } '@nestjs/common'; import from @Controller() AppController {@Get()root(@Res() res) {res.render('index');}} export class The above code lets us manipulate the response by injecting the response object using the decorator. This will ensure that Nest maps every route to the file. @Res() '/' 'index.ejs' Create a Controller The next thing we need to build is the controller for poll. This will handle every request once a user selects a choice and submit votes. So go ahead and create a new folder named in your folder and then create a file within it. Paste the following code in the newly created file. poll 'src' 'poll.controller.ts' { Controller, Post, Res, Body } '@nestjs/common'; import from // import pollService { PollService } './poll.service'; import from @Controller('poll') PollController { export class // inject service **constructor**(**private** pollService: PollService) {} @Post() submitVote(@Res() res, @Body() poll: **string**) { **this**.pollService.create(poll); res.render('index'); } } A quick peek into the code above, you will realize that we imported a service and injected it into the controller through the constructor, this is recommended by Nest in order to ensure controllers handles only HTTP requests. This service will perform a task of publishing payload to . We will create this service in a bit. Ably PollService In addition, the tells the framework that we expect this controller to respond to requests posted to route. @Controller(‘poll’) /poll Realtime Service Basically, we want to utilize one of the core functionalities of , which is publishing messages or payload to and ensure that every connected client or device on that channel receives them in realtime by means of subscription. This is where really shines; you get to focus on building apps and allow the platform to use their internal infrastructure to manage communication without you having to worry about it Ably Ably Ably Lets create a component as a service within Nest.js . This will be used to publish a payload to on a specified channel. Ably Controllers in Nest.js only handle HTTP requests and delegate complex tasks to components. Components here are plain TypeScript classes with @Component decorator. So create a new file within folder named poll poll.service.ts { Component } '@nestjs/common'; import from @Component() PollService { export class **private** poll: **string**; create(poll) { **const** Ably = require('ably'); // replace with your API Key **var** ably = **new** Ably.Realtime('YOUR\_KEY'); **var** channel = ably.channels.get('ably-nest'); **const** data = { points: 1, movie: poll.movie }; channel.publish('vote', data); } } Here, I required the ably module that was installed earlier and passed in the required API key. Also, I created a unique channel for clients to subscribe to. I also have the publish method which takes in two parameters, one is an optional message event name and the other is a payload to be published. ably-nest Connecting the dots At the moment, our application doesn’t recognise any newly created controller and service. We need to change this by editing our module file and put controller into the array and service into array of the decorator respectively. 'app.module.ts' 'controller' 'components' '@Module() { PollController } './poll/poll.controller'; { Module } '@nestjs/common'; { AppController } './app.controller'; { PollService } './poll/poll.service'; import from import from import from import from @Module({imports: [],controllers: [AppController, PollController],components: [PollService],}) ApplicationModule {} export class Plug in Ably client-side and update UI Just a quick recap before the final stage. So far, in this tutorial, we have Created a form with radio buttons for users to cast and submit polls. We went further to create an account on Ably Set up an homepage Created a controller to handle post route. Setup a service to publish payloads to a named channel on and ably-nest Ably Lastly, we registered the newly created controller and service within our application module. Remember that we included a custom file in our file? Go ahead a create a new folder called within the folder then create the file within it. Further, add the following code to the file. 'main.js' index.ejs public src main.js form = document.getElementById('opinion-form'); const // form submit eventform.addEventListener('submit', (e) => { choice = document.querySelector('input[name=movie]:checked').value; data = {movie: choice}; const const axios.post('/poll', data).then( (data) => { console.log(data); }); e.preventDefault(); }); let dataPoints = [{label: 'The Avengers', y: 0},{label: 'Black Panther', y: 0},{label: 'Captain America', y: 0},{label: 'Other', y: 0},]; chartContainer = document.querySelector('#chart-container'); const (chartContainer) { chart = CanvasJS.Chart('chart-container', {animationEnabled: ,theme: 'theme1',title: {text: 'Favorite Movies'},data: [{type: 'column',dataPoints: dataPoints}]}); if const new true chart.render(); **var** ably = **new** Ably.Realtime('YOUR\_KEY'); **var** channel = ably.channels.get('ably-nest'); channel.subscribe('vote', **function**(poll) { dataPoints = dataPoints.map(x => { **if** (x.label == poll.data.movie) { x.y += poll.data.points; **return** x; } **else** { **return** x; } }); chart.render(); }); } This content of this file is self explanatory, we handle form submission and post to the route using . poll axios We also set a default for our chart and finally subscribe to the payload posted from the server. dataPoints Don’t forget to replace the with the appropriate API KEY from your dashboard. YOUR_KEY Bringing it all together Restart the development server again if it is currently running and navigate to or to check it out. http://localhost:3000 http://127.0.0.1:3000 And that is it. If you miss any of the steps, you can find the code for this demo on GitHub here Conclusion We have successfully achieved two things in this tutorial: Get introduced to building web applications using Nest.js Explore the realtime functionality offered by Ably If you would like to find out more about how channels, publishing and subscribing works, see the or better still learn more about the complete set of . Realtime channels & messages documentation Ably features