Creating a Custom Ghost Theme

Once you have Ghost set up, you will probably want to start messing around with different themes. Ghost comes with the Casper theme by default, and this basic theme acts as a good starting point for customisation.

Other free Ghost themes can be found at their marketplace.

This tutorial will follow the creation of my custom theme, Boo, from start to finish.

Theme Structure

Ghost already has some good documentation on the file structure of themes here, so you should read their overview carefully before moving on.

Basic Theme File Structure (from Ghost documentation):

├── /assets
|   └── /css
|       ├── screen.css
|   ├── /fonts
|   ├── /images
|   ├── /js
├── default.hbs
├── index.hbs [required]
└── post.hbs [required]
└── package.json [will be required from 0.6]

Planning the Changes

For my theme, Boo (did anyone catch the Super Mario reference yet?), I want to accomplish the following things:

  1. Centre-position a large logo above the blog name on the main page
  2. Play with the fonts
  3. Change the colour of post title hyperlinks on the main page and hyperlinks within posts
  4. Play with different background patterns
  5. Add a favicon
  6. Add links to my GitHub, personal website, and Twitter, and a short bio, at the bottom of the page
  7. Add a 'share on ...' button for Reddit
  8. Add Disqus comments to the blog
  9. Add syntax highlighting and change the colour scheme of code snippets
  10. (Maybe) mess with the navigation

Updating the Blog After Making Changes

To actually update what is displayed to the users in the browser, you will have to restart Ghost after each change to the theme files.

Restart Ghost with:

sudo service ghost restart  

Current Theme

For reference and comparison, here's the main page (index.html) of the blog using the default Casper theme:


Naming, Version, Author, etc. in package.json

