In the last section of this tutorial, we learned how to add a search option to our custom Ghost theme.
You might have noticed that as we add more features to our theme, the code starts to grow and becomes difficult to manage. How can we solve this issue?
Mainly, we have two ways to solve this issue. Either we have to build reusable components like an ad block, subscription forum, widgets, etc or split large code files into smaller, manageable components. In Ghost, we do this with the help of partials.
Before we start
This tutorial is divided into a few sections. If you missed any previous posts, please read them first.
- Part 1 - Create a simple Ghost theme.
- Part 2 - Add navigation bar and custom templates.
- Part 3 - Add search to the theme.
- Part 4 - Integrating comments and partials.
If you are facing any issues or errors, you can download the source code from GitHub and use it as a reference. Code downloaded from previous posts will be different.
What are partials?
Partials are nothing but reusable components of our theme. In Ghost themes, partials are located in a folder named partials. If you have not created this folder yet, create it in the root directory of the theme now.
Benefits of using partials
- It helps to build reusable components.
- Keeps the code maintainable and clean.
“Clean code always looks like it was written by someone who cares.”
― Robert C. Martin
Can you recall how we created the navigation bar in the previous post? We created a folder named partials
and place the code of navbar there. It helped to make the navbar an independent reusable component.
Create partials
To create partials in our theme, first, make sure that the partials
folder exists in the root directory of the theme. In this post, we'll create two partials. One to integrate Disqus comments and the other to serve as the template to display posts.
Example 1: Integrate Disqus comments
To integrate Disqus comments, create a file named comment.hbs
in the partials
folder.
The content of comment.hbs
should be:
<div class="card-body">
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {
this.page.url = "{{url absolute="true"}}";
this.page.identifier = "ghost-{{comment_id}}"
};
(function() {
var d = document, s = d.createElement('script');
s.src = 'https://EXAMPLE.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<div>
Replace https://EXAMPLE.disqus.com
with https://your_disqus_shortname.disqus.com
.
Now, in the post.hbs
, add this line where you want to display the comment section.
{{> "comment"}}
Here's my post.hbs
. Note that the code is inserted in between the {{content}}
and {{/post}}
tags.
{{!< default}}
{{!-- Everything inside the #post tags pulls data from the post --}}
{{#post}}
<main id="site-main" class="container">
<div class="inner">
<article class="{{post_class}} {{#unless feature_image}}no-image{{/unless}}">
{{!-- Code removed for brevity--}}
<div class="post-content">
{{!-- Display the post content --}}
{{content}}
</div>
{{> "comment"}}
</section>
</article>
</div>
</main>
{{/post}}
Save the files, restart the ghost instance by running ghost restart
and scroll to the bottom of any post. You'll see the Disqus comment section loaded there.

Example 2: Post template using partials
In the first section of this tutorial, we created a file named index.hbs
. It holds the template to display posts and pagination. Writing multiple components in a single file is not a good approach. The code will become difficult to manage and test as we add more components and widgets.
Let's solve this problem by converting the template to display posts as a separate reusable component using partials.
First, create a new file named posts.hbs
under partials
. This file will act as the template to display the list of available posts. Then, move all the code related to displaying posts from index.hbs
to posts.hbs
.
Remember to call posts.hbs
in index.hbs
using {{> "posts"}}
.
index.hbs
{{!< default}}
{{!-- The tag above means: insert everything in this file
into the {body} of the default.hbs template --}}
{{!-- The main content area --}}
<main id="site-main">
<div class="container">
<div>
{{> "posts"}}
</div>
</div>
</main>
posts.hbs
{{#foreach posts}}
<article class="{{post_class}} card" style="margin-bottom: 20px;">
<div class="card-body">
{{#if primary_tag}}
<span class="badge badge-success">{{primary_tag.name}}</span>
{{/if}}
<a style="text-decoration-line: none;" href="{{url}}">
<h2>{{title}}</h2>
</a>
<p>{{excerpt words="33"}}</p>
<div>
<span class="reading-time">{{reading_time}}</span>
<span> - Published: {{date published_at timeago="true"}}</span>
</div>
</div>{{!--/.post-card-content--}}
</article>
{{/foreach}}
Things look much cleaner now. Isn't it?
This is how you can use partials to make reusable code in Ghost.