12.2 Lookup for Single Pages
Right, so you’ve got a piece of content, and Hugo needs to dress it up for the big show. It’s holding a single page, like a blog post or a product detail. It needs to find the right HTML template (a “single” template) to render it. This isn’t a wild guess; it’s a meticulously defined search party that scours your layouts directory following a very specific, hierarchical set of rules. Think of it less like a treasure map and more like a flow chart designed by a very, very precise bureaucrat.
The goal is specificity. Hugo’s philosophy is to start with the most specific template possible for your content and work its way back to a generic fallback. If you have a template that matches your content type and a section, it’ll use that over one that just matches the type. This is brilliant because it gives you immense control without a lot of repetition.
The Default Lookup Order
Here’s the official, step-by-step search path Hugo follows for a single page. It will use the first template it finds, so the list is in order of priority. For a page at content/posts/my-awesome-post.md, Hugo will look for these files in your layouts directory:
layouts/posts/single.html(Section-specific)layouts/posts/single.html(Type-specific, same as above in this case)layouts/_default/single.html(The universal fallback)
Let’s break this down. The posts in that path isn’t arbitrary; it’s the name of the directory (the “section”) where your content lives. So if your post is in content/posts/, Hugo first checks for a template specifically made for the posts section: layouts/posts/single.html. This is your golden ticket. If it finds it, the search stops. This is where you’d put custom styling or unique elements for your blog posts that you wouldn’t want on, say, a product page.
If that doesn’t exist, it looks for a template based on the content’s type front matter. By default, a page’s type is its section. So, our posts/my-awesome-post.md has a type of posts. This means step 2 is, hilariously, looking for the exact same file as step 1: layouts/posts/single.html. This seems redundant until you realize you can break the connection between section and type.
Overriding Type for Precision Control
You can set a type in your content’s front matter that is different from its section. This is where the lookup order gets its real power. Why would you do this? Let’s say you have a section called reviews where you review books, movies, and gadgets. They’re all in the same section for organizational purposes, but you might want them to look different.
You can set the type in the front matter of each:
---
title: "My Review of *The Great Gatsby*"
type: "book" # This overrides the default section-based type
---
Now, for this page, Hugo’s lookup order changes. It will look for:
layouts/reviews/single.html(Section-specific)layouts/book/single.html(Type-specific)layouts/_default/single.html(The universal fallback)
This is incredibly useful. You can have a general template for all reviews at layouts/reviews/single.html (step 1) that handles common review elements, but then create a more specialized template at layouts/book/single.html (step 2) that adds, say, a “Buy on Amazon” link or book-specific metadata. The review for a new TV would bypass the book template and just use the general reviews one. You get shared logic and specific overrides in a clean, predictable way.
The Ultimate Escape Hatch: Layout Front Matter
Sometimes, you have that one weird page that just doesn’t fit the system. A special landing page or a legacy post with a bizarre design. For these, you can just tell Hugo exactly what template file to use, effectively short-circuiting the entire lookup process.
---
title: "My Absolutely Bonkers Page"
layout: "custom-special-layout"
---
With this set, Hugo says, “Okay, you’re the boss,” and goes straight to layouts/_default/custom-special-layout.html or, if you want to be more specific, layouts/posts/custom-special-layout.html. It follows the same section/type rules, but for the filename you specified. Use this power sparingly, or you’ll end up with a mess of one-off templates that are a nightmare to maintain. It’s for emergencies, not standard operating procedure.
The biggest pitfall here is not understanding the hierarchy and creating a template in the wrong spot. If you create layouts/_default/single.html and wonder why your fancy layouts/posts/single.html isn’t being used, it’s because Hugo found the fallback first. The lookup order is a cascade; you have to place your templates higher in the list to override those below. My advice? Always start with your _default/single.html to establish a baseline. Then, as you need more specific designs, create the section-specific or type-specific overrides. This way, you’re building on a solid foundation instead of fighting against an invisible one.