About · Om7Sense · Ghost Theme ·
Sven Read
Sven Read
Teaser Image

A Designers Guide to Ghost Theming

"A beautifully designed platform
dedicated to one thing: Publishing."

Lately a lot of people ask me on how to start out with making a theme for Ghost. And yes, after building three themes myself I have some experience in doing this stuff. Check them out if you want to know more about how I approach theme design:

  • Marisa, a photographic Ghost theme.
  • Chiara, a minimal and elegant blogging theme. #1 Ghost theme on Creative Market, atm. This blog runs this theme.
  • Readium, an open source Medium-like theme.

And your timing couldn't be better. Ghost is still young, the community small but growing fast. Actually, designing themes for Ghost isn't difficult in comparison to other blogging systems. But it isn't that easy either, if you don't know a few things about how Ghost works. I decided to make this small and comprehensive guide on the important things you need to know to start out. So that you can dive into making your own theme.

Warning: Code ahead

You will need to get your hands dirty with some coding. So stop right now if you don't have at least basic knowledge of HTML and CSS. Instead, you should go and learn how to code.

Ghost Basics

Screenshot of present Ghost.org landing page

Ghost is a modern and still quite young open source publishing platform (version 0.4.2 so far). It is built to be completely customizable, fast, lean and features a slick design out of the box.

Ghost is built on Node.js, so you need to make sure Node (at least version 0.10.*) is installed on your computer, so you can run it locally. Follow these detailed instructions and set up a local Ghost instance, so we can start out on building your theme.

After everything is installed and you have given your Ghost instance a first run in the browser, lets have a closer look at what we have.

Your Ghost's main folder consists of three subfolders (content, core and node_modules) and a few files. The only folder relevant to us is the "content" folder. Inside you find the folder "themes", holding another single folder, called "casper". Duplicate the "casper" folder und rename it to whatever you want to name your theme.

Theme files

A Ghost theme out of the box has one folder, called "assets". It holds all your fonts, custom javascript, css or images. Whatever external file you need during theming, drop it in "assets". Now lets get serious and look at what files we have got in our main theme directory:

  • default.hbs - The HTML frame for every template in your theme.
  • index.hbs - The HTML template for your index page.
  • post.hbs - The HTML template for a single blog post.
  • page.hbs - The HTML template for a static page.
  • tag.hbs - The HTML template that lists articles after being searched via tags.
  • package.json - The config file that should contain your theme infos, like name, version, etc.
  • readme.md - Mainly for instructions or stuff. Whatever you need.

These are the essential files every theme should have, in order to function properly running Ghost 0.4.2.

Customising your theme

Ghost uses Handlebars as a templating engine. That's good for us, because Handlebars has a quite readable code syntax. This makes it easy to understand what happens in our templates. Take {{{body}}} for example. It is a handlebars tag you will encounter in your default.hbs, which is the frame for every other .hbs which starts with the {{!< default}} in the first line.

Here is a quick list of what handlebar tags we will most likely need:

  • {{@blog.title}} - Outputs the name you entered as blog title in your Ghost admin interface (usually, if you run Ghost locally -
  • {{@blog.logo}} - Gives you the URL of the logo you entered in your Ghost admin interface.
  • {{@blog.cover}} - Gives you the URL of the background image you choose in your Ghost admin interface.
  • {{@blog.description}} - Gives you the description text you entered.


Lets assume on your main page you most likely will need a list of your most recent articles. For this we need to dig a little deeper into what Ghost and Handlebars can do for us. We will use the Handlebar loop {{#foreach posts}} repeating the code between this opening tag and his closing tag {{/foreach}} as long as there are posts in your database. Everything between these two tags gets repeated for every blog post you wrote. Again, you have some Handlebar tags you will want to use inside this loop:

  • {{{title}}} - Gives you the blog post title (unsuprisingly!)
  • {{{url}}} - Gives you the blog post url (again, unsuprisingly!)
  • {{date format='YYYY-MM-DD'}} - Gives you the date of your blog post.
  • {{tags prefix="on "}} - Gives you the blog post tags.
  • {{content words="100"}} - Outputs the first 100 words of your blog posts content (including the HTML).
  • {{excerpt characters="250"}} - Same as content, but strips the HTML and counts characters instead of words. I mostly prefer this option over the {{content}}.

Combine with these tags as you see fit with the necessary HTML to make your design happen. Here is an example from one of my themes:

{{#foreach posts}}

    <article class="{{post_class}}" itemscope itemtype="http://schema.org/BlogPosting" role="article">
        <div class="article-item">
            <header class="post-header">
                <h2 class="post-title" itemprop="name"><a href="{{url}}" itemprop="url">{{{title}}}</a></h2>
                <span class="post-meta"><time datetime="{{date format='YYYY-MM-DD'}}">{{date format="DD MMM YYYY"}} {{tags prefix="on "}}</span>
            <section class="post-excerpt" itemprop="description">
                <p>{{excerpt characters="250"}}…</p>



This is the page that displays your glorious articles. It roughly needs a opening {{#post}} tag, as well as a closing one {{/post}}. In between these two you need a {{{title}}} and a {{content}} tag. Everything else is optional. Here is the obligatory list of useful handlebar tags (additionally to {{date}} and {{tags}}, which are the same as above):

  • {{author.name}} - Gives you the authors name
  • {{author.bio}} - Gives you the authors bio (as added in your Ghost admin interface)
  • {{author.website}} - Gives you the authors website URL.

And many, many more. Check out Ghosts theme helper page for more Handlebar presets and more complexe use cases. You can build nearly everything with these, so you should go make yourself comfortable with them. But for now, this simple example should help you get started.

In case you wondered: Some of the Handlebar tags have three {{{ and some just two. The difference is, that if you use three {{{, Handlebars gives you the unfiltered content of this variable (if there is HTML inside, it will give you the raw HTML, too). If you use two {{, the code gets stripped out and you get the only the text.


Basically everything the same as for post.hbs. Only, this template gets used if you have static pages. If you want your static pages to differ from your blog posts (which you should want to), this is the template you need to edit. Mostly, this page is similar to the post.hbs, but often has subtle differences. But this is entirely up to you.

A neat little feature introduced in 0.4.2: You can now make different page templates for different use cases, simply by giving it a different name. If you rename it to page-about.hbs it will only apply to static pages with the URL /about/. Helpful to make a few custom templates for special use cases.


Basically the same as the index.hbs, just this template displays your blog posts filtered by a specific tag. You can use all the same stuff as in your index.hbs.

The End

This is the end of my little Ghost theming crash course. You should now be able to handle the basic elements of a Ghost theme. Be sure to check out the documentation on the Ghost theming guide for more in depth material. Or visit their forum for community help.

Now, go ahead and build something awesome.

Additional resources

A list of interesting material on the topic of Ghost theming. Some may be too advanced for you now, so don't get yourself to tangled up in this stuff. This is just that you see what is possible if you want to go that way.