Tutorial Hugo Data Files: JSON YAML dan TOML untuk Content Management
Tutorial Hugo Data Files: JSON YAML dan TOML untuk Content Management
Hugo data files adalah fitur powerful untuk mengelola external data yang bisa diakses dari templates. Mereka memungkinkan Anda memisahkan data dari content dan menggunakan berbagai format populer.
Apa itu Hugo Data Files?
Definisi
Data files adalah files eksternal (JSON, YAML, TOML, XML) yang disimpan di folder data/ dan bisa diakses dari templates menggunakan site.Data.
Use Cases
- Configuration data: Site settings, API keys
- Reference data: Countries, states, categories
- Dynamic content: Team members, testimonials, pricing
- External APIs: Cache data dari external sources
- Translations: i18n strings
- Navigation: Menu structures
- SEO data: Meta tags configuration
Directory Structure
data/
├── config/
│ ├── site.yaml
│ └── navigation.toml
├── content/
│ ├── team.json
│ ├── testimonials.yaml
│ └── pricing.toml
├── reference/
│ ├── countries.json
│ └── states.yaml
└── i18n/
├── strings.yaml
└── messages.toml
Data File Formats
1. JSON Format
File: data/team.json
{
"members": [
{
"name": "John Doe",
"role": "CEO",
"bio": "Founder dengan 10+ tahun experience",
"image": "/images/team/john.jpg",
"social": {
"twitter": "@johndoe",
"linkedin": "johndoe",
"github": "johndoe"
}
},
{
"name": "Jane Smith",
"role": "CTO",
"bio": "Tech lead dan system architect",
"image": "/images/team/jane.jpg",
"social": {
"twitter": "@janesmith",
"linkedin": "janesmith",
"github": "janesmith"
}
}
]
}
Template:
<section class="team">
<h2>Our Team</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{{ range site.Data.team.members }}
<div class="team-member">
<img src="{{ .image }}" alt="{{ .name }}">
<h3>{{ .name }}</h3>
<p class="role">{{ .role }}</p>
<p class="bio">{{ .bio }}</p>
<div class="social-links">
{{ range $platform, $handle := .social }}
<a href="https://{{ $platform }}.com/{{ $handle }}" class="{{ $platform }}">
{{ $platform }}
</a>
{{ end }}
</div>
</div>
{{ end }}
</div>
</section>
2. YAML Format
File: data/testimonials.yaml
testimonials:
- name: "Sarah Johnson"
role: "Product Manager"
company: "Tech Corp"
quote: "Hugo has transformed our documentation workflow. Build times went from minutes to seconds."
rating: 5
featured: true
- name: "Mike Brown"
role: "Developer"
company: "Startup Inc"
quote: "The simplicity and speed of Hugo is unmatched. Highly recommended!"
rating: 5
featured: false
- name: "Lisa Chen"
role: "CTO"
company: "Enterprise Co"
quote: "We migrated from WordPress and never looked back. Hugo is a game changer."
rating: 4
featured: true
Template:
<section class="testimonials">
<h2>What Our Users Say</h2>
<!-- Featured testimonials only -->
<div class="featured">
{{ range where site.Data.testimonials.testimonials "featured" true }}
<blockquote>
<p>"{{ .quote }}"</p>
<footer>
<strong>{{ .name }}</strong>
<span>{{ .role }}, {{ .company }}</span>
<div class="rating">{{ .rating }}/5 ⭐</div>
</footer>
</blockquote>
{{ end }}
</div>
<!-- All testimonials -->
<div class="all-testimonials">
{{ range site.Data.testimonials.testimonials }}
<div class="testimonial-card">
<p>{{ .quote }}</p>
<div class="author">
<span>{{ .name }}</span>
<small>{{ .role }} at {{ .company }}</small>
</div>
</div>
{{ end }}
</div>
</section>
3. TOML Format
File: data/pricing.toml
[[plans]]
name = "Starter"
price = 0
price_unit = "month"
description = "Perfect for personal projects"
features = [
"1 site",
"100MB storage",
"Community support",
"Basic analytics"
]
highlighted = false
cta_text = "Get Started"
cta_url = "/signup/starter"
[[plans]]
name = "Pro"
price = 29
price_unit = "month"
description = "For professional developers"
features = [
"10 sites",
"10GB storage",
"Priority support",
"Advanced analytics",
"Custom domains",
"Team collaboration"
]
highlighted = true
cta_text = "Start Pro Trial"
cta_url = "/signup/pro"
[[plans]]
name = "Enterprise"
price = 99
price_unit = "month"
description = "For large organizations"
features = [
"Unlimited sites",
"Unlimited storage",
"24/7 phone support",
"Custom integrations",
"SLA guarantee",
"Dedicated success manager"
]
highlighted = false
cta_text = "Contact Sales"
cta_url = "/contact"
Template:
<section class="pricing">
<h2>Simple Pricing</h2>
<div class="pricing-grid">
{{ range site.Data.pricing.plans }}
<div class="plan {{ if .highlighted }}highlighted{{ end }}">
<h3>{{ .name }}</h3>
<div class="price">
<span class="currency">$</span>
<span class="amount">{{ .price }}</span>
<span class="period">/{{ .price_unit }}</span>
</div>
<p class="description">{{ .description }}</p>
<ul class="features">
{{ range .features }}
<li>{{ . }}</li>
{{ end }}
</ul>
<a href="{{ .cta_url }}" class="btn {{ if .highlighted }}btn-primary{{ end }}">
{{ .cta_text }}
</a>
</div>
{{ end }}
</div>
</section>
Advanced Data Usage
1. Nested Data Structures
File: data/navigation.yaml
main_menu:
- title: "Products"
url: "/products"
children:
- title: "Product A"
url: "/products/a"
description: "Description for product A"
- title: "Product B"
url: "/products/b"
description: "Description for product B"
children:
- title: "Feature 1"
url: "/products/b/feature-1"
- title: "Feature 2"
url: "/products/b/feature-2"
- title: "Solutions"
url: "/solutions"
children:
- title: "For Enterprise"
url: "/solutions/enterprise"
- title: "For Startups"
url: "/solutions/startups"
- title: "Pricing"
url: "/pricing"
- title: "About"
url: "/about"
Recursive Template untuk Dropdown Menu:
{{ define "menu-item" }}
<li class="{{ if .children }}has-submenu{{ end }}">
<a href="{{ .url }}">{{ .title }}</a>
{{ with .children }}
<ul class="submenu">
{{ range . }}
{{ template "menu-item" . }}
{{ end }}
</ul>
{{ end }}
</li>
{{ end }}
<nav>
<ul class="main-menu">
{{ range site.Data.navigation.main_menu }}
{{ template "menu-item" . }}
{{ end }}
</ul>
</nav>
2. Data Filtering dan Sorting
Filter by property:
{{ $featured := where site.Data.testimonials.testimonials "featured" true }}
{{ range $featured }}
<div class="featured">{{ .quote }}</div>
{{ end }}
Sort by field:
{{ $sorted := sort site.Data.pricing.plans "price" }}
{{ range $sorted }}
<div>{{ .name }} - ${{ .price }}</div>
{{ end }}
First N items:
{{ $recent := first 3 site.Data.blog.recent_posts }}
{{ range $recent }}
<article>{{ .title }}</article>
{{ end }}
3. Data Transformation
Group by category:
{{ $byCategory := group site.Data.products.items "category" }}
{{ range $byCategory }}
<h2>{{ .Key }}</h2>
{{ range .Pages }}
<div>{{ .name }} - ${{ .price }}</div>
{{ end }}
{{ end }}
4. Conditional Data Display
{{ with site.Data.announcements.active }}
<div class="announcement-bar" style="background-color: {{ .bg_color }}">
<p>{{ .message }}</p>
{{ with .link }}
<a href="{{ .url }}" class="btn">{{ .text }}</a>
{{ end }}
<button class="close">×</button>
</div>
{{ end }}
External Data Integration
1. Get Remote Data (Hugo 0.143+)
Fetch data dari external API:
# hugo.toml
[params.api]
endpoint = "https://api.example.com/data"
Template dengan resources.GetRemote:
{{ $url := "https://api.github.com/repos/gohugoio/hugo" }}
{{ $data := resources.GetRemote $url }}
{{ with $data }}
{{ $json := . | unmarshal }}
<div class="github-stats">
<p>Stars: {{ $json.stargazers_count }}</p>
<p>Forks: {{ $json.forks_count }}</p>
</div>
{{ end }}
2. Build Script untuk Fetch Data
scripts/fetch-data.js:
const fs = require('fs');
const https = require('https');
// Fetch data dari API
https.get('https://api.example.com/data', (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
fs.writeFileSync('data/external/fetched.json', data);
console.log('Data fetched successfully');
});
});
package.json:
{
"scripts": {
"fetch-data": "node scripts/fetch-data.js",
"build": "npm run fetch-data && hugo --gc --minify"
}
}
3. GitHub Actions untuk Data Sync
# .github/workflows/fetch-data.yml
name: Fetch External Data
on:
schedule:
- cron: '0 0 * * *' # Daily at midnight
workflow_dispatch:
jobs:
fetch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run fetch-data
- run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add data/external/
git commit -m "Update external data" || exit 0
git push
Best Practices
1. Data Organization
data/
├── config/ # Site configuration
├── content/ # Content-like data (team, testimonials)
├── reference/ # Lookup data (countries, codes)
├── external/ # Fetched from APIs
└── i18n/ # Translation strings
2. Data Validation
Gunakan JSON Schema untuk validate:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"members": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["name", "role"]
}
}
}
}
3. Data Documentation
Tambahkan comments di data files:
# data/team.yaml
# Team member data
# Updated: 2026-02-03
members:
- name: "John Doe" # Full name
role: "CEO" # Job title
# Bio should be 50-150 characters
bio: "Founder dengan experience..."
4. Environment-Specific Data
# data/config/production.toml
[analytics]
google_id = "GA-PRODUCTION-ID"
# data/config/development.toml
[analytics]
google_id = "GA-DEV-ID"
enabled = false
Troubleshooting
Issue: “Data not found”
Check:
- File path:
data/filename.json(bukandata/filename.yamljika file-nya .json) - Case sensitivity:
team.json≠Team.json - Extension: harus .json, .yaml, .yml, .toml, atau .xml
Issue: “Cannot access data”
Debug:
<!-- Debug output -->
<pre>{{ site.Data | jsonify | safeHTML }}</pre>
<!-- Check specific file -->
<pre>{{ site.Data.team | jsonify | safeHTML }}</pre>
Issue: “Syntax error in data file”
Validate:
# Untuk JSON
jq . data/file.json
# Untuk YAML
yamllint data/file.yaml
# Untuk TOML
python3 -c "import toml; toml.load('data/file.toml')"
Kesimpulan
Hugo data files adalah fitur powerful untuk:
✅ Content Management: Separate data dari content
✅ Dynamic Content: Team, testimonials, pricing
✅ Configuration: Site settings, navigation
✅ Reference Data: Countries, codes, lists
✅ External Integration: APIs, third-party data
✅ i18n: Translation strings
Gunakan format yang sesuai:
- JSON: Data dari APIs, complex structures
- YAML: Human-readable, configuration
- TOML: Simple data, Hugo config style
Artikel Terkait
Link Postingan: https://www.tirinfo.com/tutorial-hugo-data-files/