What we want to achieve
Often I want to insert examples, interactivity, and quality-of-life features into one of these blog posts. I will invariably have to reach for JavaScript to achieve it. But it annoys me to have to manually include the scripts through the source file. Also, it just feels wrong to do this by hand when using a static site generator like Hugo. Let the generator take care of it.
We can embed it through a Hugo short-code. In the right circumstances, this is the correct method. But short-codes appear in the text. They want to describe a part of the article which exists at this location. JavaScript embeds don’t always do that. They can, when the embed refers to a specific example which I want to insert at the short-code location. But they don’t have to for a lot JavaScript functionality. Then again, the way we declare data for a post is to put it in the post’s [front-matter](TODO link). For me, the right way to embed JavaScript in one of my posts is to create a ‘universal’ embed-code.
In the following two paragraphs we will see how to create a Hugo short-code, embedding JavaScript within the text. We will then look at how we can set Hugo up to embed any JavaScript added in the front-matter.
JavaScript via short-code
Creating new short-codes in Hugo is straight-forward. Most themes, and Hugo
itself, contain
an array of them
already. Creating the code snippet to embed JavaScript is rather easy. Create a
new an html file in the layouts > shortcodes directory in your Hugo folder.
Call it whatever you want to call your short-code. We will use js
for this
example to keep it straightforward. All you have to put into this html file is
the following:
<script src="{{ .Get 0 }}"></script>
This will let you call embed JavaScript at a specific location in your text by
calling {{ % js https://link.to/my-javascript-file.js % }}
. You can do way more
with custom short-code templates, but even this example gives some advantages.
Say we were to decide on a new style of embedding JavaScript. We change the
template and all our earlier embeds automatically update. We may add a new
Generally in-text embeds like this are more specific. They embed a YouTube
video, or a GitHub gist – but this is their basic idea.
JavaScript via front-matter
What if we do not want to embed our file at a specific location. What if the JavaScript we wrote is not specific to a location on the page but related to the page itself. What if we need it on a lot of separate pages, but not every one. In that case, I prefer to use the front-matter. It separates the content of our article from the content of our page and let’s us change both individually.
Accomplishing this is not that different from creating a short-code. The biggest change is where we place the template. Instead of creating a short-code html file, we will put the code into the footer template partial.1 Find the footer partial in your themes > theme name > layouts > partials directory. Copy it into your main page directory while keeping the folder structure the same: layouts > partials. Then add the following to the bottom of the partial:
{{- range .Params.js }}
<script src="{{ . }}.js"></script>
{{- end }}
This uncomplicated template will allow you to add the following to the front-matter of your pages:
---
title: "Inserting JavaScript into Hugo Posts through your front-matter"
date: "2019-02-02T10:09:45+01:00"
js:
- "my-relative-file"
- "https://link.to/my-absolute-file"
---
Hugo will include both of these files will in your page when it compiles. It
will do so for any number of files you append. The absolute link is
straightforward, the relative link lies at the root of your static folder. You
can use js: "folder-to/my-relative-file"
if your file is in a sub-directory.
At its simplest, that is all we have to do. In the name of keeping things
modular, it may be worth it to put the html snippet into its own scripts.html
partial and append that to the footer instead, more so when your theme has its
own complicated footer already. I will keep that an exercise for you to
experiment with. Now try your hand at your own front-matter embedded page customizations!
Thanks for reading.
-
This will not work if the theme you are using does not place a footer somewhere on each page. Most themes do this for the pages. If yours does not, you can override it to do so. Place the footer-partial html code on the single.html layout default. Or you can use some other partial which appears on every page in your layout. ↩︎