As I’ve added more posts to charliehowlett.co.uk, the site has gradually accumulated lots of screenshots, photos, and short animations. I usually upload whatever media files I have available without first optimising them for web, which can increase site size and negatively impact page load times. At first I thought to simply enable the img-bot GitHub action to automatically optimise images, but unfortunately the service’s free tier does not extend to private repositories. So I spent some time implementing my own automatic image optimisation process.
Measuring the problem
The first step was setting up some metrics to measure the problem and see how my subsequent work impacted it. I added a GitHub Actions workflow that builds the site on every push, measures the generated public directory, and writes a row to metrics/site-size.csv on a separate metrics branch. Each row records the commit, total bytes, media bytes, file count, and post count. This should help me keep an eye on the site’s performance in the future.
This also made it easy to identify the largest assets and decide where optimisation would have the biggest impact.
Optimising images
The first optimization I considered was serving resized image variants. Before this change a phone (which has a smaller screen and does not need very high resolution images) would be sent the same large JPEG or PNG that I had exported at a resolution suitable for desktop viewing.
To support that, I added a shared responsive-image.html partial and wired it into both Hugo’s Markdown image render hook and the image shortcode. For normal raster images, the partial creates a <picture> element with WebP variants at appropriate display widths, while keeping the original file as a fallback.
The GIF problem
The biggest remaining issue was animated GIFs. Several posts use them for short demonstrations because they are easy to embed, but some are poorly converted MP4s and unnecessarily large. The worst example was nearly 25 MB for a single file showing a short animation.
I used Codex to help identify the largest served assets and convert the GIFs to more appropriate formats. The replacements were much smaller. In one case, an animation went from 25.0 MB to 2.8 MB.
Result
Together, these changes produced a clear reduction in generated site size:
I’m happy with the improvement, and the site is now set up to benefit from automated optimisation as it continues to grow.