Hosting My Own Things, part 4


This is a post in the Hosting My Own Things series:



Well, it hasn’t been six years! It’s been a little less than a year since my last blog post, and I finally spent some time figuring out a decent way to get image galleries working. I’ve gone back and edited the posts that should have had image galleries to add them. Hugo has some pretty sweet image resizing tricks up it’s sleeve. A big thanks to Christian Specht’s post for getting me going in the right direction.

Here’s the solution I landed on. If you want to see what it looks like, my Trip to Kaua’i post is a good example. In my content/posts directory, I create a new directory for the post, say 2016-01-07-trip-to-kauai and the structure looks like this:

posts
  └── 2016-01-07-trip-to-kauai
      ├── img
      │   ├── 01.jpg
      │   ├── 02.jpg
      │   ├── 03.jpg
      │   ├── 04.jpg
      │   ├── 05.jpg
      │   ├── 06.jpg
      │   ├── 07.jpg
      │   ├── 08.jpg
      │   ├── 09.jpg
      │   ├── 10.jpg
      └── index.md

The index.md bit seems to be nessesary to create the Hugo page bundle. This contains my post, like this:

---
title: Trip to Kaua’i
author: Mitchell Scott
type: post
date: 2016-01-08T04:03:52+00:00
url: /2016/01/trip-to-kauai/
categories:
  - My Own Words

---
These photographs document the Scott family trip to Kaua’i.
Click on a picture to enlarge.

{{< gallery >}}

The {{< gallery >}} tag is the shortcode to trigger the gallery logic.

The gallery shortcode gets defined in /layouts/shortcodes/gallery.html. Here’s what that looks like:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.1/css/lightbox.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.1/js/lightbox.min.js"></script>

<div class="container">
<ul class="image-gallery">
{{ $image := (.Page.Resources.ByType "image") }}
{{ with $image }}
    {{ range . }}
    <li>
    {{ $resized := .Fill "350x270 q100" }}
        <a href="{{ .Permalink }}" data-lightbox="x" data-title="{{ with .Exif }}{{ .Tags.ImageDescription }}{{ end }}"><img src="{{ $resized.Permalink }}" /></a>
    {{ end }}
    </li>
{{ end }}
</ul>
</div>

I’ve added a little bit to Christian’s example, mainly adding <ul class="image-gallery"> and the associated <li> bits. This is becasue I wanted to get the images in the post to a FlexBox layout. I added the following SCSS for that to the _base.scss for the theme I’m using:

.image-gallery {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 5px;
	>li {
		flex-basis: 196px;
	}
	li {
    list-style-type: none;
		img {
			object-fit: cover;
			max-width: 100%;
			height: auto;
			vertical-align: middle;
		}
	}
}

Overall, I’m very happy with this solution. The image order is set by the filenames, in lexicographic order (so 10.jpg comes before 2.jpg for example), I solved this by prepending with zeros. It also takes the description field from EXIF and uses it as the image description in Lightbox.

Aside from the gallery work, I’ve make some tweaks to the Tale theme and I’m pretty happy with how the blog looks now. I also have Continuous Deployment hooked up. Once I do a git push to GitHub, a GitHub Action runs that builds a Docker image and pushes it to the GitHub Container Registry. After that, another Action runs that bumps the image tag in my main Kubernetes infrastructure-as-code repository that contains the manifests for all of my applications. Once that git push runs, GitHub pokes a webhook in my Kubernetes cluster that triggers Flux to run its reconciliation. The nice part about this workflow is GitHub doesn’t need any access into Kubernetes. This whole process takes about 4 minutes from my pushing content to the new container taking traffic.