Persisting data across the build of a site

I am trying to implement a random image to break up my wall-of-text posts.

I have a pile of images in an assets directory and am able to pull the list of them into a short code and randomly pull one out. The only issue is that this can result in duplicates being randomly selected during the build even on the same page.

Since these are in the markdown content, I believe I have to use a shortcode.

Is there a way to have a “global variable” that I can use to store the image list, modifying it each time I use an image so that is not an option for future calls to the shortcode?

Thank you, as always, for any help!

Maybe using Scratch? .Scratch | Hugo

1 Like

Thanks, I could be wrong… I was looking at that, but it seemed like both were either tied to the page context or just a local scope for newscratch.

It would help stop duplicates on the same page which would be a huge help regardless of being reused on the rest of the site

You can attach a Scratch to another page. For example, to set a Scratch on the home page:

{{ site.Home.Scratch.Set "foo" "bar" }} 

So your shortcode would look something like:

{{- $i := "" }}

{{- range $r := resources.Match "random-images/*" | shuffle }}
  {{- with site.Home.Scratch.Get "imagesUsed" }}
    {{- if in . $r }}
      {{- continue }}
    {{- else }}
      {{- $i = $r }}
      {{- site.Home.Scratch.Add "imagesUsed" $i }}
      {{- break }}
    {{- end }}
  {{- else }}
    {{- $i = $r }}
    {{- site.Home.Scratch.Set "imagesUsed" (slice $i) }}
    {{- break }}
  {{- end }}
{{- end }}

{{- with $i }}
  {{- with .Resize "200x" -}}
    <img src="{{- .RelPermalink }}" width="{{- .Width }}" height="{{- .Height }}" alt="{{- .Name | path.BaseName | humanize }}">
  {{- end }}
{{- else }}
  {{- warnf "There are not enough random images to choose from. See %s" .Position }}
{{- end -}}

However, because Hugo builds pages concurrently, by default this will not yield a unique image for each instance of the shortcode. You can get around this by setting the number of threads to 1.


There may be another way around the concurrency issue, but it’s not coming to me at the moment.

Whoa… I did not realize that an object (or whatever construct it has) would exist for other pages even when not building them… I guess in retrospect it needs to.

That is a really cool solution to my challenge! Thank you very much


There is.

In your baseof.html template, at the top:

{{- partialCached "init.html" . -}}


{{- range site.AllPages }}
  {{- $noop := .Content }}
{{- end -}}

What does this do? When the first page (any page) is rendered, the .Content of every page is rendered, sequentially, and assigned to a throw-away variable ($noop).

Here’s a working example:

git clone --single-branch -b hugo-forum-topic-41114 hugo-forum-topic-41114
cd hugo-forum-topic-41114
hugo server