Featured image of post Enhancing Hugo Theme Stack: Displaying Tags on Homepage

Enhancing Hugo Theme Stack: Displaying Tags on Homepage

Learn how to customize the Hugo theme Stack to display tags on the homepage for each article, along with configuring global and local tag display settings.


In this article, I am sharing how I have updated the theme hugo-theme-stack on my blog powered by goHugo, to display tags on the homepage for each article. How to add configuration to control the display of these tags, globally for the website and locally for each article.


❯  Prerequisites

I consider that you have already a website Hugo up and running, and a theme that you have the right to update (forked from one of the various themes that you can find here). If this is not the case, I recommend you to have a look at this article before continuing your reading.

Also, note that I give here the explanations concerning how to update my theme based on the theme Stack by Jimmy Cai. You may have to adapt some parts of the procedure I am going to explain in this article if you choose a different theme.


❯  Dive deeper on what I want to accomplish here

Actually, on Hugo websites, there is a notion of taxonomy, with two taxonomies available by default (“Categories” and “Tags”), and the possibility to create other ones. In the frontmatter of the articles, we can define a list of tags and a list of categories. For example, in this article:

1
2
3
4
5
6
+++
...
categories = ["Tech"]
tags = ["Hugo", "Hugo Themes", "Website Development", "Web Design", "Frontend Development", "GoHugo", "Taxonomies", "Tags", "Homepage Display", "Customization"]
...
+++

With the theme Stack, these tags are displayed in 2 locations: at the bottom of the article (right before the footer) and, if you have enabled the corresponding widget, in the right panel on the Homepage.

List of tags in the footer of this article
List of tags in the footer of this article
half-half
half-half

I believe that being able to see which tags have been defined for an article directly from the homepage is interesting for the reader of the article. These keywords, in association with the title and the description, allow them to understand quite rapidly what will be the topics explored in the article.


❯  Add the code displaying these tags

First, let’s have a look at the file layouts/partials/article-list/default.html. This partial layout is used to display each article on the home page. It is invoking a partial, layouts/partials/article/components/headers.html. If you have a look at what the elements displayed on the homepage and the headers look like, you will see that the elements are the same: the cover image, the title and the description, the category, the creation date, and the reading time. Here, we want to integrate some differences, with an element (the tags), displayed only on the homepage.

I have explored the different solutions available, and have finally identified two ones:

  • Modify the call to the partial header.html in default.html in replacing . by (dict "context" . "isHome" true) } (and also in the other locations where header.html is also referenced, in replacing . by (dict "context" . "isHome" false) }. It also requires updating header.html, by replacing . with .context.. Since I want to add these tags between the description and the information on the creation date and reading time, we also have to pass this to the partial details.html. Finally, surround the block containing the logic displaying the tags in details.html with:
1
2
3
4
5
{{ if .isHome }}
...
code containing the tags logic
...
{{ end }}

If you are interested in this solution, I recommend you to have a look on this discussion.

  • Create a copy of the file header.html. We put the logic specific to the homepage on the new file, and we reference this new file on the partial default.html.

Note that there exists a variable named .isHome, a priori perfect for our case, but it always returns false in this case (cf this discussion).

I choose the second solution, but the two solutions are viable. Furthermore, the second may be more interesting in cases where you plan to apply more than one update like this (in my case, I made several updates, with particular a logic regarding the display of the last update time in the header of my articles).

So, create a copy of header.html and name it home-article-block.html. Then, since the update of the categories, title, description, creation date, and reading time are handled in another partial, details.html, either we have to create a copy for this file or replace in home-article-block.html the call to the partial by the content of this file.

Finally, change the partial in default.html to reference this new file:

