The Ghost Themes Developer Hub

Welcome to the Ghost Themes developer hub. You'll find comprehensive guides and documentation to help you start working with Ghost Themes as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    


Accelerated Mobile Pages support for your posts


The amp template is used to render an automatic AMP (Accelerated Mobile Pages) version of your post, which makes things load crazy-fast on mobile devices and puts you in Google's good-books.


To access any post rendered using the amp.hbs template, just add /amp/ to the end of your post URL. The parent post will also have a new canonical link to its AMP equivalent, to make it easily discoverable by machines.


The amp context always uses the amp.hbs template. Ghost will first look for and use an amp.hbs template within your theme files and, if none exists, it will fall back to its own basic default amp template.

The custom amp.hbs template should live within the file structure like here:

├── /assets
|   └── /css
|       ├── screen.css
|   ├── /fonts
|   ├── /images
|   ├── /js
├── default.hbs 
├── index.hbs [required]
└── post.hbs [required]
└── amp.hbs [optional]
└── package.json [required]

If you wanna see, how Ghost accesses the data for an AMP post or - even more important what information you need and what is prohibited - , you will find Ghost's default template in /core/server/apps/amp/lib/views/amp.hbs.


The amp context provides access to the post object which matches the route. As with all contexts, all of the @blog global data is also available.

When outputting the post, you can use a block expression ({{#post}}{{/post}}) to drop into the post scope and access all of the attributes. See a full list of attributes here.

Specific AMP features

AMP consists of three different parts:

  • AMP JS
  • Google AMP Cache

AMP has many restrictions for optimal performance, which is why we can't use regular HTML in our AMP posts:

  • AMP pages can’t include any JavaScript, except under special circumstances. Follow these official AMP HTML docs to create a valid amp.hbs.
  • CSS is prohibited in any other places than the AMP specific <style amp-custom></style> tag inside of the <head> section. See the official AMP CSS docs for best results.
  • AMP doesn't use common HTML, but AMP HMTL. That means, some HTML tags are prohibited, while others need to be transformed. Ghost uses a tool to transform the HTML of the content (e. g. <img> becomes <amp-img>) and strips out disallowed tags, like embed or frame. Check out the full list of prohibited HTML tags here.
  • AMP needs a required mark-up to run.
  • Media needs width and height attributes
  • AMP provides two ways to validate your template. The first one is to add #development=1 to the URL, in our case this would be and check for any validation errors in your console. The second way is to copy your HTML into their online validator, but keep in mind, that this will not work with our handlebars helpers.

If you want more in depth information, check out the official AMP documentation.

Debugging AMP template

When developing your amp.hbs, one of the most important things is to make sure that your code passes AMP validation, because only validated pages will be served from the Google AMP Cache.

You can access development mode by adding #development=1 to the URL, like this: http://localhost:2368/welcome-to-ghost/amp/#development=1. Any validation errors will now be listed in your browser console.

Read more about AMP validation here.

You can also check, if your post gets served from the Google Cache:

For Blogs served on http:

For Blogs served on https:


Because the amp context is using the post data, you can use almost every post helper inside of the {{#post}}{{/post}} block expression:

{{title}}, {{url}}, {{author}}, {{date}}, {{excerpt}}, {{post_class}}, {{tags}}

In addition to those, you can use three more helpers especially for amp:

{{amp_ghost_head}}, {{amp_components}}, {{amp_content}}.

Special case for {{img_url} helper in amp context:

The {{img_url}} helper needs to be wrapped in an <amp-img> tag and must provide a width and height property and works only for post images. {{author.profile_image}} is not supported, in amp context, but the {{img_url}} helper can still be used within the {{#author}}{{/author}} block expression. See the examples below:

  <amp-img src={{img_url feature_image absolute="true"}} width="600" height="400" layout="responsive"></amp-img>
  	<amp-img src={{img_url profile_image absolute="true"}} width="50" height="50"></amp-img>

{{amp_ghost_head}} helper:

Usage: {{amp_ghost_head}}





{{amp_ghost_head}} – belongs just before the </head> tag in amp.hbs, outputs the following:

  • Structured data microformats in JSON/LD - no need to clutter your theme markup!
  • Structured data tags for Facebook Open Graph and Twitter Cards.
  • RSS url paths to make your feeds easily discoverable by external readers.
  • Link to regular post equivalent

This is a simplified version of {{ghost_head}} which prevents any AMP-incompatible/breaking tags from being loaded into your head section.

{{amp_components}} helper:

Usage: {{amp_components}}





{{amp_components}} – belongs just before the </head> tag in amp.hbs, outputs the following, depending on the HTML in your content:

  • if a .gif is detected in the HTML, it outputs the necessary javascript lib for <amp-anim>.
  • if an <iframe> tag is detected in the HTML, it outputs the necessary javascript lib for <amp-iframe>.
  • if an <audio> tag is detected in the HTML, it outputs the necessary javascript lib for <amp-audio>.

{{amp_content}} helper:

Usage: {{amp_content}}





{{amp_content}} is used for transforming post content into valid AMP HTML.

  • <img> will be transformed into <amp-img>
  • .gif images will be transformed into <amp-anim>
  • <iframe> will be transformed into <amp-iframe>
  • <audio> will be transformed into <amp-audio>
  • Removes prohibited HTML tags to validate AMP post.

Note: More transforms coming soon! ✨

Example code

<!DOCTYPE html>
<html >
    {{!-- Document Settings --}}
    <meta charset="utf-8">

    {{!-- Page Meta --}}

    {{!-- Mobile Meta --}}
    <meta name="HandheldFriendly" content="True" />
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">

    {{!-- Brand icon --}}
    <link rel="shortcut icon" href="{{asset "favicon.ico"}}">


    {{!-- Styles'n'Scripts --}}
    <link rel="stylesheet" type="text/css" href=",700,700italic,300italic|Open+Sans:700,600,400" />
    <style amp-custom>
      {{!-- All CSS styles have to go here and are strictly forbidden anywhere else in the template --}}

    {{!-- The AMP boilerplate --}}
    <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
    <script async src=""></script>
		{{!-- amp_components helper renders the necessary script tags for AMP depending on the HTML in the content --}}


<body class="amp-template">
    <header class="main-header">
        <nav class="blog-title">
            <a href="{{@blog.url}}">{{@blog.title}}</a>

    <main class="content" role="main">
        <article class="post">

            <header class="post-header">
                <h1 class="post-title">{{title}}</h1>
                <section class="post-meta">
                    <p class="author">by <a href="{{url}}">{{name}}</a></p>
                    <time class="post-date" datetime="{{date format="YYYY-MM-DD"}}">{{date format="YYYY-MM-DD"}}</time>

            <section class="post-content">



    <footer class="site-footer clearfix">
        <section class="copyright"><a href="{{@blog.url}}">{{@blog.title}}</a> &copy; {{date format="YYYY"}}</section>
        <section class="poweredby">Proudly published with <a href="">Ghost</a></section>


Accelerated Mobile Pages support for your posts