Show Photo EXIF Data in Hugo

Having used Wordpress for years, I have gown accustom to posting photos in a very graphical manner. I had also written a plugin that would effectively allow me to insert images, and the interesting bits of the image’s EXIF data would automatically appear below the image. Coming to Hugo, not only did I have to get a better understanding of how images are handled, I also had to figure out how to bring the interesting bits of the EXIF data with me.

Why Show Metadata?

I’ve been asked by a few people why I’m so keen on showing metadata on my photos. I think the answer lies in the idea that I really like to understand how a photo was taken, so seeing metadata of other photos helps me learn. I also like going back over my photos and seeing what camera I used, or what aperture I used to take the photo. It helps me remember the moment.

I’m not a professional. I take and share photos for my own edification. I’m trying to learn, so anything I can do to further that learning, I’m interested.

EXIF Support in Hugo

I was delighted to see that Hugo has built-in support for EXIF data. And thankfully, it seems to do most of the hard work for us. This is great, as EXIF data is pretty complicated to parse.

The easiest path forward is to utilize a Hugo shortcode template. These small snippets can be placed right in your markdown files, and when the processing logic builds your site, they will be replaced with whatever you define them as. What’s more, they can take parameters.

So, for all my images, I wrote a shortcode that takes in the image source file, the alternate text (what gets displayed if the image cannot be shown), and the title. The image title for me is something which goes below the image. If I don’t specify a title, it will use the alt text I specify.

The shortcode looks something like this:

{{< img src="/path/to/image.jpg" alt="good image descrpition" title="Descriptive title" >}}

This tells Hugo to process this specific line through the shortcode named img and provide it three parameters – src, alt and title.

Writing an Image Shortcode for EXIF Data in Hugo

So how does one define a shortcode in Hugo? It’s actually very simple. Just create a directory in your layouts directory names shortcodes. Any file in this folder with a <name>.html name will define a shortcode called <name>.

So for example, I create a file named img.html and put the following template inside.

  <img src="{{$src}}" {{ with .Get "alt" }}alt="{{.}}"{{ else }}alt=""{{end}}>
    <div class="image_title">
      {{ with .Get "title" }}
        {{ . }}<br/>
      {{ else }}
        {{ with .Get "alt" }}{{ . }}<br/>{{ end }}
      {{ end }}
    <div class="image_meta">
      {{ with $src.Exif }}
        {{ with .Tags.Model }} {{ . }} {{ end }} 
        {{ with .Tags.FocalLength }}@ {{ . }}mm {{ end }}
        {{ with .Tags.ExposureTime }} &mdash; {{ . }} sec {{ end }}
        {{ with .Tags.FNumber }} , &fnof;/ {{ . }} {{ end }}
        {{ with .Tags.ISOSpeedRatings }}, ISO {{ . }} {{ end }}
      {{ end }}

Now, wherever I use this image shortcode, I’ll automatically get an HTML <figure>, with a properly formatted <figcaption> section displaying both the title, and the image metadata such as camera model, focal length, etc…

There are also classes defined, so I added the following customized CSS to my theme:

.image_title {
    font-size: 2.2rem;
    line-height: 2.8rem;
    margin: 10px auto;

.image_meta {
    font-size: 1.6rem;
    line-height: 2.4rem;
    font-style: italic;

If you’ve created your own theme, I’m going to assume you know how to add additional CSS, and you probably have a better understanding on how you want to style this then I do. If you’re using a pre-made theme, you’ll need to consult with your specific theme’s documentation regarding adding custom CSS. Most themes I’ve seen do allow for this, but they all handle it slightly differently.

In the end, you should have a beautiful image, with appropriate metadata such as what follows.

Looking up at a tree with a beautiful blue sky
Beautiful sky
iPhone 8 Plus @ 6.6mm — 1/340 sec , ƒ/ 2.8 , ISO 20