Recipes
Below are ready-to-use recipes you can adapt for your custom template.
Query Parameter Styling (v1.3.0+)
Since version 1.3.0, you can use clean query parameter syntax instead of HTML wrappers.
Centered small images

Instead of:
<img src="assets/images/icon.png" alt="Small icon" style="display:block;margin:0 auto" />
Full-width images

Instead of:
<div class="wide-content"><img src="assets/images/hero.jpg" alt="Hero image" /></div>
Responsive embedded media
<iframe src="https://codepen.io/username/embed/xxxxx?style=embed" height="300"></iframe>
Instead of:
<div class="embeded-media-container">
<iframe src="https://codepen.io/username/embed/xxxxx" height="300"></iframe>
</div>
Vimeo videos
<iframe src="https://player.vimeo.com/video/12345?style=vimeo"></iframe>
The ?style=vimeo parameter ensures proper responsive sizing for Vimeo embeds.
Featured post
You can use the postsList Handlebars helper with perPageLimit set to 1. Then provide your wrapper className and style it as needed.
{{postsList
perPageLimit=1
currentPage=1
className="homepage-featured-post"
dateFormat="dd mmmm yyyy"
noTags=true
noExcerpt=true
noDate=true
byTagName="featured"
readMoreButtonLabel="Let's dive in!"
}}
Posts categories
You can use the postsList Handlebars helper with perPageLimit and treat tags as categories. Posts will be divided into sections and listed by tag name.
<div class="homepage-section homepage-section-bg">
<div class="container">
<h1 class="homepage-header">Coding</h1>
{{postsList
perPageLimit=3
currentPage=1
className="post-list-items"
dateFormat="dd mmmm yyyy"
byTagName="coding"
readMoreButtonLabel="⇢"
}}
</div>
</div>
<div class="homepage-section">
<div class="container">
<h1 class="homepage-header">Art and Design</h1>
{{postsList
perPageLimit=3
currentPage=1
className="post-list-items"
dateFormat="dd mmmm yyyy"
byTagName="art"
readMoreButtonLabel="⇢"
}}
</div>
</div>
More examples on GitHub
Simple posts list
You can use the postsList Handlebars helper with most content disabled to create a simple post list for menus.
{{postsList
className="docs-articles-list"
noTags=true
noExcerpt=true
noDate=true
noReadMoreButton=true
byTagName='docs'
}}
This documentation uses this approach to generate left sidebar menus.
Similar posts
You can use the postsList with byTagName, which you should set up the same as the current post tag or tags. This way, you will be able to display a similar posts list. Remember to do this in the layout hbs file, not in Markdown files.
{{postsList
className="docs-articles-list"
byTagName=tags.[0]
}}
Set OG tags
You can do this for pages and also in Markdown files for blog/docs posts.
{{> head
title="Homepage"
description="Harold app default theme"
ogTitle="Harold Homepage"
ogDescription="Harold Description"
ogImage=""
twitterTitle="Harold Homepage"
twitterDescription="Harold Description"
twitterImage=""
}}
---
layout: 'blog-post'
title: 'Harold is alive!'
excerpt: "Excerpt of the featured example post."
coverImage: 'https://picsum.photos/id/82/1500/600'
tags:
- tag7
- featured
publicationDate: '2021-04-18'
ogTitle: 'Harold is alive!'
ogDescription: 'Harold is a static site generator based on Handlebars templating and Markdown'
ogUrl: 'https://my-website.com/blog/doc1.html'
ogImage: 'https://my-website.com/assets/images/ogImage.png'
twitterTitle: 'Harold is alive!'
twitterDescription: 'Harold is a static site generator based on Handlebars templating and Markdown'
twitterUrl: 'https://my-website.com/blog/doc1.html'
twitterImage: 'https://my-website.com/assets/images/ogImage.png'
---
More examples on GitHub
Posts JSON data
By default, you have access to JSON data for all posts. It is useful when you want to do something dynamic with JavaScript, such as "load more" functionality or search. Some ready templates already include a search implementation. Here is an example:
Note: For nested posts, the fileName field includes the relative path from the posts root. For example:
- Root-level post:
"fileName": "example1.html" - Nested post:
"fileName": "category/nested-post.html"
const postsJsonDataPath = '/jsonData/posts.json';
const fetchPostsJsonData = () => {
return fetch(postsJsonDataPath)
.then((response) => response.json())
.then((data) => {
postsJSON = data;
return data;
});
};
fetchPostsJsonData().then((data) => {
searchIndex = lunr(function () {
this.ref('fileName');
this.field('title');
this.field('body');
this.field('excerpt');
this.field('tags');
data.forEach((doc) => {
this.add(
Object.assign(doc, {
tags: doc.tags.join(' '),
body: doc.body.replace(/(<([^>]+)>)/gi, ''),
})
);
}, this);
});
});
More examples on GitHub
Custom directories names
Sometimes you don't want to build a blog, but let's say, documentation. There is a posts directory for Markdown files and a blog-layouts directory for layouts by default. Because URLs are using posts directory name, you will end with /posts/my-documentation-article-1, which isn't optimal. You can change it by using the .haroldrc configuration file. Example:
{
mdFilesDirName: 'docs',
mdFilesLayoutsDirName: 'docs-layouts'
}
Adding robots.txt, manifest.json, etc.
In many cases, there is a need to add some custom files to the root of your website. You can do this using the optional src/statics directory. Example: src/statics/robots.txt will be placed in build/robots.txt next to your index.html file. You can also nest your directories like src/statics/some-dir/some-dir/file.txt. It will land in build/some-dir/some-dir/file.txt.
GitHub Pages hosting
If you want to host Harold's website under your main username (username.github.io), you would need to rename your output directory to supported by GitHub. It is the docs directory. You would need to create a .haroldrc file and put the output directory name there.
{
outputDirName: 'docs',
}
Build your Harold app and push it to the repo. Remember to add the .gitignore file, and exclude node_modules but keep the output directory (docs).
Configure your GitHub Pages to take the source from the docs directory.
Here is the quick walk-through demo on how to do that:
If you want to host Harold's website under the repository subdirectory name (username.github.io/my-blog), you need to add hostDirName and remember to keep your paths in order. You can use the relativePath handlebars helper. The default template (from v0.4.0) is already using it, so it should work as-is.
{
outputDirName: 'docs',
hostDirName: 'my-blog'
}
Check out demo: github.com/juliancwirko/testing-github-pages
Git-based static hosting
With build-capable static hosts such as Cloudflare Pages, Netlify, Vercel, and similar services, deployment is usually simple. Point the service to your Git branch, set the build command, and choose the output directory. The service can run the build scripts for you and publish the generated static files.
Here is an older quick walk-through demo using one of these services:
Other ideas?
I would be thrilled if you could share your ideas. Let me know.
Please read Guides section if you need more detailed docs.