As part of my setup for Ghost, I wanted to have a custom editable home page as well as a listing of recent blog posts. While getting this set running was quite simple to do, there weren't many tutorials around explaining how to do this. The information needed is buried in some API documentation; so I thought I'd share how to do this in an easy and succinct manner.

There are two parts to this solution: adding a custom template for the home page, and adding a custom route telling Ghost to use the custom template for the route /.

Getting started

To build custom themes, it's helpful to have Yarn and Gulp. On Mac OSX this is as simple as a homebrew install:

brew install node yarn
npm install gulp

Full guidelines for installation are available here: https://yarnpkg.com/lang/en/docs/install and https://www.npmjs.com/package/gulp

Custom homepage

The next step is to create a custom homepage as a Ghost page - this is fairly self explanatory. It's important to make note of the page URL in the menu that you assign. I set mine to home. The novelty of this tutorial vs the tutorial on the Ghost website is that this page can be editable as a Ghost page rather than being static HTML that is baked into the template file.

Custom template

Following the guidelines for a custom homepage, you'll be making some edits to the Ghost template. Download the Ghost casper template from your blog (in the design page) and make changes to it as follows:

Add a home.hbs file

We'll make a home.hbs file that combines parts from index.hbs and post.hbs. I started by copying all of index.hbs and adding a few sections from post.hbs. We don't really need all the information from the post page. Here's what my template looks like:

...
<main id="site-main" class="site-main outer">
    <!-- from post.hbs -->
    <div class="inner">
        {{#page}}
        <article class="post-full {{post_class}} no-image">

            <header class="post-full-header">

                <h1 class="post-full-title">{{title}}</h1>

            </header>

            <section class="post-full-content">
                <div class="post-content">
                    {{content}}
                </div>
            </section>

        </article>
        {{/page}}
    </div>
    
    <!-- get the list of posts -->
    {{#get "posts"}}
    <div class="inner posts">
        <div class="post-feed">
            {{#foreach posts}}

                {{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
                {{> "post-card"}}

            {{/foreach}}
        </div>
    </div>
    {{/get}}
</main>
...

You can tweek this to your liking. There's 2 parts I'd like to point out: line 5-21 is copied from post.hbs and displays the post. line 25 is a query to get a list of posts. You can edit this to only show featured posts or posts with certain tags/authors by following this documentation: https://ghost.org/docs/api/v3/handlebars-themes/helpers/get/

Custom routes

Download the current routes.yaml file from your blog. At the time of writing, you can find it on the labs page:

I added a custom route from / to use the home template and load data from the home page. Here's what my routes.yaml file looks like after editing.

routes:
  /:     
    data: page.home
    template: home
    
collections:
  /blog/:
    permalink: /blog/{slug}/
    template: index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

Putting it all together

The next steps were to upload the route, compile and upload the template and add a static link to /blog in the menu.

To compile the template, go to the folder you've been editing the casper theme in and run the following command which will output a compiled version of the theme in the dist/ folder.

yarn zip

That's it!