Before I begin editing, I will change the name and version attributes in the package.json file, and add additional fields:

  "name": "Boo",
  "version": "0.1.0",
  "author": {   "name" : "Joe Gibson",
                "email" : "[email protected]",
                "url" : ""
  "description": "Boo - A clean and simple Ghost blog theme",
  "keywords": "boo, ghost, casper, blog, theme, gibsjose",
  "homepage": "",
  "license": "MIT"

More info on the package.json and the possible tags can be found here.

Centre a Bigger Logo on the Main Page

As silly as it sounds, this is the main reason I wanted to modify the theme in the first place, beyond simply enjoying it as an educational exercise.

I will begin by editing the index.hbs file, by inserting the image code right above the lines:

{{! Insert the image code right here...}}
<h1 class="page-title">{{@blog.title}}</h1>  
<h2 class="page-description">{{@blog.description}}</h2>  

I'm using the @blog.logo handle so I can easily change the logo everywhere by just changing the logo on the Ghost general settings page.

To insert the logo, I added the following snippet:

{{! Large logo centred above the title}}
{{#if @blog.logo}}
    <a class="blog-logo-large" href="{{@blog.url}}"><img src={{@blog.logo}}" alt="{{@blog.title}}" /></a>

Note that I used class="blog-logo-large", instead of blog-logo.

This means I will have to create a new entry in the assets/css/screen.css file:

/* Large logo centred above blog title */
.blog-logo-large {
    display: block;
    background: none !important; /* Makes sure there is never a background */
    border: none !important; /* Makes sure there is never a border */

.blog-logo-large img {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    display: block;
    margin-left: auto;
    margin-right: auto;
    height: 180px;
    padding: 1px 0 5px 0;
    width: auto;

The key attributes here are under .blog-logo-large img:

  • margin-left: auto; - These set the left and right margins to be equal, centring the image
  • margin-right: auto;
  • height: 180px; - This sets the height of the logo and thus the size

To maintain the responsiveness when changing screen size, I also added classes under the following entries:

@media only screen and (max-width: 900px) {

    .blog-logo-large img {
        padding: 16px 0;



@media only screen and (max-width: 500px) {

    .blog-logo-large {
        padding: 20px;

    .blog-logo-large img {
        height: 100px;


Additionally, I removed the small logo on the left of the main page, and increased its size on the post pages, by simply removing the following lines in the main-nav class of the index.hbs header:

{{#if @blog.logo}}
    <a class="blog-logo" ...

and modifying the height attribute of the .blog-logo img class:

height: 64px;  

The end result:

Boo Main

Using Different Fonts

The Casper theme uses the Google Fonts API, which is a great way to use custom fonts on your site without any hassle, although it does add to the load time of the page significantly more than using local fonts.

You can browse Google Fonts with their interactive font search, and preview the fonts with any text you want.

For my page, I'm going to use the following fonts:

Using the Google Fonts page, you can browse through the fonts and just click Add to Collection for each font you would like. Then click on Use on the bottom right corner, and you can select each of the font weights you want, as well as additional character sets (i.e. latin-ext, cyrillic, etc.).

After selecting which fonts you want, Google automatically generates an html snippet to copy to the head in default.hbs:

<link href=',700|Righteous|EB+Garamond&subset=latin,latin-ext,cyrillic' rel='stylesheet' type='text/css'>  

I put this right below the {{! Styles'n'Scripts }} comment in default.hbs.

Next, to actually use the fonts, I will edit the assets/css/screen.css stylesheet. To specify the font, I use the font-family attribute, and the font-weight attribute to specify (surprise) the font weight.

First I will change the font for post body and headings:

In body:

font-family: 'EB Garamond', serif;  
font-weight: 400;  

In h1, h2, h3, h4, h5, h6:

font-family: 'Raleway', sans-serif;  
font-weight: 700;  

Hyperlink Colours

Changing the hyperlink colours is easy as well. I just changed the links to a blue colour when hovered. In assets/css/screen.css:

a {  
    color: #4A4A4A;
    transition: color 0.3s ease;

a:hover {  
    color: #3b7dff;


My goal for the background/colours is to change the colour of the main-header when there is no cover in the ghost settings, change the title font colour to yellow, and change the colour of the description to light grey.

In assets/css/screen.css:

.no-cover.main-header {
    min-height: 160px;
    max-height: 40vh;
    background: #404040; /* Dark grey */

.no-cover .page-title {
    color: rgba(255, 255, 56, 1); /* Yellow */

.no-cover .page-description {
    color: rgba(140, 140, 140, 1); /* Light grey */

I also changed the colour of the logo to match the darker background, but that is just changing the image and uploading it again via the Ghost settings panel.

If you have a cover defined in the Ghost settings, none of these changes will matter, and you will instead be editing the normal .page-title color attribute, instead of the .no-cover .page-title attribute.

This logo is also displayed in the top left corner of every page, but this presents an issue: The main page has a dark background but the post pages are white, and my logo happens to be yellow.

I tried adding a drop-shadow, adding a background to the image, and a few other things, but I ultimately decided to create two new images in a new folder under assets: assets/img/post-logo.png and assets/img/post-logo-hover. Then I used a bit of JavaScript to display they darker logo by default and then switch to the yellow logo on hover for an extra bit of pizzaz.

In post.hbs:

{{#if @blog.logo}}
    <a class="blog-logo" href="{{@blog.url}}">
        <img src="{{asset "img/post-logo.png"}}" onmouseover="this.src='{{asset "img/post-logo-hover.png"}}'" onmouseout="this.src='{{asset "img/post-logo.png"}}'" alt="{{@blog.title}}" />

Notice that I used the {{asset "path/to/image"}} built-in helper, rather than a link directly to the file. This makes the theme easier to reuse and modify later, although this method of using an image that is not governed under the @blog-... helper will be an issue if someone wants to use this theme out of the box and doesn't have the knowledge or ability to put their own post page icons in the assets/img/ folder.

At this point, my blog main page looks like this:


Pretty nice!

Adding a favicon

By default, a Ghost blog will use the standard Ghost favicon. To use your own, you just need to add it to the assets folder, and use the built-in {{asset}} helper.

In defaults.hbs, change:

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


<link rel="shortcut icon" href="{{asset "/favicon.ico"}}">  

Note the addition of the leading /.

Then simply place your favicon under assets/favicon.ico.

Adding Links and a Bio to the Footer

The footer that appears under each post is found in, you guessed it: post.hbs. Most of the information it displays is from variables defined by using your Ghost dashboard, by clicking on Users and then your username.

However, I still want to add a link to my GitHub and Twitter, and also change some of the hyperlinks from my blog to my personal website.

Adding links to GitHub and Twitter is easy... just use <a href=...>.

But what if I want to have the fancy icons? Well, you can either use something like FontAwesome, or roll your own icon font with Icomoon. I chose the latter, and added the following files generated by Icomoon to the assets/fonts folder:

  • boo-icons.eot
  • boo-icons.svg
  • boo-icons.ttf
  • boo-icons.woff

Then, I added to the assets/css/screen.css file under the font section:

/* Boo */
@font-face {
    font-family: "boo-icons";
    src:url("../fonts/boo-icons.eot?v=1#iefix") format("embedded-opentype"),
        url("../fonts/boo-icons.woff?v=1") format("woff"),
        url("../fonts/boo-icons.ttf?v=1") format("truetype"),
        url("../fonts/boo-icons.svg?v=1#icons") format("svg");
    font-weight: normal;
    font-style: normal;

/* Apply these base styles to all icons */
[class^="icon-"]:before, [class*=" icon-"]:before {
    font-family: "boo-icons", "Open Sans", sans-serif;
    speak: none;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    text-decoration: none !important;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

.boo-icon-github:before {
    content: "\e600";

.boo-icon-twitter:before {
    content: "\e601";

.boo-icon-reddit:before {
    content: "\e602";

and the following further down under the .post-footer attributes to change the colours when hovering:

.post-footer .share .boo-icon-reddit:hover {
    color: #FF4500;

.post-footer .author .boo-icon-github:hover {
    color: #6CC644;

.post-footer .author .boo-icon-twitter:hover {
    color: #55acee;

To choose the colours, I used BrandColors, which gives you the hex value for the colour set of almost any brand.

NOTE: I was unable to get the font icons to work properly as of right now, so I am just using the text for GitHub and Twitter, but I will edit this as soon as I get it working.

Adding Disqus Comments

Ghost has a great tutorial on this here, and there's really not anything else that I would add to that, other than that if you have downloaded my Boo theme then you will have to modify post.hbs and default.hbs to use your own Disqus username.

Also, I added a slim vertical bar between the date and comment items on the loop, by adding the following to assets/css/screen.css:

.post-comment-count {
    display: inline-block;
    margin-left: 8px;
    padding-left: 12px;
    border-left: #d5dbde 1px solid;
    font-size: 1.3rem;
    white-space: nowrap;

and then using the new class in partials/loop.hbs:

{{! Adding comment counts }}
<a class="post-comment-count" href="{{url}}#disqus_thread">Comments</a>  

Syntax Highlighting and Code Snippet Colours

Another blog post has a nice tutorial on how to add syntax highlighting using prism.js.

Getting prism.js to work is super simple. Just head over to PrismJs's Download Page and configure the JavaScript and CSS files and download them. You will have downloaded prism.js and prism.css. Now simply place them in the assets/js/ and assets/css/ folders, respectively.

Then edit default.hbs:

Add the following line under {{! Styles'n'Scripts }}:

<link rel="stylesheet" type="text/css" href="{{asset "css/prism.css"}}" />  

and the following line just above {{! The main JavaScript file for Boo }}:

<script type="text/javascript" src="{{asset "js/prism.js"}}"></script>  

Other Changes

Over the course of editing the theme, I made a number of small stylistic changes, such as changing colours of buttons, adding small animations, making external links open in new tabs instead of in the same page, etc. By now, you should be able to make any stylistic changes you want for your own theme.

Oh, and the code to open external links in new tabs is:

<script type="text/javascript">  
    $(document).ready(function() {
        $( 'a[href^="http://"]' ).attr( 'target','_blank' );
        $( 'a[href^="https://"]' ).attr( 'target','_blank' );

You can put this code in the code injection section on the Ghost admin panel.