<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rahat Khanna</title>
    <description>The latest articles on DEV Community by Rahat Khanna (@mappmechanic).</description>
    <link>https://dev.to/mappmechanic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F54723%2Fef81ce2e-8c8c-4e09-8278-477e5c122772.png</url>
      <title>DEV Community: Rahat Khanna</title>
      <link>https://dev.to/mappmechanic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mappmechanic"/>
    <language>en</language>
    <item>
      <title>How to build a live comment feature using Javascript &amp; Pusher?</title>
      <dc:creator>Rahat Khanna</dc:creator>
      <pubDate>Mon, 22 Jan 2018 13:00:49 +0000</pubDate>
      <link>https://dev.to/mappmechanic/how-to-build-a-live-comment-feature-using-javascript--pusher--5akl</link>
      <guid>https://dev.to/mappmechanic/how-to-build-a-live-comment-feature-using-javascript--pusher--5akl</guid>
      <description>&lt;p&gt;These days &lt;strong&gt;Social&lt;/strong&gt; has become the buzzword and we all want our apps to be the centre of these amazing social conversations. Comments on a post, video, update or any feature of your new app is a great way to add fun &amp;amp; enriching social conversations to your App.&lt;/p&gt;

&lt;p&gt;If these conversations can be Realtime, then it's even better, so in this blog post we will be discussing how we can create a realtime comment feature for our web apps using &lt;strong&gt;Pusher&lt;/strong&gt; with &lt;strong&gt;Vanilla Javascript&lt;/strong&gt; on front end &amp;amp; &lt;strong&gt;NodeJS&lt;/strong&gt; on the backend.&lt;/p&gt;

&lt;p&gt;We will call this realtime comment system &lt;strong&gt;Flash Comments&lt;/strong&gt;, which can be re-used for multiple posts/features in your app and can generate amazing conversations in real time. Only basic HTML, CSS &amp;amp; JS knowledge is required to follow through this blog post. Our app will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-app-video-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-app-video-1.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sections
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Brief Introduction to Pusher&lt;/li&gt;
&lt;li&gt;Signing Up with Pusher&lt;/li&gt;
&lt;li&gt;NodeJS &amp;amp; Express App for exposing a Comment Creation API &amp;amp; trigger Pusher Event&lt;/li&gt;
&lt;li&gt;Front End using Vanilla JS subscribing to Channel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Skip the first two sections, if you have already signed up with Pusher.&lt;/p&gt;

&lt;h1&gt;
  
  
  Brief Introduction to Pusher
&lt;/h1&gt;

&lt;p&gt;Pusher is an amazing platform which abstracts the complexities of implementing a Realtime system on our own using Websockets or Long Polling. We can instantly add realtime features to our existing web applications using Pusher as it supports wide variety of SDKs. Integration kits are available for variety of front end libraries like &lt;strong&gt;Backbone, React, Angular, jQuery etc&lt;/strong&gt; and also backend platforms/languages like &lt;strong&gt;.NET, Java, Python, Ruby, PHP, GO etc&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Signing up with Pusher
&lt;/h1&gt;

&lt;p&gt;You can create a free account in Pusher at this link &lt;a href="http://pusher.com/signup" rel="noopener noreferrer"&gt;http://pusher.com/signup&lt;/a&gt;. After you signup and login for the first time, you will be asked to create a new app as seen in the picture below. You will have to fill in some information about your project and also the front end library or backend language you will be building your app with. You also have an option to select the cluster of Pusher based on your users location distribution, I have chosen &lt;code&gt;ap2 (Mumbai, India)&lt;/code&gt; as I may be building an app for the India region.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-img2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-img2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this particular blog post, we will be selecting &lt;strong&gt;Vanilla JS&lt;/strong&gt; for the front end and &lt;strong&gt;NodeJS&lt;/strong&gt; for the backend as seen in the picture above. This will just show you a set of starter sample codes for these selections, but you can use any integration kit later on with this app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-img3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-img3.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  NodeJS App
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Initialising Node Project
&lt;/h2&gt;

&lt;p&gt;You can create a new folder named &lt;strong&gt;flash-comments&lt;/strong&gt; and run the following command at the root of the folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will ask you bunch of information regarding the app and it will create a new package.json file inside your folder.&lt;/p&gt;

&lt;p&gt;We will be using the fairly simple and popular &lt;strong&gt;Express&lt;/strong&gt; framework in Node. Now, we will install the important packages that will be used in our minimal Express app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; express body-parser path &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing all required &lt;code&gt;npm&lt;/code&gt; modules, now we will create an entry point file for our &lt;strong&gt;Node&lt;/strong&gt; app as &lt;code&gt;server.js&lt;/code&gt; inside the root folder. Add the following basic code for a basic HTTP Server to be run using port &lt;code&gt;9000&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="c1"&gt;// Error Handler for 404 Pages&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;error404&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Route Not Found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;error404&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error404&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Example app listening on port 9000!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pusher has an open source NPM module for &lt;strong&gt;NodeJS&lt;/strong&gt; integrations which we will be using. It provides a set of utility methods to integrate with &lt;strong&gt;Pusher&lt;/strong&gt; APIs using a unique appId, key &amp;amp; a secret. We will first install the pusher &lt;code&gt;npm&lt;/code&gt; module using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;pusher &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can use require to get the Pusher module and to create a new instance passing an options object with important keys to initialise our integration. For this blog post, I have put random keys; you will have to obtain it for your app from the Pusher dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Pusher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pusher&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pusher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pusher&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;303964&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;82XXXXXXXXXXXXXXXXXb5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7bXXXXXXXXXXXXXXXX9e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ap2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will have to replace the &lt;strong&gt;appId&lt;/strong&gt;, &lt;strong&gt;key&lt;/strong&gt; &amp;amp; a &lt;strong&gt;secret&lt;/strong&gt; with values specific to your own app. After this, we will write code for a new API which will be used to create a new comment. This api will expose the route &lt;code&gt;/comment&lt;/code&gt; with HTTP &lt;code&gt;POST&lt;/code&gt; method and will expect an object for comment with the properties name, email &amp;amp; comment. Add the following code to your &lt;code&gt;server.js&lt;/code&gt; file before the app.listen part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/comment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newComment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;pusher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flash-comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_comment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newComment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we have extracted the data from &lt;code&gt;req.body&lt;/code&gt; into a &lt;code&gt;newComment&lt;/code&gt; object and then used it to call the trigger method on &lt;strong&gt;Pusher&lt;/strong&gt; instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Pusher Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Channel
&lt;/h3&gt;

&lt;p&gt;In Pusher, we have a conceptual grouping called &lt;strong&gt;Channels&lt;/strong&gt; and it provides the basic way to filter data in Pusher. A Channel can represent many entities in a real world application. For example: In our comments app, a channel can be comments for a specific Article, video, blog post, photo, live streaming of an event etc.&lt;/p&gt;

&lt;p&gt;We would create a new unique channel id for each of these entities to uniquely identify or group data like comments associated with any one of these. Two unique live streaming videos should also have separate &lt;strong&gt;Channel&lt;/strong&gt; so that we can show the respective live comments stream on their respective pages.&lt;/p&gt;

&lt;p&gt;So we will create a new unique channel for each entity with their unique id, so for example a Youtube video comments channel can be named &lt;code&gt;comments-youtube-234&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are three types of channel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public Channel&lt;/strong&gt; - can be subscribed by anyone who knows the name of the channel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private Channel&lt;/strong&gt; - channel which can be subscribed by authorised users only. If the channel name has a &lt;code&gt;private-&lt;/code&gt; prefix, it will be regarded as a private channel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Presence Channel&lt;/strong&gt; - this is a special channel type similar to private as only authorised users can subscribe, where the subscribers list is also maintained and notified to other users also. Channel name should have a prefix &lt;code&gt;presence-&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use a public channel in our blog post which we are naming as &lt;strong&gt;flash-comments&lt;/strong&gt; but you should ideally use a private channel for commenting systems with unique name for each entity you want to enable commenting feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Event
&lt;/h3&gt;

&lt;p&gt;Now, the real data in pusher is transmitted through events which is the primary way of packaging messages. An event can be triggered by a backend or even client in special cases for any particular channel. A channel is required to ensure that your message reaches the intended recipient.&lt;/p&gt;

&lt;p&gt;We give a unique name to each &lt;strong&gt;event&lt;/strong&gt; so that we can setup handlers for receiving and processing these event messages at each of our client end who has subscribed to any channel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pusher Trigger Method
&lt;/h3&gt;

&lt;p&gt;Now we will understand our server side code for sending an &lt;strong&gt;Event&lt;/strong&gt; to the pusher channel &lt;strong&gt;flash-comments&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;pusher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flash-comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_comment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newComment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using the &lt;code&gt;.trigger(channel-name,event-name, payload)&lt;/code&gt;** to send an **Event from the server whenever the &lt;code&gt;POST API&lt;/code&gt; is called for creating a new comment. For the simplicity of this blog post, we will not use any database to save and persist the comments but in a production system, you would be required to store a comment corresponding to a unique entity id like a Youtube Video ID or a Blog Post ID.&lt;/p&gt;

