Selecting a Random Image at Build Time in Hugo

Posted on Jan 18, 2023

Sometimes, when searching for “how to do x” on the internet, you’ll come across forum posts that just say “don’t do that” or “that’s not how this is supposed to work”. It’s interesting that, in software, that would be an answer. One of the more recent things like that that I came across was for the static site generator, Hugo, which I use to build this site. I also use it to build the site for my TTRPG group where I keep track of session notes, NPCs, players, items, and world building. I’ve had to do some customization for my purposes and I have also taken it upon myself to bring some of the game into the website. I routinely use Midjourney to generate visuals and portraits to help immerse the players.

Pipes

For one NPC in particular, I want to pick a random portrait out of 8 or so. And I want to do this at build time. Technically, do this in javascript is feasible however I thought it would be interesting to do this at build time–the portrait would change but not too often. This, additionally, allows for the image, in my assets folder, to be processed and resized. As far as I’ve seen, for that to happen the image needs to be used in the build. This is where it gets interesting. The information for this is located on the Hugo Pipes page which, to be honest, is not where I expected to find it.

On this page the information of interest is regarding the resources… class? Object? It’s the best way to access the items in your assets folder. This is where my image files are located. using resources.Get you can grab and resize an image file easily enough:

{{ $resource := resources.Get (.Get "path")  }}
{{ $image := $resource.Fit "300x300" }} 

<figure style="float: right; max-width: 25%;" >

    <img style="max-width: 100%; width: auto; height: auto;" src="{{ $image.RelPermalink }}" >
	<figcaption style="text-align: center">
	    <small>
            {{ .Inner }}
	    </small>
	</figcaption>
</figure>  

This is how I get my player portraits right now–a partial template called portrait.html. This partial takes a parameter, called path and that parameter is passed in the shortcode like this: {{< portrait path="images/npc/fishman.png">}} . The path here is relative to the site assets folder so the images folder is inside of my assets folder already. Setting the src attribute of the img tag to {{ $image.RelPermalink }} will get Hugo to drop the relative permalink for the asset in there.

Spicing It Up

Variety is the spice of life, they say. I may actually break my website building it for this post so I’m definitely trying to spice up my own life–but what about your audience? Let’s grab a random image using resources.Match:

{{ $path := resources.Match "images/alric/*.png" }}

I realize that I reused path, but do as I say not as I do and name it something else. You may recognize that this gives us an array of all the images in images/alric/ with the file extension png. If we try to pass this to the image object to resize it and then grab a relative link–we can’t.

I tried various programmerly methodologies that I believe should have worked however, the Go templating world is a little bit different and I don’t think I’ve quite got the hang of it, so I worked around it. I also very well might have the hang of it and this is how it is.

{{ $path := resources.Match "images/alric/*.png" | shuffle }}
{{ range first 1 $path }}
    {{ $image := .Fit "300x300" }} 
    <figure style="float: right; max-width: 25%;" >
        <img style="max-width: 100%; width: auto; height: auto;" src="{{ $image.RelPermalink }}" >
    </figure>  
{{ end }}

So here, I grab the array of images and I pass it into shuffle to randomize it. I then iterate through exactly 1 image, the first one, and drop it into the page. I named this partial after this one NPC because this isn’t a trick that I intend to repeat but, by passing a parameter, you can use that to dynamically specify resources.Match and reuse this partial in other places. Now that I mention this, I may end up doing it. But as it sits, this shortcode does not take any parameters or have an Inner value so it’s very barebones.

This character’s portrait has a chance to be different every time the website builds which, if anyone is paying attention, will be an interesting hint. Stay safe and be nice.

Hi, this post was checked with vale which is a content-aware linter. It was checked using the Microsoft style as well as some rules that I made. A summary of those results is below. More details as to how this was put together check out this post. This post had: 6 errors, 41 warnings and 0 suggestions For details on the linting of this post
 ./content/posts/selecting-a-random-image-in-hugo.md
 9:126   error    Punctuation should be inside    Microsoft.Quotes       
                  the quotes.                                            
 9:274   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 9:357   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 9:420   warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 9:440   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 9:470   error    More than 3 commas!             marktoso.TresComas     
 9:552   warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 9:567   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 9:610   warning  Consider using 'some' instead   Microsoft.Wordiness    
                  of 'some of the'.                                      
 9:644   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 13:80   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 13:168  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 13:278  error    More than 3 commas!             marktoso.TresComas     
 13:319  warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 13:608  error    Use 'isn't' instead of 'is      Microsoft.Contractions 
                  not'.                                                  
 13:620  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 15:70   warning  In general, don't use an        Microsoft.Ellipses     
                  ellipsis.                                              
 15:166  warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 15:254  warning  Consider removing 'easily'.     Microsoft.Adverbs      
 30:12   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 30:19   warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 30:381  warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 33:40   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 33:62   warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 33:102  warning  Use first person (such as       Microsoft.FirstPerson  
                  'I'm') sparingly.                                      
 33:136  warning  Use first person (such as       Microsoft.FirstPerson  
                  'my') sparingly.                                       
 33:181  warning  Try to avoid using              Microsoft.We           
                  first-person plural like                               
                  'Let's'.                                               
 38:1    warning  Use first person (such as 'I    Microsoft.FirstPerson  
                  ') sparingly.                                          
 38:15   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 38:42   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 38:55   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 38:123  warning  Try to avoid using              Microsoft.We           
                  first-person plural like 'us'.                         
 38:206  warning  Try to avoid using              Microsoft.We           
                  first-person plural like 'we'.                         
 38:292  warning  Try to avoid using              Microsoft.We           
                  first-person plural like 'we'.                         
 40:1    warning  Use first person (such as 'I    Microsoft.FirstPerson  
                  ') sparingly.                                          
 40:48   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 40:140  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 40:188  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 40:208  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 40:216  warning  Consider removing 'very'.       Microsoft.Adverbs      
 40:268  error    Use 'it's' instead of 'it is'.  Microsoft.Contractions 
 51:40   warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 51:236  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 51:391  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 51:407  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          
 51:462  error    Use 'doesn't' instead of 'does  Microsoft.Contractions 
                  not'.                                                  
 51:522  warning  Consider removing 'very'.       Microsoft.Adverbs      
 56:210  warning  Use first person (such as ' I   Microsoft.FirstPerson  
                  ') sparingly.                                          

6 errors, 42 warnings and 0 suggestions in 1 file.