Tips and tricks for building a theme in Hugo

So I am learning how to build a theme in hugo and wanted to document the things I found that were not obvious to me.

  1. To add a list of categories with counts of articles in each category use this snippet I found in the hugo-icarus theme.
{{ range $name, $items := .Site.Taxonomies.categories }}
<li><a href="{{ $.Site.BaseURL }}categories/{{ $name | urlize | lower }}">{{ $name }} &nbsp;<span>({{ len $items }})</span></a></li>
{{ end }}

2. To add custom global variables.

in your config.toml or theme.toml[params]
myvariable = "testing 123"

mysubvariable = "more tests"
in your theme file.{{ .Site.Params.myvariable }}
{{ .Site.Params.general.mysubvariable }}
Don't forget to restart hugo if you make changes to the .toml files. If you don't these variables you added will not show up.

3. To show a list of tags.

{{ range $name, $taxonomy := .Site.Taxonomies.tags }}
<a href="/tags/{{ $name | urlize }}">{{ $name }}</a>
{{ end }}

4. To show the most recent three posts with dates in format 9 hours ago, 3 days ago etc. Install timeago javascript plugin. In hugo insert this in your theme.

{{ range first 3 .Site.Pages }}
<h5><a href="{{ .Permalink }}">{{ .Title }}</a></h5>
<time class="timeago" datetime='{{ .Date.Format "2006-01-02T15:04:05-07:00" }}'>{{ .Date }}</time>
{{ end }}

5. To show a list of posts for a specific tag. In this case I have a tag named featured.

{{ range .Site.Taxonomies.tags.featured }}
<h5><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a></h5>
<time class="timeago" datetime='{{ .Page.Date.Format "2006-01-02T15:04:05-07:00" }}'>{{ .Page.Date }}</time>
{{ end }}

6. If you have an article and you want to change the breakpoint of the summary text for an article you can add a more comment where you want the summary to end.


7. You can combine first and after to make a more complicated query. I am showing 3 featured posts after skipping the first one. I am also showing a featured_image that was in the content markdown in the front matter. This is the top area with the title and other parameters in your markdown post.

{{ range after 1 (first 3 .Site.Taxonomies.tags.featured) }}
{{ with .Page.Params.featured_image }}<img src="{{ . }}">{{ end }}
<h5><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a></h5>
{{ end }}

8. If you are inside of a loop you need to add $ to the beginning of .Params to access the value.

{{ with .Params.some_variable }}{{ with $.Params.some_other_variable }}{{ . }}{{ end }}{{ . }}{{ end }}

9. To tell if some value doesn’t exist. (There is probably a less convoluted way to handle this.)

{{ if (not (isset .Params "some_variable")) }}do something{{ end }}

10. This command is useful for debugging. It shows a lot of useful information related to your hugo theme.

{{ printf "%#v" $.Site }}

11. Pagination

/partials/pagination.html{{ $baseurl := .Site.BaseURL }}
{{ $pag := .Paginator }}
{{ if gt $pag.TotalPages 1 }}
<nav class="center">
<div class="pagination">
<div class="row">
{{ if $pag.HasPrev }}
<a class="prev page-numbers" href="{{ $baseurl }}{{ $pag.Prev.URL }}"><span class="glyphicon glyphicon-chevron-left"></span></a>
{{ end }}
<div class="pagination__page-numbers">{{ range $pag.Pagers }}{{ if eq . $pag }}<span class='page-numbers current'>{{ .PageNumber }}</span>{{ else }}<a class='page-numbers' href='{{ $baseurl }}{{ .URL }}'>{{ .PageNumber }}</a>{{ end }}{{ end }}</div>
{{ if $pag.HasNext }}
<a class="next page-numbers" href="{{ $baseurl }}{{ $pag.Next.URL }}"><span class="glyphicon glyphicon-chevron-right"></span></a>
{{ end }}
{{ end }}
in your index.html or wherever you wish to paginate. This is pulling only those items in the post subdirectory. in config.toml for your site place paginate=5 or to any amount of posts you want per page.{{ $pag := .Paginate (where .Data.Pages "Type" "post")}}
{{ range $pag.Pages}}
{{ partial "some_content" . }}
{{ end }}
{{ partial "pagination" . }}

12. Show 3 related links to a story based on similar tags. Found the solution here.

{{ $page_link := .Permalink }}
{{ $categories := .Params.categories }}
{{ range $page := .Site.Pages }}
{{ $has_common_categories := intersect $categories .Params.categories | len | lt 0 }}
{{ if and $has_common_categories (ne $page_link $page.Permalink) (lt ($.Scratch.Get "$c") 3)}}
{{ $.Scratch.Add "$c" 1 }}
<h4><a href="{{ $page.Permalink }}">{{ $page.Title }}</a></h4>
<h5>{{ $page.Description }}</h5>
{{ end }}
{{ end }}

13. To show multiple authors in your blog with special attributes. This code was borrowed from the casper theme in hugo. You will need to add a data/authors directory in the root of your theme. Inside this directory put a file title it the same as the author’s name you want to use (very important to be exactly the same way you capitalize your author’s name in your front matter). So if your name was “John Doe”, the data file would be “John Doe.toml”. In the data file you can put the info you want about each author.

in your /data/authors/John Doe.tomlname = "John Doe"
bio = "The most generic man in the world"
location = "Normal, Il"
website = ""
thumbnail = "/images/john.jpg"
<!-- Start of post author -->
{{ if not .Params.noauthor }}
{{$author := index .Site.Data.authors (or}}
{{$authorname := or $ }}
{{$authorbio := or $ }}
{{$authorlocation := or $author.location .Site.Params.author_location }}
{{$authorwebsite := or $ .Site.Params.author_website }}
{{$authorthumbnail := or $author.thumbnail .Site.Params.author_thumbnail }}
<div class="post-author">
<h6>Written By</h6>
<img src="{{ $authorthumbnail }}" alt="{{ $authorname }} image" width="90" height="90">
{{if $authorbio}}
<span class="post-author__text">{{$authorbio}}</span>
<span class="post-author__text">Read <a href="{{.Site.BaseURL}}">more posts</a> by this author.</span>
<!-- End of post author -->

14. For certain pages you may want to use a different template like a contact form or an about page. In your _default/single.html at the very top of the file.

{{ if .Params.page_template }}
{{ partial .Params.page_template . }}
{{ else }}
<!-- regular single page template code -->
{{ end }}

Then in partials/page/ create your new template file. As an example contact.html. Finally call this file in a regular content file called contact.html

in your front matter of your contact.html add a new parameter for your custom template.___page_template: 'page/contact'

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store