&lt;p&gt;Now, we can run our server using &lt;code&gt;node server&lt;/code&gt; command. Our web service will be accessible on the URL &lt;code&gt;http://localhost:9000/comment&lt;/code&gt;.We can write a POST request using any chrome extension like POSTMan or even &lt;strong&gt;CURL&lt;/strong&gt; to test if it returns &lt;code&gt;{ "created":"true" }&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;The Curl command to test your POST api will be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -H "Content-Type: appliaction/json" -X POST -d '{"name":"Rahat Khanna","email":"rahat.khanna@yahoo.co.in","comment":"Creating a sample comment"}' http://localhost:9000/comment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of running the CURL command on the terminal will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoc-00-14-docs.googleusercontent.com%2Fdocs%2Fsecuresc%2Fha0ro937gcuc7l7deffksulhg5h7mbp1%2Ffldks8a039ehs4grhsior17396hmosvo%2F1488549600000%2F09074992365332311988%2F%2A%2F0B1OCkZMZ1m7sS0xLM0xhT3Y3OUE" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoc-00-14-docs.googleusercontent.com%2Fdocs%2Fsecuresc%2Fha0ro937gcuc7l7deffksulhg5h7mbp1%2Ffldks8a039ehs4grhsior17396hmosvo%2F1488549600000%2F09074992365332311988%2F%2A%2F0B1OCkZMZ1m7sS0xLM0xhT3Y3OUE"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Front End using Vanilla JS
&lt;/h1&gt;

&lt;p&gt;Now, we will be writing the most crucial part, the front end code using Vanilla JS. In the front end code we will be developing a Comments box section which would have following 2 features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Display&lt;/strong&gt; all the Live Comments added to the channel with a smooth animation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add&lt;/strong&gt; new comment to the live comments by hitting the POST Api we have just created&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create a folder named public &amp;amp; create an index.html
&lt;/h2&gt;

&lt;p&gt;We have already written code in our &lt;code&gt;server.js&lt;/code&gt; to serve static content from &lt;code&gt;public&lt;/code&gt; folder, so we will write all our front end code in this folder.&lt;/p&gt;

&lt;p&gt;Please create a new folder &lt;code&gt;public&lt;/code&gt; and also create an empty &lt;code&gt;index.html&lt;/code&gt; for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Add Boilerplate Code to our index.html
&lt;/h2&gt;

&lt;p&gt;We will be adding some basic boilerplate code to setup the base structure for our web app like Header, Sections where content like video or blog post can be put and also the section which will contain our &lt;strong&gt;Flash Comments&lt;/strong&gt; box.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="na"&gt;DOCTYPE&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Making Social Comments Realtime &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; Fun with Pusher using Javascript like the Flash&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/purecss@0.6.2/build/pure-min.css"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-UQiGfs9ICog+LwheBSRCt1o5cbyKIHbwjWscjemyBMT9YCUMZffs6UqUTd0hObXD"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css?family=Raleway:200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./style.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./assets/pusher-logo.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flash-logo"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./assets/flash-logo.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Flash Comments - Super Fast&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Put here Content like Youtube Video, Blog Post or Live Stream --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;

           &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flash-comments"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./assets/comments.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Comments&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pure-form"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comment-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Here we will put a form to create new comment --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
                 &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"comments-list"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comments-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Here we will display live comments --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Create style.css file
&lt;/h3&gt;

&lt;p&gt;Now we will also create a &lt;code&gt;style.css&lt;/code&gt; file to contain the important css code for styling our web app and the &lt;strong&gt;flash comments&lt;/strong&gt; component. We will add basic styles to render our skeleton.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Raleway&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2b303b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-logo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;60px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;45px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.logo&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;35px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nc"&gt;.flash-comments&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#aeaeae&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#eaeaea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.header&lt;/span&gt; &lt;span class="nc"&gt;.text&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#eaeaea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Add the Pusher JS Library &amp;amp; create app.js
&lt;/h3&gt;

&lt;p&gt;Now we will add the &lt;strong&gt;Pusher Vanilla JS&lt;/strong&gt; Library available on its CDN to use it to integrate with the Pusher system using plain Javascript code. Please add the following script tag at the end of the body before its closing tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.pusher.com/3.2/pusher.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, create a new &lt;code&gt;app.js&lt;/code&gt; file where we will be writing all our code and also import the same in our &lt;code&gt;index.html&lt;/code&gt; file after the script tag to import &lt;strong&gt;Pusher JS&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.pusher.com/3.2/pusher.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our file &lt;code&gt;app.js&lt;/code&gt; now, we will write code to initialise the Pusher instance using the unique client API key we have got from the Pusher dashboard. We will also pass an object specifying the cluster and setting the flag encrypted to true so that all messaging &amp;amp; communication is encrypted. We will also use the &lt;code&gt;pusher.subscribe('channel-name')&lt;/code&gt; to listen to all events for a specific channel.&lt;/p&gt;

&lt;p&gt;We will create a Javascript IIFE (Immediately Invoking Functions) to create a private scope so that we do not pollute global scope. Please add the following code to &lt;code&gt;app.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using IIFE for Implementing Module Pattern to keep the Local Space for the JS Variables&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Enable pusher logging - don't include this in production&lt;/span&gt;
    &lt;span class="nx"&gt;Pusher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logToConsole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="nx"&gt;pusher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pusher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;82XXXXXXXXXXXXXX5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ap2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="c1"&gt;// Subscribing to the 'flash-comments' Channel&lt;/span&gt;
        &lt;span class="nx"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pusher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flash-comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Creating Form for adding new comment
&lt;/h3&gt;

&lt;p&gt;Now, we will create the form controls for letting the user input their name, email and comment text for creating a new comment using our Node API and Pusher. We will add the following HTML code inside the existing form tag to create form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pure-form"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comment-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"comment-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"left-side"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"enter your name"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"new_comment_name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"enter valid email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"new_comment_email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"enter comment text"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"new_comment_text"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"right-side"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"button-secondary pure-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send Comment&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the form code above, we have used HTML5 validations like required &amp;amp; type=email which would not allow user to keep these fields blank or submit an invalid email. These validations will automatically work in most browsers which support HTML5 form validations.&lt;/p&gt;

&lt;p&gt;Also, we will be adding the following css to style the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment-form&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#eaeaea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nc"&gt;.left-side&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nc"&gt;.left-side&lt;/span&gt; &lt;span class="nc"&gt;.row&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nc"&gt;.left-side&lt;/span&gt; &lt;span class="nc"&gt;.row&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;32px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nc"&gt;.left-side&lt;/span&gt; &lt;span class="nc"&gt;.row&lt;/span&gt; &lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;42px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nc"&gt;.right-side&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nc"&gt;.right-side&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pre-wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.comment-form&lt;/span&gt; &lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.button-secondary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;66&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;184&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;221&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* this is a light blue */&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After building the visual form, now we need to attach an event handler to the Submit event of the form. We will do that using the following code in the &lt;code&gt;app.js&lt;/code&gt; file probably at the top after the var declarations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;commentForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment-form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Adding to Comment Form Submit Event&lt;/span&gt;
&lt;span class="nx"&gt;commentForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addNewComment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will write the code for implementation of the handler &lt;code&gt;addNewComment&lt;/code&gt; with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addNewComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newComment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_comment_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_comment_email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;comment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_comment_text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;comment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json;charset=UTF-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onreadystatechange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// On Success of creating a new Comment&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Success: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;commentForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newComment&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using native XHR request to make an AJAX request to the Node API. You can use either jQuery Ajax or any framework-specific Ajax method in your app. Now if we run our application, then fill the form and submit it, then we will see a &lt;code&gt;Success: { created: true }&lt;/code&gt;message in our browser developer tools console.&lt;/p&gt;

&lt;p&gt;Also, we can see the &lt;strong&gt;Pusher Dashboard&lt;/strong&gt; to see the stats about Event Messages sent for any channel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-debug_console.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-debug_console.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Display List of Comments Received for this Channel
&lt;/h3&gt;

&lt;p&gt;Now, we will bind to the &lt;code&gt;new_comment&lt;/code&gt; event on this channel &lt;code&gt;flash-comments&lt;/code&gt; so that we can receive any message about new comment creation done from any client in realtime, and we can display all those comments.&lt;/p&gt;

&lt;p&gt;We will first add a template for a new comment in our &lt;code&gt;index.html&lt;/code&gt; file inside the div tag with &lt;code&gt;id="comments-list"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"comments-list"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comments-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comment-template"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/x-template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-icon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./assets/user.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;comment-info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;             &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;             &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;             &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will write the Javascript code to bind to the new_comment event on the pusher channel instance we have subscribed. Whenever the &lt;code&gt;new_comment&lt;/code&gt; event will be fired, we will take the template innerHTML content and replace the placeholders &lt;code&gt;{{name}}, {{email}} &amp;amp; {{comment}}&lt;/code&gt;with the data passed along with the event and append them to the &lt;strong&gt;comments-list&lt;/strong&gt; div element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;commentsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comments-list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;commentTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment-template&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Binding to Pusher Event on our 'flash-comments' Channel&lt;/span&gt;
&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_comment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;newCommentReceived&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// New Comment Received Event Handler&lt;/span&gt;
    &lt;span class="c1"&gt;// We will take the Comment Template, replace placeholders &amp;amp; append to commentsList&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;newCommentReceived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newCommentHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;commentTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{name}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;newCommentHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newCommentHtml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{email}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;newCommentHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newCommentHtml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{comment}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newCommentNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;newCommentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;newCommentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newCommentHtml&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;commentsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newCommentNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the above code, a new div tag representing the new comment will automatically be created and appended to the &lt;strong&gt;comments-list&lt;/strong&gt; container. We will now add the following css to nicely display the list of comments and also animate whenever a new comment appears on the list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.user-icon&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.user-icon&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;45px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment-info&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment-info&lt;/span&gt; &lt;span class="nc"&gt;.row&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment-info&lt;/span&gt; &lt;span class="nc"&gt;.name&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment-info&lt;/span&gt; &lt;span class="nc"&gt;.email&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#aeaeae&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment-info&lt;/span&gt; &lt;span class="nc"&gt;.text&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;13px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* CSS Code for Animating Comment Element */&lt;/span&gt;
