In working on my Hugo powered gallery, I ran into some interesting issues, one of which was from my theme.
I use a Bootstrap powered theme called Hinode. And Hinode is incredibly powerful, but it’s also very complicated and confusing, as Hugo’s documentation is still in the alpha stage. It’s like the early days of other web apps, which means a lot of what I’m trying to do is trial and error. Don’t ask me when I learned about errorf
, okay?
My primary issues are all about images, sizing and filing them.
Image Sizes
When you make a gallery, logically you want to save the large image as the zoom in, right? Click to embiggen. The problem is, in Hinode, you can load an image in a few ways:
- Use the standard old
img
tag - Call the default Hugo shortcode of
{{< figure >}}
- Call a Hinode shortcode of
{{< image >}}
- Use a partial
Now, that last one is a little weird, but basically you can’t us a shortcode inside a theme file. While WordPress has a do_shortcode()
method, you use partial calls in Hugo. And you have to know not only the exact file, but if your theme even uses partials! Some don’t, and you’re left reconstructing the whole thing.
Hinode has the shortcodes in partials and I love them for it! To call an image using the partial, it looks like this:
{{- partial "assets/image.html" (dict
"url" $imgsrc
"ratio" "1x1"
"wrapper" "mx-auto"
"title" $title)
-}}
That call will generate webp versions of my image, saved to static image folder (which is a post of its own), and have the source sets so it’s handy and responsive.
What it isn’t is resized. Meaning if I used that code, I would end up with the actual huge ass image used. Now, imagine I have a gallery with 30 images. That’s 30 big ass images. Not good. Not good for speed, not good for anyone.
I ended up making my own version of assets/image.html
(called lightbox-image.html
) and in there I have this code:
{{ with resources.Get $imagefile }}
{{ $image = .Fill "250x250" }}
{{ $imagesrc = $image.RelPermalink }}
{{ end }}
If the file is local, which is what that get call is doing, it uses the file ($imagefile
is the ‘path’ to the file) to make a 250×250 sized version and then grabs that new permalink to use.
{{ if $imagefile }}
<img src="{{ $imagesrc }}" class="img-fluid img-lightbox" alt="{{ $title }}" data-toggle="lightbox" data-gallery="gallery" data-src="{{ $imagefile }}">
{{ end }}
Boom!
This skips over all the responsive resizing, but then again I don’t need that when I’m making a gallery, do I?
Remote Image Sizes
Now let’s add in a wrinkle. What if it’s a remote image? What if I passed a URL of a remote image? For this, you need to know that on build, that Hinode code will download the image locally. Local images load faster. I can’t use the same get, I need the remote get, but now I have a new issue!
Where are the images saved? In the img
folder. No subfolders, the one folder. And I have hundreds of images to add.
Mathematically speaking, you can put about four billion files in a folder before it’s an issue for the computers. But if you’ve ever tried to find a specific file to check in a folder that large, you’ve seriously reconsidered your career trajectory. And practically speaking, the more files, the slower the processing.
Anyone else remember when GoDaddy announced a maximum of 1024 files in a folder on their shared hosting? While I question the long term efficacy of that, I do try to limit my files. I know that using the get/remote get calls with tack on a randomized name at the end, but I’d like them to be organized.
Since I’m calling all my files from my assets server (assets.example.com
), I can organize them there and replicate that in my build. And my method to do that is as follows:
{{ if eq $image "" }}
{{- $imageurl = . | absURL -}}
{{- $imagesrc = . | absURL -}}
{{ $dir := (urls.Parse $imageurl).Path }}
{{ with resources.GetRemote $imageurl | resources.Copy $dir }}
{{ with .Err }}
{{ warnf "%s" . }}
{{ else }}
{{ $image = . }}
{{ $imageurl = $image.Permalink }}
{{ $image = $image.Fill "250x250" }}
{{ $imagesrc = $image.RelPermalink }}
{{ end }}
{{ end }}
{{ end }}
I know that shit is weird. It pairs off the earlier code. If you don’t create the image variable, then you know the image wasn’t local. So I started by getting the image url from ‘this’ (that’s what the period is) as an absolute url. Then I used the path of the url to generate my local folder path! When I use the Copy command with the pipe, it will automatically use that as the destination.
Conclusion
You can totally make images that are resized in Hugo. While I wish that was easier to do, most people aren’t as worried as I am about storing the images on their repository, so it’s less of an issue. Also galleries on Hugo are fairly rare.
I’m starting some work now with Hinode for better gallery-esque support, and we’ll see where that goes. Maybe I’ll get a patch in there!