My experience with Hugo has been pretty good so far. It’s fast and flexible. Ever since I started using Hugo, I’ve been improving my website with small tweaks. In this post, I am going to share some tricks and workarounds I’ve found online while working with Hugo. Besides that, I’ll that links that I’ve found useful.
Post Summary
Hugo’s .Summary
function provides an easy built-in solution for displaying post summaries. Yet, it has some flows. Hugo suggests 3 ways of generating a summary. Manual splitting and front-matter options are cumbersome. So, the summary function seems handy but it doesn’t always do well. It includes lists and headings. It can’t handle code-fences. Luckily, I’ve found a better solution created by Yihui Xie.
Pagination
online but Hugo already has _internal/pagination.html
. These partials are for buttons and links that create the navigation. Also, you need to paginate the Pages in a loop.
You can either use .Paginator
function or .Paginate
function. The first one is the result of the second one, and a shortcut is provided for convenience. .Paginator
is created by Hugo, and supported on homepage and list pages since it’s using the .Pages
function. On the other hand, we can tell which pages we want to gather and paginate by using the .Paginate
function.
Here is the simplest form of pagination:
{{ range (.Paginate .Pages).Pages }}
{{.Title}} //Display post info, link here.
{{ end }}
{{ partial "pagination.html" . }} // Include pagination partial.
You’ll probably use more detail about posts, include links to it, instead of .Title
alone. I use another partial I’ve created.
// Another example with custom $pages
{{ $pages := where $.Site.RegularPages ".Type" "!=" "ordinary" }}
{{ $pages = where $pages ".Section" "not in" (slice "karalama" "projects") }}
{{ range (.Paginate $pages).Pages }}
// Of course, you can sort pages however you like.
{{ range (.Paginate (.Pages.ByParam "episode").Reverse).Pages }}
Related Posts
In Hugo, you really should use the built-in feature for gathering related posts. Because it’s easy and fast. I’m not gonna make this post longer than it should be. I display 2 sections under my posts. One is, related posts generated by Hugo, and the other one is next/previous posts in the same section. I’ll come to the latter later.
To use the related indices, you need to add these lines to your config file, it’s explained in the docs. I don’t add “category” here, because I don’t use “category” taxonomy. Since there is only one indice I use, the weight parameter becomes redundant too. Anyway…
[related]
threshold = 10
includeNewer = true
toLower = true
[[related.indices]]
name = "tags"
weight = 90
Now you need to gather the related posts on a post’s page. So, you’ll probably use this code in the single.html
template.
{{ $related := .Site.RegularPages.RelatedIndices . "tags" | first 3 }}
You may want to filter out ordinary pages like /about /contacts
and use something like this:
{{ $posts := where .Site.RegularPages "Section" "blog"}}
{{ $related := $posts.RelatedIndices . "tags" | first 3 }}
In my case, I use the code below and also added a backup strategy. It’ll display the latest posts if there is no $related
found.
{{ $posts := where .Site.RegularPages "Section" "!=" "" }}
{{ $related := $posts.RelatedIndices . "tags" | first 3 }}
{{ if eq (len $related) 0 }}
{{ $related = $posts.ByDate | first 3 }}
{{ end }}
Easy enough. Now, the second part: next/previous posts. You are probably using category taxonomy but I use sections to categorize my posts. Each post has a parameter named episode
which specifies its order in the section. For example, this is the 14th post in Hugo section.
Here is how I get the previous/next episodes.
{{ $posts := where $.Site.RegularPages ".Section" $.Section }}
{{ $posts := where $posts ".Title" "!=" $.Title }}
{{ $prePosts := where $posts ".Params.episode" "lt" $.Params.episode }}
{{ $prePosts := $prePosts.ByParam "episode" | last 2 }}
{{ $nextPosts := where $posts ".Params.episode" "gt" $.Params.episode }}
{{ $nextPosts := $nextPosts.ByParam "episode" | first 2 }}
After that, all we need to do is loop through them.
{{ range $nextPosts }}
<li><span>#{{ .Params.episode }}</span><a href="{{ .RelPermalink }}">{{.Title}}</a></li>
{{ end }}
Something similar can be done with category and date instead of section and episode.