Skip to content

Serve resized WebP images and lazy-load them - #193

Closed
bendichter wants to merge 1 commit into
mainfrom
image-pipeline
Closed

bendichter wants to merge 1 commit into
mainfrom
image-pipeline

Conversation

@bendichter

Copy link
Copy Markdown
Contributor

Images are served at the size they were uploaded. The news cards on the home page load about 6 MB of banners for 300 px slots, the Team page loads a 9.8 MB headshot, and no image on the site is lazy-loaded.

This mounts static/images as assets/images so templates can use Hugo's image processing without moving any files. A new partial, img-src.html, takes an image path and a maximum width and returns the URL of a WebP version scaled down to that width. It returns the original URL for anything it cannot improve: remote URLs, SVG, GIF, files under 20 KB, and cases where the WebP would be larger. The 60 template images whose source comes from front matter now use it with a width chosen for each slot, and a render hook applies it to Markdown images. All of them are lazy-loaded except the banner at the top of event and news pages. Source images are untouched, so adding an image works as before.

The 186 images it converts go from 90 MB to 8 MB. Counting the images each page loads, the home page goes from 7.2 MB to 0.9 MB and the Team page from 20.7 MB to 3.4 MB.

To check that nothing moves, I rendered all 155 pages at 1280 px and 400 px wide before and after and compared the rendered size of every image, 2,750 in total. They match except for 1 px of rounding on four images. The site builds on Hugo 0.128.0 and 0.152.2, and the processing adds about 4 seconds to a build.

Two CSS selectors matched images by file name including .png. They now match without the extension so they still apply to the converted files.

This does not cover images written as raw <img> HTML in Markdown (25 of them), CSS background images, or GIFs.

🤖 Generated with Claude Code

Images are stored at their original size in static/images and were served that way, so the news cards on the home page loaded about 6 MB of banners for 300 px slots and the Team page loaded a 9.8 MB headshot. No image on the site was lazy-loaded.

static/images is now also mounted as assets/images, which lets templates run images through Hugo's image processing. A new partial, img-src.html, returns a WebP version of a PNG or JPEG, scaled down to the width the slot needs, and falls back to the original URL for anything it cannot improve (remote URLs, SVG, GIF, small files, or a WebP that would be larger). The 60 template images that take their source from front matter use it with a width chosen for each slot, and a render hook applies it to Markdown images. All of them except the banner at the top of event and news pages are lazy-loaded.

Two CSS selectors matched images by file name including the .png extension. They now match on the name without the extension so they keep applying to the converted files.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for nwborg ready!

Name Link
🔨 Latest commit 3aff33f
🔍 Latest deploy log https://app.netlify.com/projects/nwborg/deploys/6ac922e6aef43d0008993be7
😎 Deploy Preview https://deploy-preview-193--nwborg.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@bendichter

Copy link
Copy Markdown
Contributor Author

Superseded by #207, which combines this with the related PRs. The commits here are included there unchanged.

@bendichter bendichter closed this Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant