Hugo Image Strategy: Page Bundles vs. Global Assets
Learn when to use Page Bundles versus the global assets directory in Hugo to optimize image processing, reduce duplication, and improve site performance.
07 Mar 2026, 20:45 UTC

The most common performance bottleneck in Hugo sites is the misuse of the static/ directory. Files placed in static/ are copied verbatim to the output; they cannot be resized, converted to modern formats like WebP, or fingerprinted for cache busting. To leverage Hugo's image processing engine, you must choose between Page Bundles and the global assets pipeline.
The decision rests on a single constraint: does the image belong to one specific piece of content, or is it shared across the site?
Decision Matrix: Resource Location
| Feature | Page Bundles (Page Resources) | Global Assets (assets/) |
|---|---|---|
| Storage Location | Same folder as index.md |
Root assets/ directory |
| Access Method | .Resources.GetMatch |
resources.Get |
| Lifecycle | Tied to the page (deleted with page) | Independent site-wide asset |
| Primary Use Case | Article screenshots, diagrams, covers | Logos, avatars, shared UI icons |
| Processing Cache | Cached per page resource | Processed once, referenced globally |
Page Bundles for Content-Scoped Imagery
Page Bundles (specifically leaf bundles) store images in the same directory as the Markdown file. This creates a strong logical link between the content and its dependencies. When you move or delete a post folder, the associated images move with it, preventing the "orphan file" problem common in large sites.
Because these are Page Resources, they are accessed via the page context. This allows you to use pattern matching (e.g., finding any file starting with "cover") rather than hardcoding filenames in your front matter.
Global Assets for Shared Elements
The assets/ directory is the global pipeline. If an image—such as a company logo or a recurring author headshot—appears on every page, placing it in a Page Bundle would require duplicating the file across every folder or using complex cross-page references. By using assets/, Hugo processes the image once and serves the same optimized version to every template.
Implementation Example
To use these features, you must use the Hugo Extended version. Standard Hugo lacks the imaging libraries required for advanced processing. The following implementation should be placed in your layout files (e.g., layouts/_default/single.html).
{{/* 1. Process a Page Bundle image (e.g., a cover photo) */}}
{{ with .Resources.GetMatch "cover.*" }}
{{ $img := .Resize "800x" }}
<img src="{{ $img.RelPermalink }}" width="{{ $img.Width }}" height="{{ $img.Height }}" alt="Page Cover">
{{ end }}
{{/* 2. Process a Global Asset (e.g., site logo) */}}
{{ with resources.Get "img/logo.png" }}
{{ $logo := .Resize "200x 100x" }}
<img src="{{ $logo.RelPermalink }}" alt="Site Logo">
{{ end }}
Verification and Diagnostics
To verify that images are being processed rather than simply copied, perform these checks:
- Check Version: Run
hugo versionin your terminal. Ensure the output includesextended. - Inspect the Cache: Run
hugoand check theresources/_gendirectory. If your images appear here with modified filenames (hashes), Hugo is successfully processing them. If the directory is empty, yourGetMatchorGetpaths are incorrect. - Validate Dimensions: Compare a file in
static/with a processed resource. The processed resource should have the exact pixel dimensions specified in the.Resizemethod, whereas the static file will remain at original size. - Test Build Speed: Run the
hugocommand twice. The second run should be significantly faster because Hugo reuses the processed images from the resource cache.
Limitations and Risks
- Cross-Bundle References: Page Bundle images cannot be easily referenced by other pages. Attempting to do so often leads to file duplication. If an image is needed in more than one place, move it to
assets/. - Cache Growth: The
resources/_genfolder can grow very large on image-heavy sites. It is safe to delete this folder to clear the cache, but doing so will increase the time of the next build. - Static Folder Conflict: Avoid placing the same image in both
static/andassets/. This creates duplicate URLs and confuses browser caching.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.