Hugo Page Bundles: Asset Management Modern untuk Content
Hugo Page Bundles: Asset Management Modern untuk Content
Page Bundles adalah fitur powerful di Hugo untuk mengorganisir content dan assets bersama-sama dalam satu folder. Ini adalah best practice untuk modern content management.
Apa itu Page Bundles?
Definisi
Page Bundle adalah folder yang berisi file content Markdown (biasanya index.md) bersama dengan assets terkait (images, files, data) dalam satu lokasi.
Why Page Bundles?
- Co-location: Assets bersama dengan content
- Resource Management: Akses ke Hugo image processing
- Clarity: Struktur yang jelas dan terorganisir
- Portability: Mudah move content dengan assets-nya
- Version Control: Track changes untuk content + assets
Types of Page Bundles
1. Leaf Bundle (index.md)
Single page dengan resources:
content/posts/my-awesome-post/
├── index.md # Content file
├── featured.jpg # Featured image (page resource)
├── gallery/
│ ├── image-1.jpg
│ ├── image-2.jpg
│ └── image-3.jpg
├── diagram.png
└── attachment.pdf
Frontmatter di index.md:
---
title: "My Awesome Post"
date: 2026-02-03T10:00:00+07:00
draft: false
resources:
- name: featured
src: featured.jpg
params:
credits: "Photo by John Doe"
- name: gallery
src: gallery/**
---
Content goes here...
2. Branch Bundle (_index.md)
Section dengan content dan sub-pages:
content/blog/ # Branch bundle
├── _index.md # Section content
├── _index.jpg # Section featured image
├── my-post-1/ # Leaf bundle
│ ├── index.md
│ └── featured.jpg
└── my-post-2/ # Leaf bundle
├── index.md
└── featured.jpg
_index.md:
---
title: "Blog"
description: "Latest articles and tutorials"
cascade:
featured_image: _index.jpg
---
Welcome to our blog!
Resource Management
1. Accessing Resources in Templates
Single resource:
{{ $image := .Resources.GetMatch "featured.jpg" }}
{{ if $image }}
{{ $resized := $image.Resize "800x" }}
<img src="{{ $resized.RelPermalink }}" alt="{{ .Title }}">
{{ end }}
Multiple resources (glob patterns):
{{ $images := .Resources.Match "gallery/*.jpg" }}
<div class="gallery">
{{ range $images }}
{{ $thumb := .Resize "300x200" }}
<img src="{{ $thumb.RelPermalink }}" loading="lazy">
{{ end }}
</div>
By name:
{{ $featured := .Resources.Get "featured" }}
{{ $gallery := .Resources.Match "gallery/**" }}
2. Resource Properties
{{ $image := .Resources.GetMatch "*.jpg" }}
{{ if $image }}
<figure>
<img src="{{ $image.RelPermalink }}"
width="{{ $image.Width }}"
height="{{ $image.Height }}"
alt="{{ $image.Title }}">
<figcaption>
{{ $image.Params.credits }}
({{ $image.Width }}x{{ $image.Height }}px, {{ div $image.Size 1024 }}KB)
</figcaption>
</figure>
{{ end }}
3. Image Processing
{{ $image := .Resources.GetMatch "featured.jpg" }}
{{ if $image }}
{{ $original := $image }}
{{ $resized := $image.Resize "800x webp" }}
{{ $small := $image.Resize "400x webp q60" }}
{{ $large := $image.Resize "1200x webp" }}
<picture>
<source media="(min-width: 800px)" srcset="{{ $large.RelPermalink }}">
<source media="(min-width: 400px)" srcset="{{ $resized.RelPermalink }}">
<img src="{{ $small.RelPermalink }}" alt="{{ .Title }}">
</picture>
{{ end }}
Frontmatter Resource Definitions
1. Named Resources
---
title: "Post Title"
resources:
- name: "header"
src: "images/header.jpg"
title: "Header Image"
params:
credits: "Photo by Jane Doe"
- name: "diagram"
src: "diagram.png"
params:
alt: "System architecture diagram"
- name: "downloads"
src: "downloads/*"
---
2. Resource Parameters
{{ $header := .Resources.Get "header" }}
{{ if $header }}
{{ with $header.Params.credits }}
<p class="photo-credits">Photo: {{ . }}</p>
{{ end }}
{{ end }}
3. Glob Patterns
---
resources:
- name: "gallery"
src: "gallery/*.jpg"
- name: "all-images"
src: "**/*.jpg"
- name: "documents"
src: "*.pdf"
---
Practical Examples
Example 1: Blog Post dengan Gallery
Content structure:
content/posts/bali-travel-guide/
├── index.md
├── featured.jpg
├── gallery/
│ ├── beach-1.jpg
│ ├── beach-2.jpg
│ ├── temple.jpg
│ └── sunset.jpg
└── map.pdf
index.md:
---
title: "Bali Travel Guide: 7 Days Itinerary"
date: 2026-02-03
draft: false
resources:
- name: "featured"
src: "featured.jpg"
params:
caption: "Beautiful sunset at Uluwatu"
- name: "gallery"
src: "gallery/**"
---
Explore Bali with this comprehensive 7-day itinerary...
## Photo Gallery
{{ < gallery > }}
## Download Map
[Download Detailed Map]({{ < resource "map.pdf" > }})
Gallery shortcode:
{{ $images := .Page.Resources.Match "gallery/*" }}
<div class="masonry-grid">
{{ range $images }}
{{ $thumb := .Resize "400x300" }}
{{ $full := .Resize "1200x800" }}
<a href="{{ $full.RelPermalink }}" data-lightbox="gallery">
<img src="{{ $thumb.RelPermalink }}" loading="lazy">
</a>
{{ end }}
</div>
Example 2: Tutorial dengan Code Files
content/tutorials/hugo-basics/
├── index.md
├── hugo.toml
├── config.yaml
└── tree.txt
index.md:
---
title: "Hugo Basics Tutorial"
type: "tutorial"
resources:
- name: "config-toml"
src: "hugo.toml"
- name: "config-yaml"
src: "config.yaml"
---
## Configuration
### TOML Format
{{ < code-file resource="config-toml" lang="toml" > }}
### YAML Format
{{ < code-file resource="config-yaml" lang="yaml" > }}
Example 3: Product Page dengan Assets
content/products/software-tool/
├── index.md
├── hero.jpg
├── features/
│ ├── screenshot-1.jpg
│ ├── screenshot-2.jpg
│ └── screenshot-3.jpg
├── videos/
│ └── demo.mp4
└── datasheet.pdf
index.md:
---
title: "Software Tool Pro"
price: 99
resources:
- name: "hero"
src: "hero.jpg"
- name: "screenshots"
src: "features/*.jpg"
- name: "demo-video"
src: "videos/demo.mp4"
- name: "datasheet"
src: "datasheet.pdf"
---
Product description here...
Cascade dengan Resources
Inheriting Resources di Sections
---
title: "Tutorials"
resources:
- name: "section-banner"
src: "banner.jpg"
cascade:
resources:
- name: "watermark"
src: "../watermark.png"
---
Resources akan tersedia untuk semua pages dalam section.
Content Organization Best Practices
1. Naming Conventions
✅ GOOD:
content/posts/
├── 2026/
│ ├── 01-january/
│ │ └── my-post/
│ │ ├── index.md
│ │ └── featured.jpg
│ └── 02-february/
│ └── another-post/
│ ├── index.md
│ └── featured.jpg
❌ AVOID:
content/posts/my-post.md
static/images/my-post-image.jpg
2. Asset Organization
content/posts/
└── my-post/
├── index.md
├── featured.jpg
├── assets/
│ ├── diagram-1.png
│ ├── diagram-2.png
│ └── chart.svg
├── downloads/
│ ├── whitepaper.pdf
│ └── checklist.pdf
└── gallery/
├── photo-1.jpg
├── photo-2.jpg
└── photo-3.jpg
3. Resource Metadata
---
resources:
- src: "*.jpg"
name: "photo-{{ .counter }}"
params:
photographer: "John Doe"
license: "CC BY-SA"
---
Troubleshooting
Issue: “Resource not found”
Check:
- File extension case:
.jpg≠.JPG - Path relatif ke index.md
- File ada di folder page bundle
# Check resources untuk page
hugo server -D
# Buka: http://localhost:1313/__hugo/resrc/
Issue: “Cannot resize resource”
Pastikan:
- Hugo Extended terinstall
- File adalah image yang valid
- Format supported (JPG, PNG, GIF, WebP)
Issue: “Glob pattern not working”
Gunakan pattern yang benar:
# Benar
resources:
- src: "gallery/*.jpg" # Semua JPG di gallery/
- src: "**/*.jpg" # Semua JPG di semua subfolder
- src: "*.pdf" # Semua PDF di root bundle
Performance Tips
1. Image Optimization
# hugo.toml
[imaging]
quality = 80
resampleFilter = "lanczos"
2. Lazy Loading
<img src="{{ $resized.RelPermalink }}"
loading="lazy"
decoding="async"
alt="{{ .Title }}">
3. Resource Caching
# Hugo caches processed resources
# Clear cache jika perlu:
hugo --gc
Migration ke Page Bundles
From Traditional Structure
Before (Traditional):
content/posts/my-post.md
static/images/posts/my-post/
├── featured.jpg
└── gallery/
└── images.jpg
After (Page Bundle):
# 1. Buat folder
mkdir content/posts/my-post
# 2. Move content
mv content/posts/my-post.md content/posts/my-post/index.md
# 3. Move images
mv static/images/posts/my-post/* content/posts/my-post/
# 4. Update image paths di content
# Ganti /images/posts/my-post/ dengan . (relative)
Script untuk Bulk Migration
#!/bin/bash
# migrate-to-bundles.sh
POSTS_DIR="content/posts"
IMAGES_DIR="static/images/posts"
for post in "$POSTS_DIR"/*.md; do
basename=$(basename "$post" .md)
# Buat bundle folder
mkdir -p "$POSTS_DIR/$basename"
# Move post
mv "$post" "$POSTS_DIR/$basename/index.md"
# Move images jika ada
if [ -d "$IMAGES_DIR/$basename" ]; then
mv "$IMAGES_DIR/$basename/"* "$POSTS_DIR/$basename/"
rmdir "$IMAGES_DIR/$basename" 2>/dev/null
fi
done
Kesimpulan
Page Bundles memberikan:
✅ Organization: Assets bersama content
✅ Portability: Move content dengan semua assets
✅ Image Processing: Hugo resources API
✅ Version Control: Track semua dalam Git
✅ Clarity: Struktur yang jelas dan scalable
Gunakan page bundles untuk semua content baru dan pertimbangkan migrasi content existing untuk better asset management.
Artikel Terkait
- Cara Setup Image Optimization di Hugo dengan WebP dan Responsive Images
- Panduan Lengkap Membuat Website dengan Hugo dan Tailwind CSS 2026
- Best Practices Structuring Content Hugo untuk SEO Maksimal
- Hugo Shortcodes Lengkap: Membuat Components Reusable
- Tutorial Hugo Data Files: JSON YAML dan TOML untuk Content Management
Link Postingan : https://www.tirinfo.com/hugo-page-bundles-asset-management/