I’ve successfully configured Hugo with multiple output formats to render pages in different formats (e.g., multiple HTML formats, ICS for internet calendars, and JSON). This setup works great so far.
However, I’m now running into a challenge: I need Hugo to dynamically search for and resize images based on speaker names provided in the page’s front matter data. While I’ve got a working solution for the HTML template, I’m struggling to integrate this functionality into the JSON output.
Current HTML Template
Here’s the working template that locates and resizes images based on the speaker’s name:
{{ $headshot := (printf "headshots/%s.*" (default (.name | urlize | safeURL) .headshot)) -}}
{{ $img := $.Page.Resources.GetMatch $headshot }}
{{ $title := (printf "%s - %s" .name .title) }}
{{ with $img }}
{{ $img = $img.Resize "x150" }}
{{ return $img.RelPermalink }}
{{ end }}
This looks for an image file named headshots/speaker-one.jpg
and generates a relative permalink to the resized image. It also allows manual overrides using the .headshot
variable for filenames with diacritics or other complexities.
The JSON Output Template
Currently, my JSON output template is straightforward:
{{- .Page.Params.data | jsonify -}}
Which results in:
{
"name": "Event name",
"speakers": [
{
"name": "Speaker One",
"title": "Expert at Org Inc."
},
...
]
}
When we can’t modify the data, our template becomes significantly more complex and error-prone, as it would mean reconstructing the entire JSON output just to add the resized images.
Front Matter Example
Here’s an example of my page’s front matter:
outputs:
- html
- event-data
- event-overlays
- event-session
- event-agenda
data:
name: Event name
timezone: America/Chicago
speakers:
- name: Speaker One # Locate image based on this name
title: Expert at Org Inc.
- name: Speaker Fifty
title: Expert at Org Ltd.
Some speakers might not have associated headshots, and in such cases, the output should gracefully handle missing images.
Desired scratch pad data
I want to enhance the data.speakers
section by adding resized images for each speaker, resulting in something like this:
data:
speakers:
- name: Speaker One
title: Expert at Org Inc.
headshots:
"150x": "./speakers/speaker-one-150x.jpg"
"500x": "./speakers/speaker-one-500x.jpg"
- name: Speaker Fifty
title: Expert at Org Ltd.
Scratchpad Issue
I attempted to use Hugo’s scratch pad to dynamically update the data
object, but I’m running into issues. For example, the following simple example doesn’t update the data.name
value as expected:
{{- $s := newScratch -}}
{{- $s.Set "data" .Page.Params.data -}}
{{- $s.Set "data.name" "test" -}}
{{- $s.Get "data" | jsonify -}}
same for:
{{- $s := newScratch -}}
{{- $s.Set "data" .Page.Params.data -}}
{{- $s.SetInMap "data" "name" "test" -}}
{{- $s.Get "data" | jsonify -}}
but this ‘works’ (overwrite the entire object):
{{- $s := newScratch -}}
{{- $s.Set "data" .Page.Params.data -}}
{{- $s.Set "data" "test" -}}
{{- $s.Get "data" | jsonify -}}
Questions
- Can the scratch pad or store handle nested data to begin with?
- Is there a better approach than the scratchpad to achieve this transformation?
Any advice or insights would be greatly appreciated. Thanks in advance for your help!