Learning to Hugo Part 4: Shortcodes and Archetypes

Learning to Hugo Part 4: Shortcodes and Archetypes

Table of Contents

A long time ago in a galaxy far, far away…

This post is over 12 months old and Hugo is evolving. Please be mindful of that when reading this post, young Padawan, as it could be outdated. I try to keep things up to date as much as possible. If you think something needs updating, please let me know in the comments.

Intro

This is the fourth part of the learning to Hugo series detailing my journey to getting this site up and running! I am also using Hugo to configure my business website. In typical dev style, I just installed Hugo and got going. I have learnt a few things along the way that have improved my development time and hopefully these things will help you.

In this section I am going to explain how to use shortcodes and archetypes to create repeatable content.

Health & safety warning

I am no web dev! My world is data and so this stuff is outside my area of expertise. I am learning as I go and so the info I am sharing is my interpretation of that in a way that makes sense for me as a data-person-doing-web-dev. Some of the technical aspects might be a little misunderstood and I would love to hear from you in the comments if you think there's a better way or if I have misunderstood a concept. Hopefully outlining my understanding of it might make it easier for someone wanting to give it a go. If you want advanced CSS understanding or web development skills though these are not the posts you're looking for!

obi wan kenobi saying these are not the posts you're looking for

obi wan says these might not be the posts you're looking for

Shortcodes

A shortcode is a snippet that can be added to your markdown file to call a built in or custom template. It’s a great way of reducing complexity in post creation. There are a number of built in shortcodes and you can also roll your own. That’s great for me - it’s a handy way of not having to fumble through HTML all the time. I can engage my brain for a few hours to get a snippet to work and then I will never have to remember it again!

Tweet

Hugo has a number of built in shortcodes. For example, there is a Twitter shortcode which takes the tweet ID and creates an embedded tweet (2023 edit…this will no longer work because of Elon, but there is a fix, read in this blog post). Find the tweet you are after and hit the share button, from there you can grab the tweet’s URL.

picture of a tweet pointing at the share icon

The URL for this tweet is https://twitter.com/justinjbird7/status/1389503945291309056. If I just take the numeric ID and place it in the tweet shortcode;

{{< tweet 1389503945291309056 >}}

It will embed my tweet like this;

Image is of a tweet by justinjbird7 click on the image to see the original tweet

It’s a fully embedded tweet!

Behind the scenes, the tweet shortcode has constructed the embed tweet coding and simply grabs the number you have passed in and applies the code to your built page. Pretty neat!

Gist

Another useful shortcode for coders is the gist shortcode. This shortcode requires the last two sections of the gist URL. Take this URL for example;

https://gist.github.com/justinjbird/65e6f915b37189ac520047cb40ed8c4d

Turn it into the following shortcode;

{{< gist justinjbird 65e6f915b37189ac520047cb40ed8c4d >}}

And it will be embedded like this;

The main purpose for these is to reduce clutter and perhaps to reduce your need to know more complex HTML but it can also be quite a time saver. There is a host of built in shortcodes listed on the Hugo page (see more reading section below).

Page params

You can also reference front matter using the param shortcode. Here is a few examples for this page;

{{< param categories >}}
[hugo]
{{< param authorName >}}
Justin

So I could build up these params to create sentences;

{{< param authorName >}} wrote a post about {{< param categories >}} on {{< param date >}}
Justin wrote a post about [hugo] on 2021-05-05 11:04:00 +0100 +0100

Custom shortcodes

On top of these built in shortcodes, it’s possible to create your own. I have been using this as a way to conform sections of posts, it also makes updating sections really easy too. All of my posts end with a thanks shortcode;

<h2>Thanks</h2>
If you made it all the way down here, thanks for reading my post and enjoy your day.
<br>
<br>
<figure>
    <picture>
        <source srcset="/images/stuff-jb/jedi.webp">
        <img src="/images/stuff-jb/jedi.webp" alt="#mtfbwy" defer class="lazyautosizes lazyloaded" data-sizes="auto" data-src="/images/stuff-jb/jedi.webp" >
    </picture>
    <figcaption>
        <b><p class="caption">#mtfbwy</p></b>
    </figcaption>
</figure> 

There are two advantages to this. Firstly, this makes all my summaries consistent. Secondly, if I ever wanted to change this section, I only have to edit the content of my shortcode and rebuild my site!

How to create a shortcode

Create a folder in your layouts folder called shortcodes, any html file created in this folder becomes a shortcode. I will create a new file called “example-shortcode.html” which you can see here;

image showing a new file at path ./layouts/shortcodes/example-shortcode.html

And that is it! Once the file is saved it’s immediately available. So then I can reference the new shortcode like this;

{{< example-shortcode >}}

It will create that block of code on the page like this;

Example Shortcode

Check out my new shortcode!!! It's cool!


Archetypes

Archetypes are content templates. It is a way of constructing preconfigured front matter and content for your new posts. This can be a useful way to reduce the amount of time to create new posts. You can prepare a template with a number of preconfigured settings and once you create a new post, Hugo will apply that template to it.

Default archetype

When you create a new site, a default archetype will exist which looks like this;

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

There is no content in this archetype, just front matter settings. The title of the post, the creation date and a setting to tell Hugo it is currently a draft.

