Hugo partials

Learn how to break down your Hugo pages into smaller “components” with partials in this Hugo tutorial.

What you’ll learn here:

  • Create reusable HTML partials throughout your site

  • Pass data to partials

  • More practice with Go templating

  • Get an overview of partials vs. “shortcodes”

# Starting repo
git clone

# Starting branch:
git checkout partials-intro-start 

# Finished branch:
git checkout partials-intro-finish 

What's a partial?

A partial is quite self-explanatory: it’s a small “part” (or”component”) of an HTML page. You’ll often end up needing one any time you find that you have repetition or want to divide larger pages into more manageable parts. Great examples of use cases are headers, footers, navigation, and any other fragments of a page that you might reuse.

In fact, let’s use exactly these examples for our partials.

Important notes on partials

  • Hugo partials can only be used in HTML layouts - not in content pages. (See discussion on “shortcodes” below.)
  • You generally can’t “query” data for partials inside a partial*.* Any data for your partial needs to be passed down into a partial from where you are including it. (More context on this below.)

Practical work: creating partials

As we did in the previous tutorial, clone the code for our code-along project and check out the branch for this lesson.

What we want to work on here is our baseof.html, as it’s a bit long and we want to make it more modular with partials.

Creating partials

  • Create the partials folder in the root of  layouts (Hugo knows to look for this).
  • Create head-meta.html, nav.html, and footer.html in the newly created folder.
  • Extract these parts of layouts/_default/baseof.html into their respective empty files from above:
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{ if isset .Params "title" }}
  <title>{{ site.Title }} | {{ .Title }}</title>
{{ else }}
  <title>{{ .Title }}</title>
{{ end }}
<meta property="og:title" content="{{ site.Title }}" />
  • nav.html: <header> block.
  • footer.html: <footer> block.
  •  Include these partials back into baseof.html where the original HTML used to be:
<!DOCTYPE html>
<html lang="en">
    {{ partial "head-meta.html" }}
    {{ $style := resources.Get "sass/main.scss" | resources.ToCSS | resources.Minify }}
    <link rel="stylesheet" href="{{ $style.Permalink }}">
    <link href=";600;700&family=Prompt:wght@700&display=swap" rel="stylesheet">
  <body class="page">
    {{ partial "nav.html" }}
    <main class="main-content">
      <div class="container">
        <div class="page-content">
          {{ block "main" . }}{{ end }}
    {{ partial "footer.html" }}

Now baseof.html is a bit cleaner, and we can work on the partials more easily now they are smaller components.

Passing data to partials

Partials are great for making your site more manageable. But sometimes you want to do more with them, to make them a bit more flexible and dynamic.

We can do some amazing, powerful things, but for now let’s focus on simple examples. Currently, the page title is not being shown if you look in the browser tab (should be “Page name | Site name”). To solve this, we can simply pass the current page context (current data available to that page) into the head-meta partial:

<!-- Pass current context "." to head-meta -->
{{ partial "head-meta.html" . }}

Additionally, we can also pass our own, specific data into our partials. Let’s make a small change to the footer to demonstrate:

First, add a dictionary with data to the footer partial in _default/baseof.html:

{{ partial "footer.html" (dict "description" "your favourite bird blog" )}}

Then, next to {{ site.Title }}, add a reference to the “description” key in in layouts/partials/footer.html:

<h2 class="footer-content__site-name">
  {{ site.Title }}, {{ .description }}

There are many applications for this. For example, you could build components, such as buttons or lists, that dynamically change from the data you pass into it, such as arrays, CSS classes, or image locations.

Partials → layouts | shortcodes → content

We mentioned earlier that you can’t use partials inside your content files (which we’ll look at more closely next), only layouts. Before we get too ahead of ourselves, it’s worth mentioning that there is, in fact, a counterpart to partials for your content pages: shortcodes.

Shortcodes are custom code snippets, written in HTML and Go templating, that are only usable inside content pages. Hugo has many built-in shortcodes, but we’ll deal with these later, and even write our own.

What's next?

Partials in Hugo are great for making your layouts easier to manage. Now that we’ve got most of the basic framework of a site ready to go, let’s start adding actual content pages to our site.