Creating a WordPress-style archive view in Hugo for better content organization.
Introduction
As the clock ticks down on 2024, I thought I’d sneak in one last blog post. This time, I’m sharing my recent adventure in customizing Hugo’s archive view. Before my latest tinkering, my blog’s archive layout looked pretty basic.
Here’s what the homepage overview looked like:
And when visiting the archives page, you’d see just a plain list of posts. Functional, sure, but I wanted something more visually engaging—something akin to WordPress-style archiving that breaks posts down by year and month, with a handy post count for each month.
The WordPress style I had in mind looks something like this:
I decided to roll up my sleeves and see if I could recreate this structure in Hugo.
The Plan
Hugo’s flexibility and the Stack theme by CaiJimmy made this a fun challenge. Since I’m using the theme as a Git submodule, I had to create the necessary customizations outside the theme’s directory to keep my setup clean and maintainable.
Create an Archive Page
Setting up an archive page is straightforward! Follow these steps:
Navigate to the content folder in your Hugo site.
Create a new folder named archives.
Inside the archives folder, create a file called archives.md.
The first step was to create a new archive.html file under <site-root>/layouts/partials/widget/. This file contains the logic for grouping posts by year and month and displaying the post counts.
{{- $query := first 1 (where .Context.Site.Pages "Layout" "==" "archives") -}}
{{- $context := .Context -}}
{{- $limit := default 5 .Params.limit -}}
{{- if $query -}}
{{- $archivesPage := index $query 0 -}}
<sectionclass="widget archives"><divclass="widget-icon"> {{ partial "helper/icon" "infinity" }}
</div><h2class="widget-title section-title">{{ T "widget.archives.title" }}</h2> {{ $pages := where $context.Site.RegularPages "Type" "in" $context.Site.Params.mainSections }}
{{ $notHidden := where $context.Site.RegularPages "Params.hidden" "!=" true }}
{{ $filtered := ($pages | intersect $notHidden) }}
{{ $archives := $filtered.GroupByDate "2006" }} <!-- Grouping by year --><divclass="widget-archive--list"> {{ range $index, $item := first (add $limit 1) ($archives) }}
{{- $id := lower (replace $item.Key " " "-") -}}
<divclass="archives-year"><ahref="{{ $archivesPage.RelPermalink }}#{{ $id }}"> {{ if eq $index $limit }}
<spanclass="year">{{ T "widget.archives.more" }}</span> {{ else }}
<spanclass="year">{{ .Key }}</span><spanclass="count">({{ len $item.Pages }})</span> {{ end }}
</a></div><divclass="archives-months"><ul> {{ $months := $item.Pages.GroupByDate "January" }} <!-- Grouping by month --> {{ range $month := $months }}
<li><ahref="{{ $archivesPage.RelPermalink }}#{{ $id }}-{{ lower (replace $month.Key """-")}}"><spanclass="month">{{ $month.Key }}</span><spanclass="count">({{ len $month.Pages }})</span></a></li> {{ end }}
</ul></div> {{ end }}
</div> {{ if gt (len $archives) $limit }}
<divclass="pagination"> {{ $previous := (index $archives 0) }}
{{ $next := (index $archives 1) }}
<spanclass="prev"> {{ if $previous }}<ahref="{{ $archivesPage.RelPermalink }}#{{ lower (replace $previous.Key """-")}}">Previous</a>{{ end }}
</span><spanclass="next"> {{ if $next }}<ahref="{{ $archivesPage.RelPermalink }}#{{ lower (replace $next.Key """-")}}">Next</a>{{ end }}
</span></div> {{ end }}
</section>{{- else -}}
{{- warnf "Archives page not found. Create a page with layout: archives." -}}
{{- end }}
2. Updating the Default Archive Page
Next, I customized the default archives layout file: <site-root>/layouts/_default/archives.html. This file handles rendering the main archive page structure and ensures the new widget integrates seamlessly.
After implementing these changes, the archive view now displays posts grouped by year and month, with a clear count of posts for each month.
Conclusion
Thanks to Hugo’s flexibility and some help from GitHub Copilot, I managed to create a clean, WordPress-style archive view that makes navigating my posts a breeze. If you’re looking to customize your Hugo site, don’t hesitate to experiment—it’s incredibly rewarding!
Let me know your thoughts or share how you’ve customized your Hugo setup in the comments below.