The quick guide to getting started with Ghost

By Ezequiel Bruni Posted Aug. 31, 2015 Reading time: 7 minutes

You’ve probably heard of Ghost, the new-ish blogging platform that’s taken the blogging world by storm; it’s simple, it’s sleek, it’s sexy; it’s got that live-preview thing. What’s not to like?

I’m moving to Ghost, like many web designers, from a WordPress background. But before I actually managed to wrap my head around WordPress’ template functions, I had tried dozens, possibly hundreds, of CMS options. Some of the more memorable include ExpressionEngine, Textpattern, the ill-fated FrogCMS, an old, old script called CuteNews, and many more.

For a long time WordPress gave me everything I needed: powerful template functions; an endless supply of plugins; just seeing what I could do.

But WordPress has been a heck of a lot more than a blogging engine for some time now. It’s moving steadily toward the realm of the framework in some ways. A publishing framework, if you will.

I’ve reached the point where I want software that blogs, and that’s it. I want to write my posts in Markdown, type in some keywords, add an image or two, and hit publish, then forget about the whole thing.


Enter Ghost

Turns out I’m not alone in my desire for a dead-simple blogging platform. The creators behind Ghost have gone to great lengths to strip out all of the cruft we’ve added to the blogging process, and build a simple, speedy publishing platform that will get the job done. It’s a whole different beast.

It operates on the philosophy that a CMS for blogging should do one thing, and do it well. You won’t see any magazines launched on this platform without a lot of customization. It’s a blog, and turning it into anything else would sort of defeat its purpose.

Then, there’s the fact that it’s built on new technologies. Ghost is built on Node.js, which executes JavaScript code on the server rather than in the browser. It is loved by the same people who love PaaS hosting, and all of these new systems that people like me are struggling to understand. In a sense, it’s been future-proofed from the get-go. It’s part of the first generation of a new breed of CMS.

Mind you, from the blogger’s perspective, it’s just a simple interface for blogging. From the end user’s perspective, nothing’s really changed except maybe the default blog theme looks a bit “flat”. But under the hood, we’re seeing something totally new, and that’s a good thing.


Installing Ghost (the easy way)

Installing Ghost the easy way.

Typically, you’d have to install a component or two separately to get Ghost installed and running on a local machine. You’d have to install Node.js, and then you’d have to go in and start installing some extra Node packages manually from the command line.

That’s right, the typical setup for Ghost requires using the command line. For people more used to WordPress’ “five-minute setup” process with MySQL databases and a graphical installer, this may be uncomfortable.

It could be a pain in the neck if you’re not used to using the command line on a Mac or Linux machine.

Luckily, the kind people over at Bitnami made graphical installers for Windows, Mac, and Linux.