&lt;span class="nc"&gt;.flash-comments&lt;/span&gt; &lt;span class="nc"&gt;.comment&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation-fill-mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/*when the spec is finished*/&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-animation-fill-mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/*Chrome 16+, Safari 4+*/&lt;/span&gt; 
  &lt;span class="nl"&gt;-moz-animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-animation-fill-mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/*FF 5+*/&lt;/span&gt;
  &lt;span class="nl"&gt;-o-animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-o-animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-o-transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-o-animation-fill-mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/*Not implemented yet*/&lt;/span&gt;
  &lt;span class="nl"&gt;-ms-animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-ms-animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-ms-transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-ms-animation-fill-mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/*IE 10+*/&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1500px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-10px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@-moz-keyframes&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-moz-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1500px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-moz-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;-moz-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-10px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-moz-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@-webkit-keyframes&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1500px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-10px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@-o-keyframes&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-o-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1500px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-o-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;-o-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-10px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-o-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@-ms-keyframes&lt;/span&gt; &lt;span class="n"&gt;animationFrames&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-ms-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1500px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-ms-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;-ms-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-10px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-ms-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can run the app we have built, either in 2 different browsers or one in normal browser and the other in incognito window, and add multiple comments. We can see that the live comments will be added in realtime with a smooth animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-app-video-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F03%2Fbuild-live-commenting-feature-javascript-app-video-1.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The complete code for this tutorial is available on this Github link &lt;a href="https://github.com/mappmechanic/flash-comments" rel="noopener noreferrer"&gt;https://github.com/mappmechanic/flash-comments&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We have built a nice web app with live comment feature using Pusher, NodeJS and Vanilla Javascript. We can use this component with any of our applications and enable live comments for variety of social entities like Videos, Blog Post, Polls, Articles and live streams.&lt;/p&gt;

&lt;p&gt;We have used the NodeJS server to create a REST API to get a new comment and then trigger a Pusher event on a specific channel. For any real world application, we can take a unique id for each entity and use a unique channel name for any entity. In a production scenario we can also store the comments in a persistent storage and then later retrieve them.&lt;/p&gt;

&lt;p&gt;We have also created a Front End app, which will connect to the Pusher API using pusher js library. We have created a form to hit the Node API which will trigger new_comment event. Comments are displayed in realtime with an animation using the bind method on the channel instance.&lt;/p&gt;

&lt;p&gt;This blog post was originally published on Pusher’s blog -&lt;br&gt;
 &lt;a href="http://blog.pusher.com/build-live-comments-feature-using-javascript" rel="noopener noreferrer"&gt;http://blog.pusher.com/build-live-comments-feature-using-javascript&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>realtime</category>
      <category>comment</category>
      <category>pusher</category>
    </item>
    <item>
      <title>How to update a user's status in Realtime using Javascript &amp; Pusher !</title>
      <dc:creator>Rahat Khanna</dc:creator>
      <pubDate>Mon, 22 Jan 2018 12:59:51 +0000</pubDate>
      <link>https://dev.to/mappmechanic/how-to-update-a-users-status-in-realtime-using-javascript--pusher--5d3f</link>
      <guid>https://dev.to/mappmechanic/how-to-update-a-users-status-in-realtime-using-javascript--pusher--5d3f</guid>
      <description>&lt;p&gt;Hey, what's up? is not a phrase we need to ask someone these days. These days knowing what someone is up to has become so easy that we keep seeing updated status for all our friends on Whatsapp, Snapchat, Facebook etc. In this blog post, we will learn how we can update a user's status in realtime component along with a list of all members who are online.&lt;/p&gt;

&lt;p&gt;We will be using &lt;strong&gt;NodeJS&lt;/strong&gt; as the application server, &lt;strong&gt;Vanilla JS&lt;/strong&gt; in the front end and &lt;strong&gt;Pusher&lt;/strong&gt; for realtime communication between our server and front end.&lt;/p&gt;

&lt;p&gt;We will build an app which will be like your friends list or a common chat room where you can see who's online and their latest status update in realtime. In the blog post, we will learn about Pusher's &lt;strong&gt;presence&lt;/strong&gt; channel and how to know about the online members to this channel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-app-animated-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-app-animated-1.gif" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will be building the following components during this blog post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;NodeJS Server using &lt;strong&gt;ExpressJS Framework&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;/register&lt;/strong&gt; API - In order to register/login a new user to our channel and server by creating their session and saving their info&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/isLoggedIn&lt;/strong&gt; API - To check if a user is already logged in or not in case of refreshing the browser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/usersystem/auth&lt;/strong&gt; API - Auth validation done by Pusher after registering it with our app and on subscribing to a presence or private channel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/logout&lt;/strong&gt; API - To logout the user and remove the session&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Front End App using &lt;strong&gt;Vanilla Javascript&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Register/Login Form - To register/login a new user by filling in their username and initial status&lt;/li&gt;
&lt;li&gt;Members List - To see everyone who is online and their updated status&lt;/li&gt;
&lt;li&gt;Update Status - To click on the existing status and update it on blur of the status text edit control&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Find here the &lt;a href="https://github.com/mappmechanic/whats-up-realtime-status-update" rel="noopener noreferrer"&gt;link&lt;/a&gt; to the Github Repository for reference.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to Pusher
&lt;/h1&gt;

&lt;p&gt;Pusher is a platform which abstracts the complexities of implementing a realtime system on our own using Websockets or Long Polling. We can instantly add realtime features to our existing web applications using Pusher as it supports a wide variety of SDKs. Integration kits are available for variety of front end libraries like &lt;strong&gt;Backbone, React, Angular, jQuery etc&lt;/strong&gt; and also backend platforms/languages like &lt;strong&gt;.NET, Java, Python, Ruby, PHP, GO etc&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing up with Pusher
&lt;/h2&gt;

&lt;p&gt;You can create a free account in Pusher &lt;a href="http://pusher.com/signup" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After you signup and login for the first time, you will be asked to create a new app as seen in the picture below. You will have to fill in some information about your project and also the front end library or backend language you will be building your app with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-update-create_app-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-update-create_app-1.png" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this particular blog post, we will be selecting &lt;strong&gt;Vanilla JS&lt;/strong&gt; for the front end and &lt;strong&gt;NodeJS&lt;/strong&gt; for the backend as seen in the picture above. This will just show you a set of starter sample codes for these selections, but you can use any integration kit later on with this app.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-update-getting_started_view-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-update-getting_started_view-1.png" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  NodeJS Server
&lt;/h1&gt;

&lt;p&gt;NodeJS should be installed in the system as a prerequisite to this. Now let us begin building the NodeJS server and all the required APIs using &lt;strong&gt;Express&lt;/strong&gt;. Initialise a new node project by the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing Dependencies
&lt;/h2&gt;

&lt;p&gt;We will be installing the required dependencies like Express, express-session, Pusher, body-parser, cookie-parser by the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install express express-session body-parser cookie-parser --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Foundation Server
&lt;/h2&gt;

&lt;p&gt;We will now create the basic foundation for Node Server and also enable sessions in that using express-session module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var expressSession = require('express-session');
var cookieParser = require('cookie-parser');

var app = express();

// must use cookieParser before expressSession
app.use(cookieParser());

app.use(expressSession({
  secret:'&amp;lt;some-secret-token-here&amp;gt;',
  resave: true, 
  saveUninitialized: true
}));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

// Error Handler for 404 Pages
app.use(function(req, res, next) {
    var error404 = new Error('Route Not Found');
    error404.status = 404;
    next(error404);
});

module.exports = app;

