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 15 suggestions For details on the linting of this post
 ./content/posts/selecting-a-random-image-in-hugo.md
 1:1     suggestion  You averaged 1.36 complex       marktoso.Kiss            
                     words per sentence                                       
 9:1     suggestion  Try to keep sentences short (<  Microsoft.SentenceLength 
                     30 words).                                               
 9:126   error       Punctuation should be inside    Microsoft.Quotes         
                     the quotes.                                              
 9:147   suggestion  'is supposed' looks like        Microsoft.Passive        
                     passive voice.                                           
 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:423   suggestion  'TTRPG' has no definition.      Microsoft.Acronyms       
 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:9    suggestion  'NPC' has no definition.        Microsoft.Acronyms       
 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:294  suggestion  Verify your use of 'allows'     Microsoft.Vocab          
                     with the A-Z word list.                                  
 13:319  warning     Use first person (such as       Microsoft.FirstPerson    
                     'my') sparingly.                                         
 13:340  suggestion  'be processed' looks like       Microsoft.Passive        
                     passive voice.                                           
 13:425  suggestion  'be used' looks like passive    Microsoft.Passive        
                     voice.                                                   
 13:507  suggestion  'is located' looks like         Microsoft.Passive        
                     passive voice.                                           
 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:181  suggestion  'are located' looks like        Microsoft.Passive        
                     passive voice.                                           
 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:199  suggestion  'is passed' looks like passive  Microsoft.Passive        
                     voice.                                                   
 30:381  warning     Use first person (such as       Microsoft.FirstPerson    
                     'my') sparingly.                                         
 32:4    suggestion  'Spicing It Up' should use      Microsoft.Headings       
                     sentence-style capitalization.                           
 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:1    suggestion  Try to keep sentences short (<  Microsoft.SentenceLength 
                     30 words).                                               
 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:10   suggestion  Try to keep sentences short (<  Microsoft.SentenceLength 
                     30 words).                                               
 51:40   warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 51:201  suggestion  'NPC' has no definition.        Microsoft.Acronyms       
 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:40   suggestion  'was checked' looks like        Microsoft.Passive        
                     passive voice.                                           
 56:146  suggestion  'was checked' looks like        Microsoft.Passive        
                     passive voice.                                           
 56:184  suggestion  Verify your use of 'as well     Microsoft.Vocab          
                     as' with the A-Z word list.                              
 56:210  warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 56:284  suggestion  'was put' looks like passive    Microsoft.Passive        
                     voice.                                                   

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