Render Multiple Content Types in One Loop with Hugo
Hugo has a way of creating views for content types that can be rendered anywhere on the site. Today I learned that if a template cannot be found, then no error occurs. Frustrating to debug but a useful feature once figured out. Using this knowledge, I have created a way to show only certain types of content in my homepage feed without complicated logic.
Current solutions
I currently have three content types: blogs, projects, and quotes. On my feed, I only want to highlight the blog posts and quotes. Suggestions online required additional logic that I think would get complicated over time.
One of the solutions is to only render if a certain type is found:
<ul>
{{ range .Site.Pages.ByPublishDate }}
{{ if or (eq .Type "blog") (eq .Type "quote")}}
<li>{{ .Title }}</li>
{{end}}
{{ end }}
</ul>
As I start adding more post types then I think I will struggle to maintain this list of types.
My solution
Using the 'no error' feature to .Render
a specific content view
means that I can create a folder structure that determines rendering. We'll call
the view we want to render summary. We can then update the layouts folder
for each content type to have a summary.html template.
layouts/
├── _default
│ ├── single.html
├── blog
│ ├── single.html
│ └── summary.html
├── projects
│ ├── single.html
├── quote
├── single.html
└── summary.html
Now that the blog
and quote
types have a summary template, we can update the
logic from the Current Solution example.
{{ range .Site.Pages.ByPublishDate }}
{{ .Render "summary" }}
{{ end }}
What happens when this runs? All of the content pages are loaded into the
range
but only the blog
and quote
types are actually rendered.