Mobile growth is a driver for many technologies: Responsive design, HTTP/2, HTML5 replacing Flash. Facebook started with an own format for optimized mobile delivery. This is not only beneficial to users: If a page is displayed fast, ads are visible before the user clicks away, as well.

Google followed the approach of a custom format, called Accelerated Mobile Pages (Google AMP). Instead of choosing a completely different container, like XML, proven technologies were used: HTML, JavaScript and JSON notation. By using a JavaScript based runtime to implement functions like delayed loading of non-essential assets and inlining CSS, the initial transmission size of the page can be reduced.

While WordPress got support for generating AMP content by a plugin, other CMS applications seem to be lacking. Especially when using static site generators it can be challenging to generate multiple variants from the same content. I like static site generators for several reasons:

  • Can be served from a low-grade webserver without special requirements
  • Really, really fast page serving
  • Easy to cache / integrate CDN
  • Low attack surface, easy to secure

I used middleman in several projects, so far I am quite happy with it. Thanks to integrated asciidoctor support it was even possible to use a common source for web pages as well as print documents, distributed by other channels.

When facing the desire to provide Google Accelerated Mobile Pages (AMP) using the existing middleman setup along with the existing content I noticed the shortcomings of HTML or asciidoc based page templates. Nevertheless I went ahead and use some customizations (some would call it hacks) to achieve my goal. I prototyped it for and you can see the AMP result on

The implementation uses the latest middleman 4 and the targets plugin to have multiple variants as build targets. To ensure that the AMP links to not point to the non-AMP version by accident a link_prefix and deployment of AMP to a subdirectory is used. Another option would have been to use a subdomain. Of course the AMP version uses a different layout which includes the AMP engine JavaScript and required markup and meta data for the AMP pages.


# Build Targets
config[:targets] = {
  default: {
    build_dir: "build",
    layout: "layout",
    link_prefix: nil,
  amp: {
    build_dir: "build/amp",
    layout: "amp",
    link_prefix: "/amp",

In order to be able to reuse the existing content, some global search-and-replace is applied as part of the template.


<% content = yield %>
content.gsub!("<img", "<amp-img")
content.gsub!("<iframe", "<amp-iframe")
content.gsub!("</img", "</amp-img")
content.gsub!("</iframe", "</amp-iframe")
<%= content %>


It is now obvious why this can be called a hack instead of an engineered solution. A better approach would be possible if the source data for the pages is provided in a more strcutured format like JSON or YAML. Both are supported by middleman and are a good choice for content that follows a well defined structure. (A good example is the trainings catalogue on