The AMP Project provides tools and guidelines for webmasters interested in making sites that load quickly and are highly optimized for mobile devices. AMP-compatible sites are not allowed to employ custom JavaScript but predefined AMP components are provided by Google.

The <amp-twitter> component may be used to embed a specific tweet, but there is currently no built-in way to embed the “latest” tweet (or series of tweets) from a specific user.

The pain is amplified for static web sites that cannot rely on a server to dynamically generate markup on the fly. Nevertheless, it is possible for static web sites to dynamically display the latest content from Twitter. Here are three ways to accomplish it.

amp-iframe

The <amp-iframe> component can be used to display content from a page that is not AMP-compatible.

Create a regular HTML page that includes one of the standard widgets from Twitter and embed that page into an AMP-compatible page with <amp-iframe>.

This method has a few limitations. From the documentation:

  • An amp-iframe may not appear close to the top of the document (except for iframes that use placeholder as described below). The iframe must be either 600 px away from the top or not within the first 75% of the viewport when scrolled to the top, whichever is smaller.
  • By default, an amp-iframe is sandboxed (see details).
  • An amp-iframe must only request resources via HTTPS, from a data-URI, or via the srcdoc attribute.
  • An amp-iframe must not be in the same origin as the container unless they do not allow allow-same-origin in the sandbox attribute. See the “Iframe origin policy” doc for further details on allowed origins for iframes.

twamp

I wrote a node module called twamp to solve this problem. twamp was designed to be deployed as an AWS Lambda, but can also be run from the command line. Lambdas are cheap (if not free) to run and once deployed, twamp can be employed in one of two ways.

amp-list

The <amp-list> component can be used to fetch JSON and render markup from mustache templates.

All Twitter API endpoints require authentication as of version 1.1 so there is no official way to fetch a timeline as JSON without authentication.

Theoretically you could configure an API Gateway to invoke a AWS Lambda that makes calls to the Twitter API with your OAuth credentials and responds with the JSON data in real time. The downside is that this involves making two requests, one from the browser to the API Gateway and one from the Lambda to Twitter, for each visitor to your site. Add to this the additional request made by <amp-twitter> elements and you’re looking at some noticeable lag.

An alternative is to deploy an instance of twamp as an AWS Lambda that is configured to dump a user timeline in JSON format to an S3 bucket at regular intervals. If that bucket has static web hosting enabled, viola — a ready-made API endpoint with no rate limit and no authentication required. Put the S3 bucket behind a CDN with CloudFlare or CloudFront so that it can be served over HTTPS (which is an <amp-list> requirement).

In-Place HTML Update

twamp also has the ability to parse and update HTML files in place.

Assuming your static web site is hosted on S3, twamp can be used to keep the markup up to date. From the twamp README:

When an HTML file is processed, elements with the class tweet-X (where X is an integer, ex. tweet-0) are updated to reflect the latest tweet(s). The elements with class tweet-0 are populated with data from the newest tweet. The elements with class tweet-1 are populated with data from the second newest tweet and so on.

  • .tweet-X elements are given a data-tweetid value
  • child elements with class tweet-href have their href attribute set to the tweet url
  • child elements with class tweet-text have their innerHTML set to the tweet text
  • child elements with class tweet-screen_name have their innerHTML set to the screen name that posted the tweet
  • child elements with class tweet-created_at have their innerHTML set to the formatted date/time the tweet was posted

Files written to S3 have the Cache-Control maxage header set to the frequency_minutes option (converted to seconds) so that browsers and CDNs do not keep stale versions.

Modifying HTML files in place is a brute force approach to be sure, but it’s not a string replace hack. HTML parsing/rendering is handled with cheerio, a well established and popular implementation of core jQuery designed specifically for the server. By operating on the built HTML, twamp is effectively independent of whatever process you use to build the site. It works equally well if the site was typed by hand or built with static site generator like Hugo, Jekyll or metalsmith.