app.listen(9000, function(){
  console.log('Example app listening on port 9000!')
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we have created a basic Express server and using the method &lt;strong&gt;.use&lt;/strong&gt; we have enabled cookie-parser, body-parser and a static file serving from &lt;strong&gt;public&lt;/strong&gt; folder. We have also enabled sessions using &lt;strong&gt;express-session&lt;/strong&gt; module. This will enable us to save user information in the appropriate request session for the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Pusher
&lt;/h2&gt;

&lt;p&gt;Pusher has an open source NPM module for &lt;strong&gt;NodeJS&lt;/strong&gt; integrations which we will be using. It provides a set of utility methods to integrate with &lt;strong&gt;Pusher&lt;/strong&gt; APIs using a unique appId, key and a secret. We will first install the Pusher &lt;code&gt;npm&lt;/code&gt; module using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install pusher --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can use 'require' to get the Pusher module and to create a new instance passing an options object with important keys to initialise our integration. For this blog post, I have put random keys; you will have to obtain it for your app from the Pusher dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var Pusher = require('pusher');

var pusher = new Pusher({
  appId: '30XXX64',
  key: '82XXXXXXXXXXXXXXXXXb5',
  secret: '7bXXXXXXXXXXXXXXXX9e',
  encrypted: true
});

var app = express();
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will have to replace the &lt;strong&gt;appId&lt;/strong&gt;, &lt;strong&gt;key&lt;/strong&gt; and a &lt;strong&gt;secret&lt;/strong&gt; with values specific to your own app. After this, we will write code for a new API which will be used to create a new comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Register/Login API
&lt;/h2&gt;

&lt;p&gt;Now, we will develop the first API route of our application through which a new user can register/login itself and make itself available on our app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post('/register', function(req, res){
  console.log(req.body);
  if(req.body.username &amp;amp;&amp;amp; req.body.status){
    var newMember = {
      username: req.body.username,
      status: req.body.status
    }
    req.session.user = newMember;
    res.json({  
      success: true,
      error: false
    });
  }else{
    res.json({  
      success: false,
      error: true,
      message: 'Incomplete information: username and status are required'
    });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we have exposed a POST API call on the route &lt;strong&gt;/register&lt;/strong&gt; which would expect &lt;strong&gt;username&lt;/strong&gt; and &lt;strong&gt;status&lt;/strong&gt; parameters to be passed in the request body. We will be saving this user info in the request session.&lt;/p&gt;

&lt;h2&gt;
  
  
  User System Auth API
&lt;/h2&gt;

&lt;p&gt;In order to enable any client subscribing to Pusher &lt;strong&gt;Private&lt;/strong&gt; and &lt;strong&gt;Presence&lt;/strong&gt; channels, we need to implement an auth API which would authenticate the user request by calling &lt;strong&gt;Pusher.authenticate&lt;/strong&gt; method at the server side. Add the following code in the server in order to fulfil this condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post('/usersystem/auth', function(req, res) {
  var socketId = req.body.socket_id;
  var channel = req.body.channel_name;
  var currentMember = req.session.user;
  var presenceData = {
    user_id: currentMember.username,
    user_info: {
      status: currentMember.status,
    }
  };
  var auth = pusher.authenticate(socketId, channel, presenceData);
  res.send(auth);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to provide the specific route in the initialisation of &lt;strong&gt;Pusher Client&lt;/strong&gt; side library which we will see later in this blog post. The Pusher client library will automatically call this route and pass in the channel_name and socket_id properties. We will simultaneously get the user information from the user session object and pass it as presenceData to the &lt;strong&gt;Pusher.authenticate&lt;/strong&gt; method call.&lt;/p&gt;

&lt;h2&gt;
  
  
  IsLoggedIn and Logout API
&lt;/h2&gt;

&lt;p&gt;If the user refreshes the browser, the client side app should detect if the user is already registered or not. We will implement an &lt;strong&gt;isLoggedIn&lt;/strong&gt; API route for this. Also, we need a &lt;strong&gt;logout&lt;/strong&gt; route to enable any user to logout from the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/isLoggedIn', function(req,res){
  if(req.session.user){
    res.send({ 
      authenticated: true 
    });
  }else{
    res.send({ authenticated: false });
  }
});

app.get('/logout', function(req,res){
  if(req.session.user){
    req.session.user = null;
  }
  res.redirect('/');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Front End App using Vanilla JS
&lt;/h1&gt;

&lt;p&gt;We will be developing the front end app now to register a new user with an initial status, see the members who are online and their statuses. We will also build the feature for the logged in user to update their users and all other users will see the updated status in realtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a folder named public and create an index.html
&lt;/h2&gt;

&lt;p&gt;We have already written code in our &lt;code&gt;server.js&lt;/code&gt; to serve static content from &lt;code&gt;public&lt;/code&gt; folder, so we will write all our front end code in this folder.&lt;/p&gt;

&lt;p&gt;Please create a new folder &lt;code&gt;public&lt;/code&gt; and also create an empty &lt;code&gt;index.html&lt;/code&gt; for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Add Boilerplate Code to our index.html
&lt;/h2&gt;

&lt;p&gt;We will be adding some basic boilerplate code to set up the base structure for our web app like Header, Sections where registration form and the members list can be placed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;Whats Up ! Know what other's are up to in Realtime !&amp;lt;/title&amp;gt;
        &amp;lt;link rel="stylesheet" href="https://unpkg.com/purecss@0.6.2/build/pure-min.css" integrity="sha384-UQiGfs9ICog+LwheBSRCt1o5cbyKIHbwjWscjemyBMT9YCUMZffs6UqUTd0hObXD" crossorigin="anonymous"&amp;gt;
        &amp;lt;link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway:200"&amp;gt;
        &amp;lt;link rel="stylesheet" href="./style.css"&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;header&amp;gt;
            &amp;lt;div class="logo"&amp;gt;
                &amp;lt;img src="./assets/pusher-logo.png" /&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div id="logout" class="logout"&amp;gt;
               &amp;lt;a href="/logout"&amp;gt;Logout&amp;lt;/a&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/header&amp;gt;
        &amp;lt;section class="subheader"&amp;gt;
            &amp;lt;img class="whatsup-logo" src="./assets/whatsup.png" /&amp;gt;
            &amp;lt;h2&amp;gt;Whats Up ! Know what other's are up to in Realtime !&amp;lt;/h2&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;section&amp;gt;
           &amp;lt;div id="loader" class="loader"&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;script id="member-template" type="text/x-template"&amp;gt;
            &amp;lt;/script&amp;gt;
           &amp;lt;div id="me" class="me"&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;div id="membersList" class="members-list"&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;div id="signup-form" class="tab-content"&amp;gt;
                &amp;lt;div class="header"&amp;gt;
                    &amp;lt;div&amp;gt;&amp;lt;img src="./assets/comments.png"&amp;gt;&amp;lt;/div&amp;gt;
                    &amp;lt;div class="text"&amp;gt;First Time Sign Up !&amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;form class="pure-form" id="user-form"&amp;gt;
                    &amp;lt;div class="signup-form"&amp;gt;
                        &amp;lt;div class="left-side"&amp;gt;
                            &amp;lt;div class="row"&amp;gt;
                                &amp;lt;input type="text" required placeholder="enter a username or displayname" id="display_name"&amp;gt;
                            &amp;lt;/div&amp;gt;
                            &amp;lt;div class="row"&amp;gt;
                                &amp;lt;textarea placeholder="enter initial status text" required id="initial_status" rows="3"&amp;gt;&amp;lt;/textarea&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                        &amp;lt;div class="right-side"&amp;gt;
                            &amp;lt;button 
                                type="submit" 
                                class="button-secondary pure-button"&amp;gt;Signup/Login&amp;lt;/button&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/form&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;script src="https://js.pusher.com/4.0/pusher.min.js"&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script type="text/javascript" src="./app.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above boilerplate code, we have referenced our main Javascript file &lt;strong&gt;app.js&lt;/strong&gt; and the Pusher client side JS library. We also have a script tag where we will place the template for a member row in the member list. Also, we have two empty div tags with ids &lt;strong&gt;me&lt;/strong&gt; and &lt;strong&gt;membersList&lt;/strong&gt; to contain the logged in member name and info, as well as the list of all other members with their statuses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step3: Style.css
&lt;/h3&gt;

&lt;p&gt;Important to note that we will be showing the signup form for the first time and the MembersList and Logout button will be hidden by default initially. Please create a new file called &lt;strong&gt;style.css&lt;/strong&gt; and add the following css to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body{
    margin:0;
    padding:0;
    overflow: hidden;
    font-family: Raleway;
}

header{
    background: #2b303b;
    height: 50px;
    width:100%;
    display: flex;
    color:#fff;
}


.loader,
.loader:after {
  border-radius: 50%;
  width: 10em;
  height: 10em;
}
.loader {
  margin: 60px auto;
  font-size: 10px;
  position: relative;
  text-indent: -9999em;
  border-top: 1.1em solid rgba(82,0,115, 0.2);
  border-right: 1.1em solid rgba(82,0,115, 0.2);
  border-bottom: 1.1em solid rgba(82,0,115, 0.2);
  border-left: 1.1em solid #520073;
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  transform: translateZ(0);
  -webkit-animation: load8 1.1s infinite linear;
  animation: load8 1.1s infinite linear;
}
@-webkit-keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}


.subheader{
    display: flex;
    align-items: center;
    margin: 0px;
}

.whatsup-logo{
    height:60px;
    border-radius: 8px;
    flex:0 60px;
    margin-right: 15px;
}

.logout{
    flex:1;
    justify-content: flex-end;
    padding:15px;
    display: none;
}

.logout a{
    color:#fff;
    text-decoration: none;
}

#signup-form{
    display: none;
}

input, textarea{
  width:100%;
}


section{
    padding: 0px 15px;
}

.logo img{
    height: 35px;
    padding: 6px;
    margin-left: 20px;
}

#updateStatus{
    display: none;
}

.members-list{
    display: none;
    flex-direction: column;
}

.me {
  display: none;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please try to open the URL &lt;strong&gt;&lt;a href="http://localhost:9000" rel="noopener noreferrer"&gt;http://localhost:9000&lt;/a&gt;&lt;/strong&gt; in your browser and the application will load with the basic register or login form with username and status. The output will look like the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-signup-form2-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-signup-form2-1.png" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Add app.js basic code
&lt;/h3&gt;

&lt;p&gt;Now we will add our Javascript code to have basic utility elements inside a self invoking function to create a private scope for our app variables. We do not want to pollute JS global scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Using IIFE for Implementing Module Pattern to keep the Local Space for the JS Variables
(function() {
    // Enable pusher logging - don't include this in production
    Pusher.logToConsole = true;

    var serverUrl = "/",
        members = [],
        pusher = new Pusher('73xxxxxxxxxxxxxxxdb', {
          authEndpoint: '/usersystem/auth',
          encrypted: true
        }),
        channel,
        userForm = document.getElementById("user-form"),
        memberTemplateStr = document.getElementById('member-template').innerHTML;

    function showEle(elementId){
      document.getElementById(elementId).style.display = 'flex';
    }

    function hideEle(elementId){
      document.getElementById(elementId).style.display = 'none';
    }

    function ajax(url, method, payload, successCallback){
      var xhr = new XMLHttpRequest();
      xhr.open(method, url, true);
      xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
      xhr.onreadystatechange = function () {
        if (xhr.readyState != 4 || xhr.status != 200) return;
        successCallback(xhr.responseText);
      };
      xhr.send(JSON.stringify(payload));
    }

    ajax(serverUrl+"isLoggedIn","GET",{},isLoginChecked);

    function isLoginChecked(response){
      var responseObj = JSON.parse(response);
      if(responseObj.authenticated){
        channel = pusher.subscribe('presence-whatsup-members');
        bindChannelEvents(channel);
      }
      updateUserViewState(responseObj.authenticated);
    }

    function updateUserViewState(isLoggedIn){
      document.getElementById("loader").style.display = "none";
      if(isLoggedIn){
        document.getElementById("logout").style.display = "flex";
        document.getElementById("signup-form").style.display = "none";
      }else{
        document.getElementById("logout").style.display = "none";
        document.getElementById("signup-form").style.display = "block";
      }
    }

    function showLoader(){
        document.getElementById("loader").style.display = "block";
        document.getElementById("logout").style.display = "none";
        document.getElementById("signup-form").style.display = "none";
    }

    // Adding a new Member Form Submit Event
    userForm.addEventListener("submit", addNewMember);


    function addNewMember(event){
      event.preventDefault();
      var newMember = {
        "username": document.getElementById('display_name').value,
        "status": document.getElementById('initial_status').value
      }
      showLoader();
      ajax(serverUrl+"register","POST",newMember, onMemberAddSuccess);
    }

    function onMemberAddSuccess(response){
        // On Success of registering a new member
        console.log("Success: " + response);
        userForm.reset();
        updateUserViewState(true);
        // Subscribing to the 'presence-members' Channel
        channel = pusher.subscribe('presence-whatsup-members');
        bindChannelEvents(channel);
    }
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we have referenced all the important variables we will be requiring. We will also initialise the Pusher library using &lt;strong&gt;new Pusher&lt;/strong&gt; and passing the api key as the first argument. The second argument contains an optional config object in which we will add the key &lt;strong&gt;authEndpoint&lt;/strong&gt; with the custom node api route &lt;strong&gt;/usersystem/auth&lt;/strong&gt; and also add the key &lt;strong&gt;encrypted&lt;/strong&gt; setting it to value true.&lt;/p&gt;

&lt;p&gt;We will create a couple of generic functions to show or hide an element passing its unique id. We have also added a common method named &lt;strong&gt;ajax&lt;/strong&gt; to make ajax requests using XMLHttp object in vanilla Javascript.&lt;/p&gt;

&lt;p&gt;At the load of the page we make an ajax request to check if the user is logged in or not. If the user is logged in, we will directly use the Pusher instance to subscribe the user to a presence channel named &lt;strong&gt;presence-whatsup-members&lt;/strong&gt; , you can have this as the unique chat room or app location where you want to report/track the online members.&lt;/p&gt;

&lt;p&gt;We have also written a method above to &lt;strong&gt;addNewMember&lt;/strong&gt; using an ajax request to the &lt;strong&gt;register&lt;/strong&gt; api route we have built in NodeJS. We will be passing the name and initial status entered into the form.&lt;/p&gt;

&lt;p&gt;We also have a method to update the user view state based on the logged in status. This method does nothing but updates the visibility of members list, logout button and signup form. We have used a &lt;strong&gt;bindChannelEvents&lt;/strong&gt; method when the user is logged in which we will be implementing later in the blog post.&lt;/p&gt;

&lt;p&gt;Please add the following css in &lt;strong&gt;style.css&lt;/strong&gt; file to display the &lt;strong&gt;me&lt;/strong&gt; element appropriately with the username and the status of the logged in user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
.me {
    border:1px solid #aeaeae;
    padding:10px;
    margin:10px;
    border-radius: 10px;
}

.me img{
    height: 40px;
    width: 40px;
}

.me .status{
    padding:5px;
    flex:1;
}

.me .status .username{
    font-size:13px;
    color: #aeaeae;
    margin-bottom:5px;
}

.me .status .text{
    font-size: 15px;
    width:100%;
    -webkit-transition: all 1s ease-in 5ms;
    -moz-transition: all 1s ease-in 5ms;
    transition: all 1s ease-in 5ms;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Add code to render the members list and bindChannelEvents
&lt;/h2&gt;

&lt;p&gt;Now, after subscribing to the channel, we need to bind certain events so that we can know whenever a new member is added to the channel or removed from it. We will also bind to a custom event to know whenever someone updates their status.&lt;/p&gt;

&lt;p&gt;Add the following code to the &lt;strong&gt;app.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Binding to Pusher Events on our 'presence-whatsup-members' Channel

  function bindChannelEvents(channel){
      channel.bind('client-status-update',statusUpdated);
      var reRenderMembers = function(member){
        renderMembers(channel.members);
      }
      channel.bind('pusher:subscription_succeeded', reRenderMembers);
      channel.bind('pusher:member_added', reRenderMembers);
      channel.bind('pusher:member_removed', reRenderMembers);
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above &lt;strong&gt;bindChannelEvents&lt;/strong&gt; method, we use the &lt;strong&gt;channel.bind&lt;/strong&gt; method to bind event handlers for 3 internal events - &lt;strong&gt;pusher:subscription_succeeded&lt;/strong&gt;, &lt;strong&gt;pusher:member_added&lt;/strong&gt;, &lt;strong&gt;pusher:member_removed&lt;/strong&gt; and 1 custom event - &lt;strong&gt;client-status-update&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now we will add the Javascript code to render the list of members. It is important to know that the object which i returned from the &lt;strong&gt;.subscribe&lt;/strong&gt; method has a property called &lt;strong&gt;members&lt;/strong&gt; which can be used to know the information about the logged in user referred by the key &lt;strong&gt;me&lt;/strong&gt; and other members by key &lt;strong&gt;members&lt;/strong&gt;. Add the following code to &lt;strong&gt;app.js&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Render the list of members with updated data and also render the logged in user component

    function renderMembers(channelMembers){
      var members = channelMembers.members;
      var membersListNode = document.createElement('div');
      showEle('membersList');

      Object.keys(members).map(function(currentMember){
        if(currentMember !== channelMembers.me.id){
          var currentMemberHtml = memberTemplateStr;
          currentMemberHtml = currentMemberHtml.replace('{{username}}',currentMember);
          currentMemberHtml = currentMemberHtml.replace('{{status}}',members[currentMember].status);
          currentMemberHtml = currentMemberHtml.replace('{{time}}','');
          var newMemberNode = document.createElement('div');
          newMemberNode.classList.add('member');
          newMemberNode.setAttribute("id","user-"+currentMember);
          newMemberNode.innerHTML = currentMemberHtml;
          membersListNode.appendChild(newMemberNode);
        }
      });
      renderMe(channelMembers.me);
      document.getElementById("membersList").innerHTML = membersListNode.innerHTML;
    }


    function renderMe(myObj){
      document.getElementById('myusername').innerHTML = myObj.id;
      document.getElementById('mystatus').innerHTML = myObj.info.status;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have added the event handler for new member add/remove event to re-render the members list so that it remains updated with the online members only. In order to show the members list we need to add the following style into our file &lt;strong&gt;style.css&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
.member{
    display: flex;
    border-bottom: 1px solid #aeaeae;
    margin-bottom: 10px;
    padding: 10px;
}

.member .user-icon{
    flex:0 40px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.member .user-icon img{
    width:50px;
    height:50px;
}

.member .user-info{
    padding:5px;
    margin-left:10px;
}

.member .user-info .name{
    font-weight: bold;
    font-size: 16px;
    padding-bottom:5px;
}

.member .user-info .status{
    font-weight: normal;
    font-size:13px;
}

.member .user-info .time{
    font-weight: normal;
    font-size:10px;
    color:#aeaeae;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will write the code, to trigger a client event on our channel to notify all users about the status change of the logged in user. Add the following code to your &lt;strong&gt;app.js&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; // On Blur of editting my status update the status by sending Pusher event
    document.getElementById('mystatus').addEventListener('blur',sendStatusUpdateReq);

    function sendStatusUpdateReq(event){
      var newStatus = document.getElementById('mystatus').innerHTML;
      var username = document.getElementById('myusername').innerText;
      channel.trigger("client-status-update", {
        username: username,
        status: newStatus
      });
    }

    // New Update Event Handler
    // We will take the Comment Template, replace placeholders and append to commentsList
    function statusUpdated(data){
      var updatedMemberHtml = memberTemplateStr;
          updatedMemberHtml = updatedMemberHtml.replace('{{username}}',data.username);
          updatedMemberHtml = updatedMemberHtml.replace('{{status}}',data.status);
          updatedMemberHtml = updatedMemberHtml.replace('{{time}}','just now');
      document.getElementById("user-"+data.username).style.color = '#1B8D98';    
      document.getElementById("user-"+data.username).innerHTML=updatedMemberHtml;
      setTimeout(function(){
        document.getElementById("user-"+data.username).style.color = '#000';
      },500);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;IMPORTANT&lt;/em&gt;&lt;/strong&gt;: When we run this code in our browsers, update the status and blur out of the status control, we will get an error in the Javascript console for the Pusher library. To fix this, go to the console at &lt;strong&gt;Pusher.com&lt;/strong&gt; website, go to settings and enable sending events from clients directly.&lt;/p&gt;

&lt;p&gt;We can only send events from client sdirectly for Presence or Private channels. Link to the official documentation - &lt;a href="https://pusher.com/docs/client_api_guide/client_events#trigger-events" rel="noopener noreferrer"&gt;https://Pusher.com/docs/client_api_guide/client_events#trigger-events&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pusher : Error : {
  "type":"WebSocketError",
  "error":{
    "type":"PusherError",
    "data":
      {
        "code":null,
        "message":"To send client events, you must enable this feature in the Settings page of your dashboard."
      }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We have built an application which will display all the online members for a particular presence channel and their statuses. If any of the online user updates their status, every user will be notified about the updated status.&lt;/p&gt;

&lt;p&gt;This component or code can be used for developing a social networking section in most of the web apps these days. It is an important use case where the user needs to know about other available participants. For example: an online classroom app can see the other participants and the status can correspond to any question any participant wants to ask the presenter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-app-animated-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-users-status-app-animated-1.gif" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have just used &lt;strong&gt;NodeJS&lt;/strong&gt; and &lt;strong&gt;Vanilla JS&lt;/strong&gt; to implement the above functionality. You can use the Javascript for front end code with any popular framework like &lt;strong&gt;ReactJS&lt;/strong&gt; or &lt;strong&gt;AngularJS&lt;/strong&gt; etc. The backend can also be &lt;strong&gt;Java&lt;/strong&gt; or &lt;strong&gt;Ruby&lt;/strong&gt;. Please refer to the Pusher docs for more information on this.&lt;/p&gt;

&lt;p&gt;This blog post was originally published on Pusher’s blog - &lt;a href="https://blog.pusher.com/update-users-status-realtime-javascript" rel="noopener noreferrer"&gt;https://blog.pusher.com/update-users-status-realtime-javascript&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>realtime</category>
      <category>angular</category>
      <category>javascript</category>
      <category>pusher</category>
    </item>
    <item>
      <title>6 Common Misconceptions about Angular</title>
      <dc:creator>Rahat Khanna</dc:creator>
      <pubDate>Mon, 22 Jan 2018 12:55:39 +0000</pubDate>
      <link>https://dev.to/mappmechanic/6-common-misconceptions-about-angular-4nbc</link>
      <guid>https://dev.to/mappmechanic/6-common-misconceptions-about-angular-4nbc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Angular has become the most popular word among front-end/UI developers since jQuery. Angular is a popular JavaScript based open source front-end development framework maintained by Google and a community of developers/contributors. &lt;/p&gt;

&lt;p&gt;Angular was started as a side project by Miško Hevery, intended for use by web designers, to easily add reusable utility into their projects. He, along with another core contributor, decided to open source this library.&lt;/p&gt;

&lt;p&gt;After a while, when Hevery started working at Google, he convinced his boss, Brad Green, to use Angular in one project. After the success of that project, many of the Google Web apps in production started using Angular as their UI application platform.&lt;/p&gt;

&lt;p&gt;Angular has exponentially grown as an open source project and is being used by a large number of cutting edge websites as well as mobile web applications these days.&lt;/p&gt;

&lt;p&gt;According to the ever growing list at &lt;a href="https://www.madewithangular.com" rel="noopener noreferrer"&gt;https://www.madewithangular.com&lt;/a&gt;, popular organizations like: Microsoft Support, NASDAQ, Sony Pictures, GoPro and Tesla use Angular in their customer facing portals. Angular has also made a huge impact in helping with rapid application development of internal enterprise apps for multiple conglomerates in banking, finance, and retail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this article, we will refer to Angular version 1 as AngularJS, and any version greater than 2 as Angular.&lt;/p&gt;
&lt;h2&gt;
  
  
  Popularity of Angular
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Angular is one of the favourites in the JavaScript developer community, the new Angular core npm module has been downloaded &lt;strong&gt;1,459,312&lt;/strong&gt; times in May 2017 and a whopping &lt;strong&gt;2,634&lt;/strong&gt; other modules are dependent on it. AngularJS and above combined have around &lt;strong&gt;80,000&lt;/strong&gt; stars on Github. The GitHub repository of core Angular project has combined &lt;strong&gt;2,000&lt;/strong&gt; contributors which is one of the biggest project teams for an open source project.&lt;/p&gt;

&lt;p&gt;Angular has become a popular choice because of a large amount of community support, online resources like blogs, articles and video tutorials. Due to the popularity of Angular a lot of new developers planning to start with it, have a lot of misconceptions about Angular.&lt;/p&gt;

&lt;h2&gt;
  
  
  Misconceptions about Angular
&lt;/h2&gt;

&lt;p&gt;In this blog post, I want to cover the 6 most common misconceptions that developers have in mind and I will also cover the actual reality of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Angular is a&lt;/strong&gt; &lt;strong&gt;l&lt;/strong&gt;&lt;strong&gt;ibrary.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web developers who have been creating websites using jQuery like libraries often feel that Angular or AngularJS is just another library like them. This is a big misconception and they should understand that Angular is a complete framework which encompasses the design patterns and best practices to build a modern single page web app. jQuery is a single tool which helps in writing the short syntax for long JavaScript functions.&lt;/p&gt;

&lt;p&gt;On the other hand, Angular is like a toolbox and is equipped with plenty of features including: Component Hierarchy, Templating, Two-way data binding, Dependency Injection, Modules and Responsive support. Angular is a perfect framework candidate which is enough for building a performant web application rendered from any web server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9801dy24pmyerns5alye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9801dy24pmyerns5alye.png" width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Angular is a big monolithic library.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Almost all developers who are working with frameworks other than Angular or even AngularJS developers believe that the new Angular framework is a big monolithic one. Developers have been creating AngularJS apps as big bloated apps with shared scopes and services which are perceived to produce huge monolithic systems which have become tech debts for many organizations.&lt;/p&gt;

&lt;p&gt;Angular now has been divided into multiple modules with a &lt;strong&gt;core&lt;/strong&gt; module being the skeleton and the main module stitching all of them together. The modules have been divided so that any developer can opt-in or out based on his use and circumstances. The optional modules are like: @angular/animations, @angular/forms, @angular/router and @angular/material. Also, the team behind Angular has really put in thought behind the Modules system in this framework which has been developed as NgModules. The definition in the Angular docs is&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NgModules help organise an application into cohesive blocks of functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;NgModules have a few advanced features also like lazy loading and dependency injection at runtime which makes it a powerful tool for making large distributed front end apps with a modular approach. Lazy Loading helps in asynchronously loading the module at runtime whenever it is required by some other module. In order to learn more about this, you can refer the docs page at &lt;a href="https://angular.io/guide/ngmodule" rel="noopener noreferrer"&gt;https://angular.io/guide/ngmodule&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Angular applications are slow and not for performance intensive use cases.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lot of developers think that Angular apps are slower than React or Ember apps and this becomes one of the major misconceptions for why they do not try Angular. A lot of web apps made using this framework suffer from either poor implementation by developers and also some bad design elements in the core framework. &lt;/p&gt;

&lt;p&gt;In the new Angular framework, the team has moved away from the worst dirty checking algorithm to a one-way flow system. They would achieve two-way data binding using a new change detection system which uses a new library called &lt;a href="https://github.com/angular/zone.js/" rel="noopener noreferrer"&gt;zone.js&lt;/a&gt;. These words seem to be buzzing but they are all under the hood, you can use the Angular two-way data binding out of the box when building applications. Angular automatically uses Zones to detect the possible changes to update the view and internally implements some VM to process the implementations.&lt;/p&gt;

&lt;p&gt;Also, the new Angular framework has a special feature of Ahead of Time compilation which improves the performance of the web application. In the older versions of Angular either templates were requested from the server on the fly and even modules were compiled using JIT which slowed down the app response times. AOT Compilation along with change detection and universal server side rendering helps the new Angular framework to match performance with React or VueJS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Angular forces the usage of&lt;/strong&gt; &lt;strong&gt;TypeScript&lt;/strong&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another big misconception which is blocking developers in adopting the new Angular framework is its inclination towards TypeScript. In my opinion, this is it's biggest strength but Angular can even work without TypeScript. We can use ES5 (JavaScript) for developing apps using the new Angular framework. There is also a &lt;a href="https://www.dartlang.org" rel="noopener noreferrer"&gt;Dart&lt;/a&gt; version of Angular which you can use with the help of this &lt;a href="https://webdev.dartlang.org/angular/" rel="noopener noreferrer"&gt;guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Angular has been developed this time using well-thought design patterns which help in building scalable and performant universal web apps. JavaScript is evolving into a more mature language with the introduction of new ES6/ES7 features like: Classes, Arrow Functions, Spread Operators etc. TypeScript is just a superset of JavaScript and adds the capability of strong typing to your JavaScript. It helps in identifying and resolving many type-related bugs during the development stage itself. Although you can create Angular apps without TypeScript, I would strongly suggest using it. A good read on this point is &lt;a href="https://vsavkin.com/writing-angular-2-in-typescript-1fa77c78d8e8" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Angular does not have state management or is not compatible with Flux or Redux.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web Applications are becoming more complex every day and yet developers need to rapidly iterate and release new features without compromising performance. For any complex front end apps, state management is very important. We need to manage multiple types of state like server response data, local UI state, application state and user preferences. AngularJS did not work well with external state management libraries but the new Angular framework has been built in a way that it optionally support these libraries. The main concept of state management libraries like redux is based on unidirectional data flow, but the default 2-way data binding of AngularJS did not fit well with it. Another issue is that in AngularJS, the state should ideally be managed using services but the data binding is done using $scope so it becomes hard and cumbersome to tie these together in the controllers.&lt;/p&gt;

&lt;p&gt;The new Angular framework follows the unidirectional data flow design pattern at its core which makes it easy to be used with popular state management libraries like Flux, Redux, RxJS or ImmutableJS. Even without using these external libraries due to the good change detection strategies you can use state in common services and inject them into your Angular Modules. An amazing reading resource on this topic is available at this link: &lt;a href="https://bertrandg.github.io/angular2-application-state-management-strategy/" rel="noopener noreferrer"&gt;https://bertrandg.github.io/angular2-application-state-management-strategy/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Angular generates a big bundle size and build process is complicated.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;This particular misconception is always reinforced with developers who have tried out the initial beta or RC versions of Angular 2. Initial versions of Angular were generating huge bundle sizes and the build process itself was very complicated. In early versions, a simple HelloWorld app of Angular would come close to &lt;strong&gt;1.3 MBs&lt;/strong&gt; which was preposterous.&lt;/p&gt;

&lt;p&gt;Angular team took its core focus to work on this and from the v4 release onwards a lot of optimisations have been done in this regard. After this release, the HelloWorld app bundle size has been reduced to less than &lt;strong&gt;50KB&lt;/strong&gt; and that is awesome for Angular developers. Angular has introduced the (AOT)Ahead of Time compiler which enables it to compile Angular apps into such small bundle sizes. We can achieve this by using the &lt;strong&gt;--&lt;/strong&gt;&lt;strong&gt;prod&lt;/strong&gt; flag while building using Angular CLI. AOT also has an advanced feature if used with Rollup to enable &lt;a href="https://webpack.js.org/guides/tree-shaking/" rel="noopener noreferrer"&gt;tree shaking&lt;/a&gt; which further reduces the build size. A good read on this topic can be found at this &lt;a href="http://blog.mgechev.com/2016/06/26/tree-shaking-angular2-production-build-rollup-javascript/" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tree Shaking&lt;/strong&gt; is a concept used by Javascript build systems to help in dead code elimination during the build phase which helps in reducing the final bundle size.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have discussed many misconceptions but have only focused on the important ones. Angular framework has many more features which will eliminate your fear of using it and help you in at least trying the new Angular framework for building your web apps. There are features like Decorators, use of native CSS Animations, Reactive Forms modules, Scoped Styling, Dependency Injection and much more which makes Angular a perfect enterprise app development framework. It has a very rich ecosystem and an ever growing community which should be surely considered when making your choice for the front end framework of your next web app. Please tweet me if you have any doubts or questions regarding this on &lt;a href="https://twitter.com/mappmechanic" rel="noopener noreferrer"&gt;@mappmechanic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This blog post was originally published on Pusher’s blog -&lt;a href="https://blog.pusher.com/6-common-misconceptions-angular/" rel="noopener noreferrer"&gt;https://blog.pusher.com/6-common-misconceptions-angular/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>angular2</category>
    </item>
    <item>
      <title>How to build a realtime graph using Javascript &amp; Pusher</title>
      <dc:creator>Rahat Khanna</dc:creator>
      <pubDate>Mon, 22 Jan 2018 12:54:21 +0000</pubDate>
      <link>https://dev.to/mappmechanic/how-to-build-a-realtime-graph-using-javascript--pusher-5578</link>
      <guid>https://dev.to/mappmechanic/how-to-build-a-realtime-graph-using-javascript--pusher-5578</guid>
      <description>&lt;p&gt;The world needs everything uber-fast now. There are plenty of data streams being generated by different systems everyday. Realtime monitoring and analysis has become very important for taking decisions in many industries today. For example: realtime monitoring of website traffic, server performance, weather updates, IOT sensors etc. It is important to analyse and interpret this burst of data, for which interactive Charts and Graphs are an excellent solution.&lt;/p&gt;

&lt;p&gt;In this blog post, we will be building a NodeJS Server to expose APIs to provide historic data for a metric (in this case, weather in London City) and also provide an API to ingest new data points. We will also be building a front end app with a Line Chart to display the temperature changes in London weather in realtime. The application we build will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-realtime-graph-app-javascript.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-realtime-graph-app-javascript.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Signup for Pusher
&lt;/h2&gt;

&lt;p&gt;The first step to start this tutorial is to &lt;a href="https://pusher.com/signup" rel="noopener noreferrer"&gt;Signup at Pusher&lt;/a&gt; or login with your existing credentials if you already have an account. After logging in, you will need to create a new app and select 'Vanilla JS' for the front end along with 'NodeJS' for the backend. You will then be brought to a landing page containing the 'getting started' code for both front end and backend which we will use later on in the tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  NodeJS Server APIs for Monitoring &amp;amp; Analytics System
&lt;/h2&gt;

&lt;p&gt;The most essential APIs for any analytics systems for any metric or entity are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ingestion API - An API to ingest the new data points for any particular entity. In our server for this blog post, we will make an API to ingest new temperature data at a particular time for London city. This API can be called by any global weather system or any IOT sensor.&lt;/li&gt;
&lt;li&gt;Historical Data API - This API will return all the data within a range from this date in time. For our server, we will create a simple API which will return some static historical data with limited data points for London's temperature values for any day.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  NodeJS Express Server Skeleton
&lt;/h3&gt;

&lt;p&gt;We will create a basic Express Server along with instantiating the Pusher library server instance. We will create a new folder for our project and create a new file &lt;strong&gt;server.js&lt;/strong&gt;. Add the following code to this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');

var Pusher = require('pusher');

var pusher = new Pusher({
  appId: '&amp;lt;your-app-id&amp;gt;',
  key: '&amp;lt;your-app-key&amp;gt;',
  secret: '&amp;lt;your-app-secret&amp;gt;',
  cluster: '&amp;lt;your-app-cluster&amp;gt;',
  encrypted: true
});

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

// Error Handler for 404 Pages
app.use(function(req, res, next) {
    var error404 = new Error('Route Not Found');
    error404.status = 404;
    next(error404);
});

module.exports = app;

app.listen(9000, function(){
  console.log('Example app listening on port 9000!')
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;API to Get Historical Temperature Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, we will add some static data regarding London's temperature at certain times during a day and store it in any JavaScript variable. We will also expose a route to return this data whenever someone invokes it using a GET HTTP call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var londonTempData = {
    city: 'London',
    unit: 'celsius',
    dataPoints: [
      {
        time: 1130,
        temperature: 12 
      },
      {
        time: 1200,
        temperature: 13 
      },
      {
        time: 1230,
        temperature: 15 
      },
      {
        time: 1300,
        temperature: 14 
      },
      {
        time: 1330,
        temperature: 15 
      },
      {
        time: 1406,
        temperature: 12 
      },
    ]
  }

app.get('/getTemperature', function(req,res){
  res.send(londonTempData);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;API to Ingest Temperature Data Point&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we will add the code for exposing an API to ingest the temperature at a particular time. We will expose a GET HTTP API with temperature and time as query parameters. We will validate that they are not empty and store them by pushing in the &lt;strong&gt;dataPoints&lt;/strong&gt; array of our static Javascript variable &lt;strong&gt;londonTempData&lt;/strong&gt;. Please add the following code to the &lt;strong&gt;server.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/addTemperature', function(req,res){
  var temp = parseInt(req.query.temperature);
  var time = parseInt(req.query.time);
  if(temp &amp;amp;&amp;amp; time &amp;amp;&amp;amp; !isNaN(temp) &amp;amp;&amp;amp; !isNaN(time)){
    var newDataPoint = {
      temperature: temp,
      time: time
    };
    londonTempData.dataPoints.push(newDataPoint);
    pusher.trigger('london-temp-chart', 'new-temperature', {
      dataPoint: newDataPoint
    });
    res.send({success:true});
  }else{
    res.send({success:false, errorMessage: 'Invalid Query Paramaters, required - temperature &amp;amp; time.'});
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, apart from storing in the data source, we will also trigger an event &lt;strong&gt;'new-temperature'&lt;/strong&gt; on a new channel &lt;strong&gt;'london-temp-chart'&lt;/strong&gt;. For every unique data source or a chart, you can create a new channel.&lt;/p&gt;

&lt;p&gt;The event triggered by our server will be processed by the front end to update the chart/graph in realtime. The event can contain all the important data which the chart needs to display the data point correctly. In our case, we will be sending the temperature at the new time to our front end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Front End App using Vanilla JS &amp;amp; Chart.js
&lt;/h2&gt;

&lt;p&gt;Now, we will build the front end application to display a Line Chart representing the changes in temperature for London City at different times throughout the day. The key approach for displaying realtime graphs is&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We have to make an initial Ajax call to fetch historical data, and render the graph with the existing data.&lt;/li&gt;
&lt;li&gt;We will subscribe to any events for new data points being stored on a particular channel.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Basic HTML Template
&lt;/h3&gt;

&lt;p&gt;We will create a new folder called &lt;strong&gt;public&lt;/strong&gt; in our project root and then create a new file &lt;strong&gt;index.html&lt;/strong&gt; in this folder. This file will contain the basic HTML code to render a simple header and a sub-header with the app name along with few icons. We will also import the &lt;strong&gt;Pusher Javascript&lt;/strong&gt; library from its CDN URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;Realtime Analytics&amp;lt;/title&amp;gt;
        &amp;lt;link rel="stylesheet" href="https://unpkg.com/purecss@0.6.2/build/pure-min.css" integrity="sha384-UQiGfs9ICog+LwheBSRCt1o5cbyKIHbwjWscjemyBMT9YCUMZffs6UqUTd0hObXD" crossorigin="anonymous"&amp;gt;
        &amp;lt;link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway:200"&amp;gt;
        &amp;lt;link rel="stylesheet" href="./style.css"&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;header&amp;gt;
            &amp;lt;div class="logo"&amp;gt;
                &amp;lt;img src="./assets/pusher-logo.png" /&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div id="logout" class="logout"&amp;gt;
               &amp;lt;a href="/logout"&amp;gt;Logout&amp;lt;/a&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/header&amp;gt;
        &amp;lt;section class="subheader"&amp;gt;
            &amp;lt;img class="weather-icon" src="./assets/weather.png" /&amp;gt;
            &amp;lt;h2&amp;gt;Realtime Weather Updates for London !&amp;lt;/h2&amp;gt;
            &amp;lt;img class="weather-icon" src="./assets/london-icon.png" height="70px" /&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;section&amp;gt;
           &amp;lt;div id="loader" class="loader"&amp;gt;
           &amp;lt;/div&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;script src="https://js.pusher.com/4.0/pusher.min.js"&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script type="text/javascript" src="./app.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Charts Library
&lt;/h3&gt;

&lt;p&gt;In Javascript and HTML apps, we have to use either of the two technologies to build graphical components to represent mathematical graphs, SVG or Canvas. There are numerous open source libraries which can help you render different chart types, such as Bar Charts, Pie Charts, Line Charts and Scatter Charts. Here are links to a few of the popular libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highcharts - &lt;a href="http://www.highcharts.com/" rel="noopener noreferrer"&gt;http://www.highcharts.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chart.js - &lt;a href="http://www.chartjs.org/" rel="noopener noreferrer"&gt;http://www.chartjs.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google Charts - &lt;a href="https://developers.google.com/chart/" rel="noopener noreferrer"&gt;https://developers.google.com/chart/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Flot - &lt;a href="http://www.flotcharts.org/" rel="noopener noreferrer"&gt;http://www.flotcharts.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;D3 JS - &lt;a href="http://d3js.org/" rel="noopener noreferrer"&gt;http://d3js.org/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our project, we will choose Chart.js as it has fairly simple API and renders robust charts using Canvas HTML tag. You can choose any charting library but keep in mind that the library should have a means to update the chart without completely re-rendering it. Chart.js provides a method on any instantiated chart to update it.&lt;/p&gt;

&lt;p&gt;Add the following code to your index.html file at appropriate places&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
&amp;lt;section&amp;gt;
   &amp;lt;div id="loader" class="loader"&amp;gt;
    Loading...
   &amp;lt;/div&amp;gt;
   &amp;lt;canvas id="weatherChart"&amp;gt;
   &amp;lt;/canvas&amp;gt;
&amp;lt;/section&amp;gt;
&amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="https://js.pusher.com/4.0/pusher.min.js"&amp;gt;&amp;lt;/script&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding JS File &amp;amp; Instantiating Pusher client side library
&lt;/h3&gt;

&lt;p&gt;Now we will create a new file &lt;strong&gt;app.js&lt;/strong&gt; in our public folder and also add the following code to instantiate the Pusher client side library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Using IIFE for Implementing Module Pattern to keep the Local Space for the JS Variables
(function() {
    // Enable pusher logging - don't include this in production
    Pusher.logToConsole = true;

    var serverUrl = "/",
        members = [],
        pusher = new Pusher('&amp;lt;your-api-key&amp;gt;', {
          encrypted: true
        }),
        channel,weatherChartRef;

    function showEle(elementId){
      document.getElementById(elementId).style.display = 'flex';
    }

    function hideEle(elementId){
      document.getElementById(elementId).style.display = 'none';
    }

    function ajax(url, method, payload, successCallback){
      var xhr = new XMLHttpRequest();
      xhr.open(method, url, true);
      xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
      xhr.onreadystatechange = function () {
        if (xhr.readyState != 4 || xhr.status != 200) return;
        successCallback(xhr.responseText);
      };
      xhr.send(JSON.stringify(payload));
    }

})();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we have also added few utility methods to make an Ajax call and also show or hide elements from the DOM API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Code to fetch Historical Data
&lt;/h3&gt;

&lt;p&gt;Now, we will add the code to fetch the historical temperature data to display the graph with the initial values. We will also instantiate a new Chart object with a specific config to render a Line Chart. You can read more about how to construct these configs at the &lt;a href="http://www.chartjs.org/docs/" rel="noopener noreferrer"&gt;Chart.js documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please add the following code to the app.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   function renderWeatherChart(weatherData) {
      var ctx = document.getElementById("weatherChart").getContext("2d");
      var options = { };
      weatherChartRef = new Chart(ctx, {
        type: "line",
        data: weatherData,
        options: options
      });
   }

   var chartConfig = {
      labels: [],
      datasets: [
         {
            label: "London Weather",
            fill: false,
            lineTension: 0.1,
            backgroundColor: "rgba(75,192,192,0.4)",
            borderColor: "rgba(75,192,192,1)",
            borderCapStyle: 'butt',
            borderDash: [],
            borderDashOffset: 0.0,
            borderJoinStyle: 'miter',
            pointBorderColor: "rgba(75,192,192,1)",
            pointBackgroundColor: "#fff",
            pointBorderWidth: 1,
            pointHoverRadius: 5,
            pointHoverBackgroundColor: "rgba(75,192,192,1)",
            pointHoverBorderColor: "rgba(220,220,220,1)",
            pointHoverBorderWidth: 2,
            pointRadius: 1,
            pointHitRadius: 10,
            data: [],
            spanGaps: false,
         }
      ]
   };

   ajax("/getTemperature", "GET",{}, onFetchTempSuccess);

   function onFetchTempSuccess(response){
      hideEle("loader");
      var respData = JSON.parse(response);
      chartConfig.labels = respData.dataPoints.map(dataPoint =&amp;gt; dataPoint.time);
      chartConfig.datasets[0].data = respData.dataPoints.map(dataPoint =&amp;gt; dataPoint.temperature);
      renderWeatherChart(chartConfig)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we have added a function named &lt;strong&gt;renderWeatherChart&lt;/strong&gt; which will be used to render the chart using latest data which is embedded in the &lt;strong&gt;chartConfig&lt;/strong&gt; variable under the key &lt;strong&gt;datasets&lt;/strong&gt;. If we want to draw multiple line charts on same canvas, we can add more elements to this array.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;data&lt;/strong&gt; key in each of the elements of the array will display the different points on the graph. We will make an ajax request to the &lt;strong&gt;/getTemperature&lt;/strong&gt; api to fetch all the data points and put them into this key. We will call the rendering method to display the graph then. Now we can run the command &lt;code&gt;node server.js&lt;/code&gt; and then go to the browser with the following URL to see the initial chart rendered using the data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:9000/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to style our app properly, please add the following CSS into a new style.css file inside the public folder. Add the following code to that file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body{
    margin:0;
    padding:0;
    overflow: hidden;
    font-family: Raleway;
}

header{
    background: #2b303b;
    height: 50px;
    width:100%;
    display: flex;
    color:#fff;
}

.logo img{
  height: 45px;
}

.subheader{
    display: flex;
    align-items: center;
    margin: 0px;
}

.logout{
    flex:1;
    justify-content: flex-end;
    padding:15px;
    display: none;
}

.logout a{
    color:#fff;
    text-decoration: none;
}

#weatherChart{
    height: 80% !important;
    width: 95% !important;
    margin: 0 auto;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code to Update Graph on new event received
&lt;/h3&gt;

&lt;p&gt;Now we want to subscribe to the unique channel on which our server will be sending update events for this graph. For our project the channel is named &lt;strong&gt;london-temp-chart&lt;/strong&gt; and the event is named &lt;strong&gt;new-temperature&lt;/strong&gt;. Please add the following code to process the event and then update the chart in realtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;channel = pusher.subscribe('london-temp-chart');
channel.bind('new-temperature', function(data) {
    var newTempData = data.dataPoint;
    if(weatherChartRef.data.labels.length &amp;gt; 15){
      weatherChartRef.data.labels.shift();  
      weatherChartRef.data.datasets[0].data.shift();
    }
    weatherChartRef.data.labels.push(newTempData.time);
    weatherChartRef.data.datasets[0].data.push(newTempData.temperature);
    weatherChartRef.update();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to see this code in action, you have to refresh the browser and you will see the initial chart. Now we have to ingest a new data point, for which you would need to call the following API either by using some mock API calling tool or using the following URL with different values in the browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:9000/addTemperature?temperature=17&amp;amp;time=1500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to test your chart update code, you can use the following temporary code in your &lt;strong&gt;app.js&lt;/strong&gt; Javascript file which will make dummy Ajax requests to the above URL after a specific time interval.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* TEMP CODE FOR TESTING */
  var dummyTime = 1500;
  setInterval(function(){
    dummyTime = dummyTime + 10;
    ajax("/addTemperature?temperature="+ getRandomInt(10,20) +"&amp;amp;time="+dummyTime,"GET",{},() =&amp;gt; {});
  }, 1000);

  function getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
  }
/* TEMP CODE ENDS */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Github repo for reference to complete code is &lt;a href="https://github.com/mappmechanic/realtime-analytics" rel="noopener noreferrer"&gt;https://github.com/mappmechanic/realtime-analytics&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Finally our realtime analytics app is ready. We will see the weather temperature chart for London city updating in realtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-realtime-graph-app-javascript.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fblog.pusher.com%2Fwp-content%2Fuploads%2F2017%2F04%2Fbuild-realtime-graph-app-javascript.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use the code from this blog post for any charts library and also to render any type of chart like Bar Chart, Scatter Chart or Pie Chart to update in realtime.&lt;/p&gt;

&lt;p&gt;This code can also be used in multiple Enterprise Apps like Monitoring dashboards, analytics reports, sensor regulatory apps, financial apps etc. The Pusher library helps us to send realtime events to all connected client side apps which can consume the data to update the charts in realtime.&lt;/p&gt;

&lt;p&gt;This blog post was originally published on Pusher’s blog - &lt;a href="https://blog.pusher.com/build-realtime-graph-using-javascript" rel="noopener noreferrer"&gt;https://blog.pusher.com/build-realtime-graph-using-javascript&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>pusher</category>
      <category>realtime</category>
    </item>
  </channel>
</rss>