1
2
3
4
{{ $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" }}
<article class="{{ if $image.exists }}has-image{{ end }}">
    {{ partial "article/components/home-article-block" . }}
</article>

On home-article-block.html, right after the closing of the <div> containing the description, add the following block:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
...
    {{ with .Params.description }}
        <h3 class="article-subtitle">
            {{ . }}
        </h3>
    {{ end }}
</div>

{{ $tags := .GetTerms "tags" }}
{{ range $index, $tag := $tags }}
    <a href="{{ $tag.RelPermalink }}">{{- $tag.LinkTitle -}}</a>
{{ end }}
...

So, after launching hugo server, for articles that have a list of tags in their frontmatter, you now have the list of tags that are displayed.


❯  Add condition if tags are present in the frontmatter of the article

Update the code as follows:

1
2
3
4
5
6
7
8
...
{{ if .Params.Tags }}
    {{ $tags := .GetTerms "tags" }}
    {{ range $index, $tag := $tags }}
        <a href="{{ $tag.RelPermalink }}">{{- $tag.LinkTitle -}}</a>
    {{ end }}
{{ end }}
...

❯  Add configuration to enable or disable globally the tags display

To do this, we will add a global configuration that we can set on the website’s configuration file, with a default behavior that enables the tag to be displayed if there is no configuration set. Finally, we will add the possibility to override the default behavior in the frontmatter of the articles.

Since this logic is a big complex, it will require updates on several files.


❯  The default behavior if there is no configuration set

At the root of the theme repository, update the file config.yaml by adding the following line under the category ' params':

1
2
3
4
5
...
params:
  ...
  showHomepageTags: true
...

❯  The param in the website’s configuration

In the case where you want to disable globally the display of tags on the homepage, you can add a configuration key to your website’s configuration.

  • if you have a single configuration file config.toml:
1
2
3
4
...
[params]
showHomepageTags = false
...
  • Alternatively, if you have a file params.toml, simply add the showHomepageTags = false in this file without the section [params].

To enable the display of the tags on the homepage, simply set this configuration to true (or remove this key; in this case, the default configuration defined before will apply).


❯  The param in the post’s frontmatter to override the global configuration

If, for some reason, you want to apply a different behavior to the one defined globally, you can add a configuration key to the frontmatter of the posts. For example, if this is globally disabled ut you want to enable it only for an article, in the frontmatter of this article:

1
2
3
4
5
+++
...
showHomepageTags = true
...
+++

❯  update the tags display in home-article-block to use these configurations

To take into account these configurations, and then control the display of these tags, update the components we have created before as follows:

1
2
3
4
5
6
7
8
9
...
{{ $showHomepageTags := .Params.showHomepageTags | default (.Site.Params.showHomepageTags) }}
{{ if and $showHomepageTags .Params.Tags }}
    {{ $tags := .GetTerms "tags" }}
    {{ range $tag := $tags }}
        <a href="{{ $tag.RelPermalink }}">{{- $tag.LinkTitle -}}</a>
    {{ end }}
{{ end }}
...

❯  Make it more stylized

Now, let’s add some updates to make it more in phase with the global style of the theme. First, in the theme, update the file assets/scss/partials/article.scss to add the following style:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
...
.home-article-tags {
  font-weight: lighter;
  color: var(--home-article-tags-color);
  line-height: 1.2;
  font-size: 1.5rem;

  hr {
    border: none;
    height: 0.5px;
    width: 100%;
    background-color: var(--home-article-tags-hr-color);
    margin-top: 5px;
    margin-bottom: 5px;
  }
}
...

On variables.scss, add colors corresponding to the variables --home-article-tags-color, and --home-article-tags-hr-color, both for the dark and light mode:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/*
*   Global style
*/
:root {
  ...
  --home-article-tags-color: rgba(114, 114, 114, 1);
  --home-article-tags-hr-color: rgba(153, 153, 153, 1);
  ...

  &[data-scheme="dark"] {
    ...
    --home-article-tags-hr-color: rgba(102, 102, 102, 1);
    --home-article-tags-color: rgba(255, 255, 255, 0.7);
    ...
  }
}

Now, let’s add an icon of tags that we will put at the beginning of the list of tags. Again, on the theme repository, create and add the following code in assets/icons/tags.svg:

1
2
3
4
5
6
7
8
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none"
     stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"
     class="icon icon-tabler icons-tabler-outline icon-tabler-tags">
    <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
    <path d="M3 8v4.172a2 2 0 0 0 .586 1.414l5.71 5.71a2.41 2.41 0 0 0 3.408 0l3.592 -3.592a2.41 2.41 0 0 0 0 -3.408l-5.71 -5.71a2 2 0 0 0 -1.414 -.586h-4.172a2 2 0 0 0 -2 2z"/>
    <path d="M18 19l1.592 -1.592a4.82 4.82 0 0 0 0 -6.816l-4.592 -4.592"/>
    <path d="M7 10h-.01"/>
</svg>

Note. This SVG comes from Tabler Icons. You can choose if you want another SVG from their website: there is a search engine to search among more than 5200 icons. And they are regularly adding new ones, cf their GitHub repository.

Finally, let’s update the tags block in the file home-article-block.html, by applying the style we have defined, adding a horizontal line surrounding the tags, adding the SVG defined above, and finally, adding a comma between each tag of the list defined in the frontmatter of the corresponding article:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
...
{{ $showHomepageTags := .Params.showHomepageTags | default (.Site.Params.showHomepageTags) }}
{{ if and $showHomepageTags .Params.Tags }}
    <section class="home-article-tags">
        <hr>
        {{ partial "helper/icon" "tags" }}
        {{ $tags := .GetTerms "tags" }}
        {{ range $index, $tag := $tags }}
            {{ if $index }}, {{ end }}
            <a href="{{ $tag.RelPermalink }}">{{- $tag.LinkTitle -}}</a>
        {{ end }}
        <hr>
    </section>
{{ end }}
...

❯  Wrap up

I have detailed how to update a website and its theme, based on the theme Stack, to display tags on the article elements displayed on the homepage.

In case you want to apply something similar to your website, I hope this article gave you some ideas and hints to succeed in this update.

Last, but not least: to facilitate the understanding of the changes I have made to obtain this result, I propose you to have a look at the following links:

  • An example website (on GitHub pages): here
  • The commit on this website’s codebase adding changes on the theme: here
  • The commit on this website’s codebase adding changes on the website: here