Building a realtime feed Using Node.js and AMP

Something we can’t deny about Accelerated Mobile Pages (AMP) is that they are fast.

On mobile devices, web pages can take several seconds to load. However, AMPs are web pages designed to load near instantaneously due to the limited set of allowed functionality they provide and a distribution system built around caching.

AMP also uses custom elements called AMP components to implement features with complex interactions such as video players or embeddable content.

In this tutorial, we’re going to implement a realtime feed in AMP using two of these components:

  • amp-live-list, which provides a way to display and update content live so you can easily implement a live blog.
  • amp-youtube, which displays YouTube video.

In the backend, we’ll use a Node.js/Express web server with EJS as the template engine.

This is how the final application will look:

The amp-live-list component will regularly poll the server for updated content. When a new item is added, a button will be shown, which when clicked, will update the page to show the latest videos (with a simple pagination).

You can find the entire source code of the application on this GitHub repository. Also, you need to take into account that realtime features on AMP pages are limited and you can do a lot more using Pusher in your website or app.

Setting up the project

Let’s start by creating a package.json file for our project:

Or if you want to accept all the defaults:

Next, install body-parser, ejs, express, and moment as dependencies:

The project will have the following structure:

  • The view directory contains the EJS template for the main page of the app.
  • In the root directory, we can find the package.json file, as well as the file for the Express server (server.js).

Once you have created the necessary files and directory, you’ll be ready to start coding.

Building the Express server

The web server is a standard Express app with an array to hold the information of the videos we’re going to show.

We will have two endpoints:

  • /, with an optional page query parameter, which will render the template with the list of videos (paginated).
  • /new, which will register a new video.

In the server.js file, let’s start by requiring the modules we’re going to use

Next, define the array for the videos and a constant for the number of posts that will be shown on a page

Now let’s configure the Express server to use EJS as the view engine and the JSON parsing

This is the definition of the route that will present the videos

As you can see, we are implementing simple pagination, calculating the page count, and the start and end elements of the post array that will be shown based on the optional pagequery parameter.

Then, in the last lines, the index template is rendered, passing an object with the properties we’ll need.

This is the definition of the route to registering a new video

We create a new object with an ID based on the length of the array of posts, the ID of the video to show (req.body.videoID), and a timestamp in Unix and ISO 8601 format (for example, 2017-06-09T08:02:17-05:00). Then we add this object at the beginning of the array with unshift and return a success response.

Finally, let’s start the server with

Building the live blog template

An AMP HTML page will act as the content of the template. A good starting point is the boilerplate code you can find on the Create Your First AMP Page official tutorial.

For our app, we’ll use a modified version of that code. Open the file views/index.ejs and copy the following code

For this example, we’re not going to need the JSON metadata from It’s optional but required to make your content eligible to appear in the Google News carousel.
However, we need to keep the canonical link reference, as it is required for the page to be valid. This link must point to itself (the AMP version of the page), so it’s just changed to

Refer to this page to know more about both options.

AMP allows the use of custom fonts with some restrictions. This page uses the Roboto font:

All AMP components used must be imported in the header. The following are the scripts for the YouTube and live list components we’re going to use

In addition to the boilerplate style, we’re going to use some custom CSS styles. Since AMP can’t reference external stylesheets, all styles must live in the head of the document with some restrictions, so let’s add our custom CSS inside a <style amp-custom> tag in the head of the document:

Now, in the body section, let’s add the page header:

And the amp-live-list component

The id attribute identifies the amp-live-list component since multiple live lists are allowed on a single page.
The data-poll-interval attribute specifies how frequently the component will poll new data (in milliseconds). The minimum interval is fifteen seconds.
The data-max-items-per-page specifies the maximum number of items displayed on the page.
If we’re not on the first page, we’re going to add the disable attribute so the component stops polling for new data. (Since new posts will be added to the first page due to how the pagination mechanism works, there’s no need to poll the server if the user isn’t on that page.)

In this example, the amp-live-list component contains three elements as direct children.

The first element is a button with the event on="tap:[ID_OF_THE_LIVE_LIST_COMPONENT].update" to load the latest changes from the server. This button is required and it will appear when new changes are discovered. These changes won’t be shown to the users until they click the button

The second element is <div items>, the list of items to show. These items are required to have a unique id and a data-sort-time attribute (a timestamp used for sorting entries. Higher timestamps will be inserted before older entries)

Finally, the third element is <div pagination></div> element. It’s our responsibility to insert within this element any markup needed for pagination (which in this case is only shown if there’s more than one page)

And we’re done. You can find out more about how the amp-live-list component works

Testing the application

Execute the web server with

If you go to http://localhost:3000, you’ll see a blank page:

It’s recommended you use Chrome because you can validate an AMP page just by adding #development=1 to the URL, for example, http://localhost:3000/?page=1#development=1 and view the result of the validation in the Chrome DevTools console:

To register videos, you can use a tool like Postman to hit the http://localhost:3000/new endpoint with a JSON payload like the following

Or curl

After a few seconds (fifteen at most), the button to load the new videos should be visible:

In addition, if you look at the network tab of the console, you’ll see that a request to the server is made every fifteen seconds:


You’ve now learned how to implement a realtime feed with pagination on AMP using the amp-live-list component. We have covered insertions, but updates and deletions are also supported by this component.

If you have any questions or corrections, or with other suggestions, please let us know.
We’ll try to solve it at the earliest possible time.
Also please share this post on social media, use the share icons just below the post.
Don’t forget to subscribe to our blog.
Thank you for reading.

☞ Swift iOS Image Uploads Using A Node Backend

☞ Start Building Web Apps And Services With Node.js + Express

☞  Node.js for beginners, 10 developed projects, 100% practical


  1. Owing for the heads up! We will up grade this report. It seems to be which include the occasions are just upon the 3rd Sunday of the thirty day period for the duration of September.


Please enter your comment!
Please enter your name here