So you have started using Hugo for your website or blog or whatever you have built and you came across something called Shortcode.

If Hugo were a programming language, shortcodes would be sub-routines, or reusable units of code. - Eakan

But the truth is Hugo is not a programming language. It is a static site generator that generates content based on markdown files. Markdown syntax is pretty limited. So how do you make your website as attractive and engaging as any other modern website with these limitations?

Enter shortcodes.

These snippets of reusable code can be put in any markdown file. That’s the beauty of it. But wait! If you have also heard of template files, you might begin to wonder isn’t that what templates are for?

What are templates?

According to Hugo’s documentation:

A template is an HTML file with template actions, located within the layouts directory of a project, theme, or module.

Template actions are like a control structure within a template that gives the user the ability to execute some sort of code within an HTML file - conditional logic or sorts.

Difference between shortcodes and templates

Both shortcodes and templates are features that enable some level of re-use of functionality in Hugo.


However, shortcodes are like an extension to markdown, wherein you overcome the limitations of markdown using a shortcode - like displaying a twitter post or a github code snippet in markdown in a specific way and having the ability to do that in any post or page you create.


Templates on the other hand determine how an HTML page can be rendered with enhanced functionality or behave conditionally based on certain parameters. You write templates in HTML and not markdown. You then make them behave in different ways using template-actions, the things that you see between {{ and }} in a template file.

When would you use one over the other?

Let me explain with a couple of examples.

Use case 1 - content specific external content embedding

Let’s say you want to render a github gists in your blog post. In this use case, you want to include a gist in a post - using some specific params that would uniquely identify the gist to be referenced in that post. Thus the gist is specific to the content or post you are creating. This is a common use-case for shortcodes.

So a github gist shortcode could be parameterised and included in any post in the future to reference different types gists for different posts in a consistent manner.

Use case 2 - a user interface element to be rendered in every post that you create

This is a perfect use-case for a template or a partial template. Shortcodes have a limitation. They cannot be embedded in HTML and only be referenced in markdown. Hence, in order to make something that can be rendered in every post by default without having to explicitly mention it, you create a partial template for this. Then reference that partial template in the template for the type of content you are creating, e.g a post. This is exactly how I made it possible to include a Buy me a coffee link in every post I create.

Buy me a coffee button

I was searching for a way to include a Buy me a coffee button with my posts on this blog. I stumbled upon bmc-button by isqua. Checkout the documentation website to learn how to use the shortcodes.

Now the problem with using this as a shortcode is that I have to include this with every post a line in the markdown. This wasn’t what I wanted. I wanted every post to have this by default, just like the social sharing buttons. So that’s when I started looking into alternatives and learned about the differences between shortcodes and templates.

So I went ahead and converted this shortcode into a partial template!

How did that go?

So a shortcode cannot be copied and pasted into a partial template like for like. They are different things and have different limitations.

The biggest difference is that you cannot do a .Get in a partial! You always fetch params from params of the site or the page. But majority of the remaining code is pretty much the same.

The partial also relies on the same button configuration as the shortcode, so minimises any changes needed on that end too.

The above gist is rendered using hugo’s built-in shortcode for gist.

All I had to do is:

{{ < gist lonelydev 5ac6bbbe86b6c64e1d2221e2ccd99b08 > }}


  • lonelydev - is my github user name.
  • the long string is the unique identifier of the gist.

That’s all for now.