A Hugo partial that vastly improves resource management in Hugo sites by avoiding duplicate images in your content based on Page Bundles and Headless Bundles
This partial is designed for retrieving resources from a page bundle in Hugo, where resources refer to files like images, or data files. The partial is used for obtaining resources from Page Bundles, with a unique feature of traversing upwards to parent page bundles if the resource isn’t found in the current page’s bundle. This is especially useful for managing resources that are inherited on child pages or shared across multiple sections.
Illustrative example
Let’s consider the following example of a directory structure:
1content:
2 articles:
3 _index.md
4 my-article:
5 index.md
6 images:
7 feature-image.jpg
8 images:
9 index.md
10 share-image.jpg
11assets:
12 images:
13 logo.png
If you now use this partial in the file content/articles/my-article/index.md
, you can access the three images by their relative paths.
Accessing a feature image
As the feature image is specific to the article, it exists in the page bundle of the article my-article
. We can access it using the following code:
1{{ $featureImage := partial "claris/_functions/resources/get" (dict
2 "Page" .
3 "resource" "images/feature-image"
4) }}
Accessing a share image by traversing the file hierarchy
Now the share image might also be specific to the article, but in my case, I use the same share image for all articles. The share image hence only exists in the branch bundle of the articles section articles
.
Note
Ensure to turn images
directory into a headless bundle: Add a file named index.md
with the following content into every images
directory that is part of a branch bundle (see below for an explanation what a branch bundle is)
1---
2headless: true
3---
If we have properly set up the images
directory under articles
as a headless bundle, we can access the share image share-image.jpg
from the page bundle my-article
using the following code:
1{{ $shareImage := partial "claris/_functions/resources/get" (dict
2 "Page" .
3 "resource" "images/share-image"
4) }}
Perhaps surprisingly, the call to the resources
partial is almost the same, even though we will get an image from a headless bundle one level up.
Accessing the logo image from the global assets
folder
Finally, the site’s logo image will be the same for all articles. Hence, it makes sense to either put it into a headless bundle at the top of the content
directory, or into the assets
directory.
To access the share image, we use the following invocation of the resources
partial:
1{{ $logoImage := partial "claris/_functions/resources/get" (dict
2 "Page" .
3 "resource" "images/logo"
4) }}
Again, the call to the resources
partial is almost the same, even though we will get an image from the global assets
directory.
Basic usage
This partial accepts a dictionary with two key-value pairs: Page
refers to the current page, while $resourcePath
is the path of the resource. The path is treated as the prefix of the resource to be found, unless it ends with a file extension.
1{{ $resourcePath := "images/feature-image" }}
2{{ $resourceArgs := (dict
3"Page" .
4"resource" $resourcePath
5) }}
6
7{{- $image := partial "claris/_functions/resources/get" $resourceArgs }}
Page Bundles in Hugo
Hugo categorizes Page Bundles into Leaf Bundles and Branch Bundles. Leaf Bundles are directories containing an index.md
file and can include a variety of content and attachments for single pages. Branch Bundles, represented by _index.md
, need to be used for sections and typically only contain non-page resources (source: Hugo Page Bundles).
Headless Bundles
For Branch Bundles, the partial employs a workaround using Headless Bundles. By adding headless: true
to the front matter of an index.md
file within a directory, the directory can host resources similarly to a Leaf Bundle (detailed at Hugo Headless Bundles).
Parameters and Return Values
The partial uses the current page and the resource path as parameters, returning a Hugo resource object or false
if not found.
Resource Handling
Preference is given to page resources, with a fallback to site resources if the desired resource isn’t found in the current page or its ancestors (source: Hugo Page Resources).
Debugging Features
A $debug
variable can be set to true
for insights into the operational flow, aiding in troubleshooting and enhancements.
How to Get This Partial
This partial is part of my Hugo module claris-resources
and hosted on GitHub. To use it in your Hugo website, add the following to your config/_default/hugo.yaml
(or hugo.toml
) file:
1module:
2 imports:
3 - path: github.com/simonheimlicher/claris-resources
Conclusion
This custom Hugo partial offers enhanced resource management, ensuring efficient resource utilization in Hugo websites. Its ability to navigate through different types of Page Bundles and leverage Headless Bundles for Branch Bundles is particularly valuable.
This partial is the result of my continuous experimentation and adaptation to my own use case. Please let me know about [Personal information, requires JavaScript] . I would be happy to further improve it to handle additional use cases.