Add a Random Page Button to Hugo Site

UPDATED ON MAR 25, 2022 : 384 words, 2 minute read — TIL

I wanted to add a random button to one of my Hugo sites after remembering how handy it is on XKCD . Turns out it’s a really simple process with Hugo, just need to generate a JSON file and then write a simple script to choose your random article.

What are we making? 🔗︎

Portfolio website with a randomizer button

How-to 🔗︎

1. Create JSON list of pages 🔗︎

Hugo conveniently lets you output JSON data, so we create one at the root which will get deploy alongside the rest of our static files. Couple caveats for this example:

  1. my filters are simple because the site only has one page archetype and I wanted all of them. You can definitely get mroe creative with Hugo’s where and other functions .

  2. This index for site search was already in the theme I was using. If you just want the randomizer, you can drop all the extra data fields like tags and contents.

    layouts/_default/index.json 🔗︎

    {{- $.Scratch.Add “index” slice -}} {{- range where site.RegularPages “Type” “in” site.Params.mainSections -}} {{ $date:= .PublishDate.Format “02”}} {{- $.Scratch.Add “index” (dict “title” .Title “date” $date “tags” .Params.tags “image” .Params.image “categories” .Params.categories “contents” .Plain “permalink” .Permalink) -}} {{- end -}} {{- $.Scratch.Get “index” | jsonify -}}

I needed to add a small param in my config.toml, here’s an article if you want to dive a bit deeper and understand more of what is going on.

[outputs]
    home = ["json", "html"]

Prod JSON output 🔗︎

For reference, the JSON that the above Hugo code will end up outputting.

[
   {
     "categories": [
       "Developers"
     ],
     "contents": "text of the document",
     "date": "07",
     "image": "images/post/article-1.png",
     "permalink": "https://permalink",
     "tags": [
     	"Software Development"
     ],
     "title": "Title of the most recent article"
   },
 ...
 ]

2. Use JSON in an HTML page 🔗︎

You can add something similar to this in your HTML pages. I have this in a partial where the button is displayed on the page.

<script>
 var searchIndexData = [];
 // fetch on page load from the search index
 let json_path = window.location.origin + '/index.json'

 fetch(json_path).then(function (response) {
 	return response.json();
 })
 .then(function (data) {
 	searchIndexData = data;
 })
 .catch(function (err) {
 	console.log(err)
 });

  
 function sendToRandomArticle() {
 let randIndex = Math.floor(Math.random() * searchIndexData.length);
 let randArticle = searchIndexData[randIndex]['permalink'] + '?utm_source=RandomButton';
 window.location.href = randArticle;
 }

</script>
...
...
<button type="button" class="btn btn-primary" onclick='sendToRandomArticle()'>Random</button>

That’s it! Told you it was simple.


See Also