This introduces another concept of Hugo which is functions. Functions are triggered when the page is built .Name refers to the name of the file and the replace function replaces any hyphens with a space thus the title of the page by default is the name of the file with spaces instead of hyphens. {{ .Date }} is the current datetime, so when you create the page, the current date and time will be stamped to the page meta. Finally, by default the page will be created as a draft.

Create a new archetype

If you create a new post using the command line, Hugo will initially look for a file named the same as the parent directory you place the file in, or the defined type you set in the command line. If it can’t find one it will revert to default.md. So for example, if you create a posts.md archetype that will be applied to any files you create in the posts directory.

Here is the command to create a new post;

hugo new posts/new.md

A page will be created at ./content/posts/new.md and will have the layout from ./layouts/archetypes/posts.md applied. The easiest approach to this is to copy the default archetype, rename the file and work from there.

Multiple archetypes

So far we have seen how to create a single template for all your posts, but what if you want to create a template for just some of your posts? Hugo will look for a file with the same name as the content type, followed by default however, you can tell Hugo which archetype to use when creating the page using a switch. My site currently has two bespoke archetypes for themed posts;

  • hugo.html (this very post is an example of that layout)
  • tsqltuesday.html (this is an example of that layout)
image showing three archetypes - default, hugo and tsqltuesday

Therefore depending on which sort of post I want to create, I will run one of three commands;

hugo new posts/drafts/my-new-tsqltuesday-post.md --kind tsqltuesday
hugo new posts/drafts/my-new-hugo-post.md --kind hugo
hugo new posts/drafts/my-new-sql-post.md

This is really handy for preparing a consistent layout for a series of posts because it will cut down on setup when you create new posts in the series.

Putting them all together

Using all of these features together allows you to construct a lot of repeatable content. For example, you can create a template with multiple shortcodes and a number of preconfigured metadata values. Once you create a new post, a lot of the content has already been preconfigured. You can even include comments for future you, so that you know what other things need finishing up.

My Hugo archetype

Because I wanted to make all of these “learning to Hugo” posts look consistent to some extent, I set up an archetype file which looks like this;

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
image: "/images-shared/thumbs/hugo.webp"
categories: 
    - hugo
tags: 
    - getting started
description :       # add a description for the post list


intro1:             # which number in the series is this? Put it in words, i.e. fifth
intro2:             # place some words to add to the end of the sentence "in this post I am going to..."
---

{{< hugo-header >}}

<!-- put content here -->

{{< hugo-footer >}}

So a lot of the config is pre-configured - all I need to do is update the description, intro1 and intro2, then write some content. The hugo-header shortcode adds the first two sections to the page including the Obi Wan image (I start writing from the “shortcodes” header) and hugo-footer adds the last two sections after “more reading”. The hugo header is getting the values from intro1 and intro2 and putting them in my intro.

My tsqltuesday archetype

I have been a bit more creative with this one, making a bit more use of functions;

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
watermark: "Blog"
thumbnail: "/images/community/tsql-tuesday.webp"
draft: true
categories: 
  - tsql2sday
tags: 
    - untagged
description : "This is my <number> contribute to TSQL Tuesday"      # update number

post_count:         # post count in words i.e. ninth, first post was 131
host_first_name:    # first name of host
host_surname:       # second name of host
host_blog:          # url of invite
host_twitter:       # url of host's twitter
host_request:       # complete the sentence person invites us to...
---

{{< tsqltuesday-header >}}

<!-- put content here -->

{{< post-footer >}}

To give you the full picture, here is the contents of my tsqltuesday-header shortcode;

...
This month's T-SQL Tuesday is hosted by {{ $.Page.Params.host_first_name }} {{ $.Page.Params.host_surname }} (<a href="{{ $.Page.Params.host_blog }}">Blog</a> | <a href="{{ $.Page.Params.host_twitter }}">Twitter</a>). {{ $.Page.Params.host_first_name }} invites us to {{ $.Page.Params.host_request }}.
...
This is my {{ $.Page.Params.post_count }} contribution to T-SQL Tuesday! 

When I first started writing TSQL Tuesday posts, I was copying the content from the previous post, deleting the old content and replacing it with the new content which was just clunky and boring. I have written out this snippet so that once the post is created all I need to do is add the relevant information to the front matter and it will be applied into the wording accordingly.

Each of the functions grabs a value from the front matter and passes that into the text block. When the page is initially constructed these values will be blank, but if I add them into the front matter of the page and rebuild the site, content will get populated. The result is a fully formed sentence that looks something like this;

This month's T-SQL Tuesday is hosted by Mikey Bronowski (Blog | Twitter). Mikey invites us to write about the outstanding tools of the trade that make your job awesome.

Summary

In this post I have covered a few ideas on how to create repeatable content to speed up development and be able to apply changes across multiple posts in a quick and efficient way using shortcodes and archetypes.

Notes

Whilst I haven’t explored them for this sort of process, partials offer another way to create small components for your page. I have adjusted partials to alter formatting or page construct but having found a flow using archetypes and shortcodes I haven’t explored the art of possible with them just yet. If you have used partials to implement some of the ideas above, I would be interested to learn what you have done.

More reading

Any comments?

I would love to hear from you in the comments. If you think something needs more explanation or I have not quite understood a concept, if you have a question or just want to say hi please drop me a message in the comments!>

#mtfbwy



Recent Posts