Here are all of the steps you’ll need to follow:

  1. Download the appropriate installer for your OS here: https://bitnami.com/stack/ghost/installer
  2. When you run the installer, provide the following information: where you want it installed, what login info you want to use for the blog, and what IP address you want to use for testing. (I recommend
  3. Run the thing, and start playing. It comes with a cool control panel, and a start menu entry.

Since the installer provides you with all of the components you’ll need, such as Node.js and a mini-server, the file directory is not exactly straightforward.

You’ll need to open up whatever folder you installed Ghost in, and then navigate to apps/ghost/htdocs/. That’s the actual Ghost installation.

The themes are located in apps/ghost/htdocs/content/themes/.


Making a theme for Ghost

Ghost themes are fairly easy to make, as long as you know HTML and CSS. Programming knowledge is helpful, but not strictly necessary. Ghost’s templating system is simple, and even rather intuitive, if you’ve built themes for WordP… ahem, other CMSs before.

I know, I know. The comparison to WordPress is old. But that one bit of software has dominated the market for years now — much like Photoshop has for images — the comparisons are inevitable. In this case, they’re even useful.

People who have built WordPress themes will find some of the file structure and templating language to be familiar, though much simpler. WordPress’ PHP functions give you a lot of flexibility; but they also complicate the theme coding process.

Ghost’s templating system (built with Handlebars), is semantic, powerful, and a lot more readable than the raw PHP functions that we’re used to working with. Personally, I just find it a lot easier to use.

On the other hand, it is meant purely for building blogs. You won’t be building a hybrid news site/social network/forum with this thing. Simpler, but limited. That’s the trade-off inherent in the entire platform.

Creating a basic theme for Ghost.


Setting up your theme

Now, if you’ve watched the video (you really should), you’ll know the very basics. You’ll have your Ghost installation in development mode, and you’ll have a very, very limited theme to work with.

To recap, technically you only need three files to make a Ghost theme:

index.hbs (This template will list your posts)
post.hbs (This will display a single post)
package.json (This contains theme information)

However, there are other basic templates that you probably want to include. You can, of course, create custom templates for pages, posts, authors, tags, and more. We’ll get to all of that over time.

For now, I want to focus on only the basics: theme structure, extending template files, and where to put all of the HTML. This means adding some extra files and folders to our Ghost theme up there. Let’s have a look at the revised structure:

partials/ (Just examples, here. Not required.)

default.hbs will act as the basis of your theme. Your <html>, <head>, and <body> tags will go here. Every other template will be rendered ‘inside’ of this one. Now, you don’t have to do it this way; but it is standard practice, and comes highly recommended by the Ghost devs themselves.

page.hbs is exactly what you think it is, the template for static pages. The assets folder is fairly self-explanatory.

The partials/ folder is where you would keep bits and pieces of code that you use more than once, on various templates. For example, navigation.hbs might include your site name/logo and primary navigation. loop.hbs might output a list of posts with some generic HTML and styling. This could be used in a number of places on the site.


Mixing Handlebars and HTML

So let’s show you exactly how simple the templating can be. First, we’ll set up our default.hbs file:

<!DOCTYPE html>
    <meta charset="utf-8" />

    {{! Here we see the functions for page titles and descriptions. }}
    <meta name="description" content="{{meta_description}}" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    {{! Anything in the assets/ folder can be easily linked to, like so: }}
    <link rel="stylesheet" type="text/css" href="{{asset "css/style.css"}}" />

    {{! This function here outputs meta keywords, some styling information, stuff like that. }}
<body class="{{body_class}}">
    <div class="wrap">
      {{! Any .hbs file in the partials folder can be called in like this. }}
      {{> header}}

      {{! This is where the content of all the sub-templates will be output. }}

      {{! Like ghost_head, this outputs scripts, data, that sort of thing. Currently adds a link to jQuery by default. }}

Now let’s create the navigation.hbs template, because that’s going to be on every page:

<header id="page-header">
    {{! This should be fairly self-explanatory. }}
            {{! This function calls in the navigation links, which can be managed in the Ghost admin panel. Note that the template *must* be called "navigation.hbs" for this to work. }}
            {{#foreach navigation}}
                <li class="nav-{{slug}}{{#if current}} nav-current{{/if}}" role="presentation"><a href="{{url absolute="true"}}">{{label}}</a></li>

Now we create the loop to display excerpts of the posts. To be honest, I ripped this one (almost) straight from the default theme, because the markup is perfect for what I have in mind. Put all of this in partials/loop.hbs:

{{! Each post excerpt will be displayed with this same markup. }}
{{#foreach posts}}
    <article class="excerpt {{post_class}}">
        <h2 class="post-title"><a href="{{url}}">{{{title}}}</a></h2>
            {{! The actual excerpt. Not the variable that allows you to call in exactly as many words as you want. }}
            <p>{{excerpt words="26"}} <a class="read-more" href="{{url}}">&raquo;</a></p>
            {{! This is the post's meta information. }}
            {{tags prefix=" on "}}
            <time class="post-date" datetime="{{date format='YYYY-MM-DD'}}">{{date format="DD MMMM YYYY"}}</time>

{{! Links to the next and previous pages of links. You can define how many links are on each page in the admin panel. }}

Now we’re going to tie it all together with the index.hbs template, which will also act as the home page, unless you specify otherwise. The code for this, seeing how we’ve divided and organized most of the HTML elsewhere, is very simple:

{{!< default}}
{{! That isn't a comment up there. It tells Ghost that everything on this page must be rendered inside the default.hbs template.}}

<section class="posts">
    {{! This next function can be used to call in anything in the partials/ folder. In this case, we're calling up everything we just put into "loop.hbs". }}
    {{> loop}}



And that’s it. Told you it was simple!

If you have trouble, check out Ghost’s default theme, and the documentation. Play with the HTML, play with the template system, and start styling your theme.

Next time, we’ll dig a little deeper. In the meantime, have fun!


Featured image uses Ghost image via Shutterstock.