November 11, 2022

5 Useful Hugo Snippets

1. Icon Partials

Every website needs icons! I personally, don’t like having lots of SVG’s in my HTML markup. Using a partial is a great way to keep your code clean and easy to read. I have a partial for each SVG icon and pass in the classes I want to use as a single string.

<svg class="{{ . }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
    <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
</svg>

You can see on line 1 we use the class="{{ . }}" template syntax which will let you pass in classes directly to the partial. Like so

{{ partial "icons/arrow-right.html" "w-6 h-6" }}

This snippet is great for added a few related posts to the end of the current blog post. Related posts are assessed based off of your taxonomies, so it’s best to make sure you’re making use of your categories and tags.

{{ $related := .Site.RegularPages.Related . | first 3 }}
{{ if $related }}
<div>
  <div class="prose">
    <h3> Related Posts </h3>
  </div>
  {{ with $related }}
    <!-- Your Markup Here! -->
  {{ end }}
</div>
{{- end -}}

3. Next and Previous Post Snippet

This snippet will pull in the Next and Previous page into your template, which you can use to add links to the next and previous post.

<div class="grid md:grid-cols-2 gap-4">
  <div>
    {{ if .NextPage }}
    <a class="" href="{{ .NextPage.Permalink }}">
      {{ partial "icons/chevron-double-left" "h-4 w-4" }}
      {{ .NextPage.Title | truncate 30 "..."}}
    </a>
    {{ end }}
  </div>

  <div>
    {{ if .PrevPage }}
    <a class="">
      href="{{ .PrevPage.Permalink }}">{{
      .PrevPage.Title |
      truncate 30 "..."}}
      {{ partial "icons/chevron-double-right" "h-4 w-4" }}
    </a>
    {{ end }}
  </div>
</div>

4. Building a JSON API

Hugo has a lot of really cool feature, including the ability to render damn near any kind of file. One thing you might need is a Rest like API for your posts or pages. To do this you’ll need a few things.

First update your outputs in your configuration file. In this case I’m adding "JSON" to the list of sections. So for every section page that’s rendered it’s also going to look for a list.json file to render.

[outputs]
home = ["HTML", "RSS"]
section = ["HTML", "RSS", "JSON"]

Next place a list.json in the layouts directory. In my case, I only want to render JSON for my blog content type so I’ll create the file here: /layouts/blog/list.json.

{{- $.Scratch.Add "index" slice -}}
{{- range .Pages -}}{{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "content" .Plain "permalink" .Permalink) -}}{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

That’s it! Now you can access your API at https://yourdomain.com/blog/index.json. You’ll have the following keys

  • title - the title of the post
  • content - the content of the post
  • tags - the array of tags for the post
  • permalink - the permalink for the post

This is extremely useful if you want to build a search engine for your static site, something we’ll look at more closely in a future post.

5. Dynamic Values in Javascript/Typescript

In order to have dynamic light/dark mode themes with Daisy UI I wanted to be able to dynamically set the dark and light themes outside of the javascript, but in order to remember the user’s preference I needed to store it in local storage. These snippets combined are a great way to leverage the data- attributes in HTML to pass values to your javascript while not complicating your javascript code.

In this snippet I’m applying the data-theme-dark and data-theme-light attributes and rendering values from my Data files into them. When these are generated they’ll be replaced by the values in my /data/Global/Theme.yaml file.

<!DOCTYPE html>
<html
  data-theme-dark="{{ $.Site.Data.Global.Theme.Dark }}"
  data-theme-light="{{ $.Site.Data.Global.Theme.Light }}"
>
{{- partial "head.html" . -}}

<body>
  {{- partial "header.html" . -}}
  <div id="content">{{- block "main" . }}{{- end }}</div>
  {{- partial "footer.html" . -}}
</body>

</html>

Here’s the yaml file

Light: business-light
Dark: business

And finally, here’s how I’m accessing those values in Javascript

const LIGHT_THEME = document.documentElement.getAttribute('data-light-theme') || "business-light";
const DARK_THEME = document.documentElement.getAttribute('data-dark-theme') || "business";

When the page is loaded and the javascript is executed the data attributes will be read into the LIGHT_THEME and DARK_THEME variables. I can now access these throughout the rest of my scripts and use them to set the theme. You can apply this same technique to any kind of data you may want to pass between your HTML and Javascript.