Utility Helpers
Utility helpers are used to perform minor, optional tasks. Use this reference list to discover what each handlebars helper can do when building a custom Ghost theme.
Available utility helpers
- asset
- ghost_head/foot
- body_class
- post_class
- reading_time
- pagination
- prev/next_post
- plural
- translate
- encode
- log
- @labs
asset
Usage: {{asset "asset-path"}}
Description
The {{asset}}
helper exists to take the pain out of asset management. Firstly, it ensures that the relative path to an asset is always correct, regardless of how Ghost is installed. So if Ghost is installed in a subdirectory, the paths to the files are still correct, without having to use absolute URLs.
Secondly, it allows assets to be cached. All assets are served with a ?v=#######
query string which currently changes when Ghost is restarted and ensures that assets can be cache busted when necessary.
Thirdly, it provides stability for theme developers so that as Ghost's asset handling and management evolves and matures, theme developers should not need to make further adjustments to their themes as long as they are using the asset helper.
Finally, it imposes a little bit of structure on themes by requiring an assets
folder, meaning that Ghost knows where the assets are, and theme installing, switching live reloading will be easier in future.
Examples
To use the {{asset}}
helper to output the path for an asset, simply provide it with the path for the asset you want to load, relative to the assets
folder.
For example:
// Styles
<link rel="stylesheet" type="text/css" href="
ghost_head/foot
Usage: {{ghost_head}}
and {{ghost_foot}}
Description
These helpers output vital system information at the top and bottom of the document, and provide hooks to inject additional scripts and styles.
ghost_head
{{ghost_head}}
– belongs just before the </head>
tag in default.hbs
, outputs the following:
- Meta description
- Structured data Shema.org microformats in JSON/LD - no need to clutter your theme markup!
- Structured data tags for Facebook Open Graph and Twitter Cards.
- RSS url paths to make your feeds easily discoverable by external readers.
- Scripts to enable the Ghost API (if enabled in labs)
- Canonical link to equivalent
amp
post (if enabled in apps) - Anything added in the
Code Injection
section globally, or at a page-level
ghost_foot
{{ghost_foot}}
– belongs just before the </body>
tag in default.hbs
, outputs the following:
- Anything added in the
Code Injection
section globally, or at a page-level
body_class
Usage: {{body_class}}
Description
{{body_class}}
– outputs dynamic CSS classes intended for the <body>
tag in your default.hbs
or other layout file, and is useful for targeting specific pages (or contexts) with styles.
The {{body_class}}
helper outputs different classes on different pages, depending on what context the page belongs to. For example the home page will get the class .home-template
, but a single post page would get .post-template
.
Ghost provides a series of both static and dynamic body_class
classes:
Static classes
home-template
– The class applied when the template is used for the home pagepost-template
– The class applied to all postspage-template
– The class applied to all pagestag-template
– The class applied to all tag index pagesauthor-template
– The class applied to all author pagesprivate-template
– The class applied to all page types when password protected access is activated
Dynamic classes
page-{slug}
– A class ofpage-
plus the page slug added to all pagestag-{slug}
– A class oftag-
plus the tag page slug added to all tag index pagesauthor-{slug}
– A class ofauthor-
plus the author page slug added to all author pages
Examples
<html>
<head>...</head>
<body class="
post_class
Usage: {{post_class}}
Description
{{post_class}}
outputs classes intended for your post container, useful for targeting posts with styles.
The classes are as follows:
post
- All posts automatically get apost
class.featured
- All posts marked as featured get thefeatured
class.page
- Any static page gets thepage
class.tag-:slug
- For each tag associated with the post, the post get a tag in the formattag-:slug
.
For example:
A post which is not featured or a page, but has the tags photo
and panoramic
would get post tag-photo tag-panoramic
as post classes.
A featured post with a tag of photo
would get post tag-photo featured
.
A featured page with a tag of photo
and panoramic
would get post tag-photo tag-panoramic featured page
.
Setting a post as featured or as a page can be done from the post settings menu.
Example Code
<article class="
reading_time
Usage: {{reading_time}}
Description
{{reading_time}}
renders the estimated reading time for a post.
The helper counts the words in the post and calculates an average reading time of 275 words per minute. For the first image present, 12s is added, for the second 11s is added, for the third 10, and so on. From the tenth image onwards every image adds 3s.
By default the helper will render a text like this:
x min read
for estimated reading time longer than one minute1 min read
for estimated reading time shorter than or equal to one minute
You can override the default text.
Example Code
pagination
Usage: {{pagination}}
Description
{{pagination}}
is a template driven helper which outputs HTML for 'newer posts' and 'older posts' links if they are available and also says which page you are on.
You can override the HTML output by the pagination helper by placing a file called pagination.hbs
inside of content/themes/your-theme/partials
. Details of the default template are below.
The data used to output the {{pagination}}
helper is generated based on the post list that is being output (index, tag posts, author posts etc) and always exists at the top level of the data structure.
Pagination Attributes
- page - the current page number
- prev - the previous page number
- next - the next page number
- pages - the number of pages available
- total - the number of posts available
- limit - the number of posts per page
Default Template
The default template output by Ghost is shown below. You can override this by placing a file called pagination.hbs
in the partials directory of your theme.
<nav class="pagination" role="navigation">
Unique helpers within this context
{{page_url}}
- acceptsprev
,next
and$number
to link to a particular page{{page}}
- outputs the current page number{{pages}}
- outputs the total number of pages
prev_post & next_post
Usage: {{#prev_post}}{{title}}{{/prev_post}}
- {{#next_post}}{{title}}{{/next_post}}
Description
When in the scope of a post, you can call the next or previous post helper, which performs a query against the API to fetch the next or previous post in accordance with the chronological order of the site.
Inside of the opening and closing tags of the {{#next_post}}{{/next_post}}
or {{#prev_post}}{{/prev-post}}
helper, the normal helpers for outputting posts will work, but will output the details of the post that was fetched from the API, rather than the original post.
You can also scope where to pull the previous and next posts from using the in
parameter
plural
Usage: {{plural value empty="" singular="" plural=""}}
Description
{{plural}}
is a formatting helper for outputting strings which change depending on whether a number is singular or plural.
The most common use case for the plural helper is outputting information about how many posts there are in total in a collection. For example, themes have access to pagination.total
on the homepage, a tag page or an author page. You can override the default text.
Examples
%
is parsed by Ghost and will be replaced by the number of posts. This is a specific behaviour for the helper.
translate
Usage: {{t}}
Description
{{t}}
is a helper to output text in your site language.
Ghost's front-end and themes are fully translatable by enabling a publication language in the setting in Ghost admin, and using the translate helper to wrap around any plain text in your theme.
Making a theme translatable
Follow these steps to make your theme fully translatable:
1. Create a locales
folder and add language files
Create a folder called locales
. If using a theme that is already translatable, this may exist already.
Inside the locales
folder, add target language files for each translatable language used on your site. For example locales/en.json
for English and locales/es.json
for Spanish. A valid language code must be used.
2. Translate included sentences
Translate the sentences used in your theme inside your new language files.
For example, in locales/en.json
:
{
"Back": "Back",
"Newer Posts": "Newer Posts",
"Older Posts": "Older Posts",
"Page {page} of {pages}": "Page {page} of {pages}",
"Subscribe": "Subscribe",
"Subscribe to {blogtitle}": "Subscribe to {blogtitle}",
"Subscribed!": "Subscribed!",
"with the email address": "with the email address",
"Your email address": "Your email address",
"You've successfully subscribed to": "You've successfully subscribed to",
"A collection of posts": "A collection of posts",
"A collection of 1 post": "A collection of 1 post",
"A collection of % posts": "A collection of % posts",
"Get the latest posts delivered right to your inbox": "Get the latest posts delivered right to your inbox",
"Latest Posts": "Latest Posts",
"<a href='{url}'>More posts</a> by {name}": "<a href='{url}'>More posts</a> by {name}",
"No posts": "No posts",
" (Page %)": " (Page %)",
"Read More": "Read More",
"Read <a href='{url}'>more posts</a> by this author": "Read <a href='{url}'>more posts</a> by this author",
"See all % posts": "See all % posts",
"Share this": "Share this",
"Stay up to date! Get all the latest & greatest posts delivered straight to your inbox": "Stay up to date! Get all the latest & greatest posts delivered straight to your inbox",
"This post was a collaboration between": "This post was a collaboration between",
"youremail@example.com": "youremail@example.com",
"1 post": "1 post",
"% posts": "% posts",
"1 min read": "1 min read",
"% min read": "% min read"
}
And edited to translate into Spanish for locales/es.json
:
{
"Back": "Volver",
"Newer Posts": "Artículos Siguientes",
"Older Posts": "Artículos Anteriores",
"Page {page} of {pages}": "Página {page} de {pages}",
"Subscribe": "Suscríbete",
"Subscribe to {blogtitle}": "Suscríbete a {blogtitle}",
"Subscribed!": "¡Suscrito!",
"with the email address": "con el correo electrónico",
"Your email address": "Tu correo electrónico",
"You've successfully subscribed to": "Te has suscrito con éxito a",
"A collection of posts": "Una colección de artículos",
"A collection of 1 post": "Una colección de 1 artículo",
"A collection of % posts": "Una colección de % artículos",
"Get the latest posts delivered right to your inbox": "Recibe los últimos artículos directamente en tu buzón",
"Latest Posts": "Últimos Artículos",
"<a href='{url}'>More posts</a> by {name}": "<a href='{url}'>Más artículos</a> de {name}",
"No posts": "No hay artículos",
" (Page %)": " (Página %)",
"Read More": "Lee Más",
"Read <a href='{url}'>more posts</a> by this author": "Lee <a href='{url}'>más artículos</a> de este autor",
"See all % posts": "Ver todos los % artículos",
"Share this": "Comparte",
"Stay up to date! Get all the latest & greatest posts delivered straight to your inbox": "¡Mantente al día! Recibe todos los últimos y mejores artículos directamente en tu buzón",
"This post was a collaboration between": "Este artículo fue una colaboración entre",
"youremail@example.com": "tucorreo@ejemplo.com",
"1 post": "1 artículo",
"% posts": "% artículos",
"1 min read": "1 min de lectura",
"% min read": "% min de lectura",
"< 1 min read": "< 1 min de lectura"
}
It is possible to use any translation key on the left, but readable English is advised in order to take advantage of the fallback option inside the {{t}}
translation helper when no translation is available.
Dates, with month names, are automatically translated. You don't need to include them in the translation files.
Use HTML entities instead of characters, for example <
instead of <
.
3. Enable blog language
Verify that the .json
translation file for your active theme is in place and then activate the language in the General settings of Ghost admin. Enter the correct language code into your settings menu and hit save.
4. Ensure templates exist
To ensure that your theme is fully translatable, two core templates must exist in your theme. Check the following templates exist:
pagination.hbs - exists in content/themes/mytheme/partials
, copy the template
navigation.hbs - exists in content/themes/mytheme/partials
, copy the template
5. Use the translation helper
Any plain text in your theme must be wrapped in the {{t}}
translation helper, with {{t
to the left of the text and }}
to the right.
Look for any plain text in all of your theme's .hbs
template files and ensure the translation helper is present.
6. Declare language in HTML
It's advisable to add the HTML lang attribute to the "<html>
" tag at the start of the theme's default.hbs template, using Ghost's {{@site.lang}} helper: <html lang="{{@site.lang}}">
. {{@site.lang}}
will automatically be replaced on the site with the corresponding language locale tag set in Ghost admin.
7. Reactivate the theme
To make the new changes effective, run restart ghost
.
Optional features
The translation helper can interact with many other handlebars expressions in order to implement more advanced translations within your theme.
Here are some of the most commonly used advanced translation features:
Placeholders
Placeholders are dynamic values that are replaced on runtime, and can be implemented using single braces. This is useful for translations if you need to insert dynamic data attributes to your translations.
For example, here is a placeholder in the theme translation file:
"Proudly published with {ghostlink}": "Publicado con {ghostlink}",
Which is defined in the theme template default.hbs
using:
{{{t "Proudly published with {ghostlink}" ghostlink="<a href="https://ghost.org">Ghost</a>"}}}
Placeholders with data attributes can also be used, for example:
{{t "Subscribe to {blogtitle}" blogtitle=@blog.title}}
Subexpressions
The concept of subexpressions allows you to invoke multiple helpers in one expression.
For example, a (t)
subexpression (instead of normal {{t}}
helper) can be used as a parameter inside another helper such as {{tags}}
.
This can be used to translate the prefix or suffix attribute of the {{tags}}
or {{authors}}
helper.
Plural helper
{{plural}}
is a formatting helper for outputting strings which change depending on whether a number is singular or plural.
This can be used in translations to output information such as number of posts:
"No posts": "No hay artículos",
"1 post": "1 artículo",
"% posts": "% artículos",
In the theme template author.hbs
, several (t) subexpressions instead of normal {{t}}
helpers can be used as parameters inside
{{plural ../pagination.total empty=(t "No posts") singular=(t "1 post") plural=(t "% posts")}}
Reading time helper
The reading time helper can be used in translations to provide a reading time for your posts in the desired language.
For example, in es.json
:
"1 min read": "1 min de lectura", "% min read": "% min de lectura", And in theme template post.hbs
And in the theme template post.hbs
:
Pagination
The {{meta_title}}
helper accepts a page parameter that can be used in conjunction with translations. By using the follow it's possible to translate the word "Page" shown in the title of paginated pages:
<title>
encode
Usage: {{encode value}}
Description
{{encode}}
is a simple output helper which will encode a given string so that it can be used in a URL.
The most obvious example of where this is useful is shown in Casper's post.hbs
, for outputting a twitter share link:
<a class="icon-twitter" href="https://twitter.com/share?text=
Without using the {{encode}}
helper on the post's title, the spaces and other punctuation in the title will not be handled correctly.
log
Usage: {{log value}}
Description
When running Ghost in development mode, you can use the {{log}}
helper to output debug messages to the server console. In particular you can get handlebars to output the details of objects or the current context
For example, to output the full 'context' that handlebars currently has access to:
{{log this}}
Or, to log each post in the loop:
If you're developing a theme and running an install using Ghost-CLI, you must use NODE_ENV=development ghost run
to make debug output visible in the console.
@labs
The @labs
variable provides access to global data properties, which are available anywhere in your theme.
For each feature listed with a checkbox in the settings/labs/
section of a site, the @labs
global will provide a boolean flag which tells the theme developer whether or not the feature is enabled.
As of Ghost 1.0.0, there are two features which can be detected:
{{@labs.publicAPI}}
– true if the Public API feature is enabled (enabled by default){{@labs.subscribers}}
– true if the Subscribers feature is enabled (disabled by default)
Examples
Test if subscribers is enabled before outputting HTML elements to surround a subscribe form, or before adding a subscribe button.
It is also possible to test if the publicAPI is enabled before using the get helper:
Note: when these features are moved out of beta in future, there will be a point at which these properties are deprecated. Therefore it is very important to keep your theme up-to-date.
concat
Usage: {{concat "a" "b" "c"}}
Description
The {{concat}}
helper is designed to concatenate and link multiple things together.
The {{concat}}
helper will take all of the items passed to it, treat them as strings, and concatenate them together without any spaces. There can be an unlimited amount of items passed to the helper.
Strings, variables and other helpers can be passed into the {{concat}}
helper.
Simple examples
{{concat}}
is designed for strings. If an object is passed it will output [object Object]
in true JavaScript™️ fashion. To make it error proof, if {{concat}}
is passed an empty variable, the output will be an empty string.
The separator attribute
By default, strings are concatenated together with nothing in between them. The separator=""
attribute inserts the value provided between each string.
Separator example
link_class
Usage: {{link_class for="/about/"}}
Description
The {{link_class}}
helper adds dynamic classes depending on the currently viewed page. If the page slug (e.g. /about/
) matches the value given to the for
attribute the helper will output a nav-current
class. A for
value must be provided.
Simple example
<li class="nav
activeClass
By default the active class outputted by {{link_class}}
will be nav-current
, this is consistent with our navigation helper. However it can be overwritten with the activeClass
attribute:
<li class="nav
activeClass
can also be given false
value (activeClass=false
), which will output an empty string. Effectively turning off the behaviour.
class
Optionally {{link_class}}
can have additional active classes. Using the class
attribute will add whatever value has been provided when the link is the active URL, nav-current
(the default active class value) will be added last:
<li class="nav
Parent URLs
Not only can {{link_class}}
add active classes to current URLs, but it can also apply classes to parent URLs. If a user navigates to /tags/toast/
then {{link_class}}
can provide an active class to /tags/
as well as /tags/toast/
.
Example
<li class="nav