Layout lookup for Section pages

Oh, that’s interesting. I read Content Section vs Content Type and Assign a Content Type and thought that anything that ends up as something in a section (content/cats/_index.md, content/cats/index.md, content/cats.md, content/cats/siamese.md) automatically has a section of cats unless explicitly overridden. At the very least, I’d expect layouts/section/asdf.html to apply to content/asdf/index.md and content/asdf/_index.md. I put {{ define "content" }}asdfasdfa{{ end }} in it and never saw asdfasdfa show up on http://localhost:1313/asdf/.

Offhand I’m not sure how to rewrite the relevant bits of documentation so others don’t get confused the same way I was, but I’d very, very much appreciate more clarity from this in the official documentation. As far as I can tell staring at Examples: Layout Lookup for Section Pages, my setup should have worked.

Hi @adiabatic, moved your post to a new topic since the old topic was already answered.

As far as your question, once I get back to my laptop I’ll take a look, unless someone else beats me to it.

To start, you would never have both of these, only one

content/asdf/index.md
content/asdf/_index.md

It’s hard to debug with just this snippet. Do you have a project to share?

Sure do.

I don’t understand why I have to put the type: asdf bit in the front matter for content/asdf.md when ‘Section list for “posts” section with type set to “blog”’ in Examples: Layout Lookup for Section Pages seems to suggest that I can put an overriding template in layouts/asdf/single.html and have that template redefine “content” or “endofmain”, but it doesn’t seem to work like that.

I suspect the documentation doesn’t match what Hugo does anymore.

Currently your content and layouts are

├── content
│   ├── _index.md
│   └── asdf.md
├── layouts
│   ├── _default
│   │   ├── baseof.html
│   │   ├── list.html
│   │   └── single.html
│   └── asdf
│       └── single.html

To get page

content/asdf.md

to use layout (by default)

layouts/asdf/single.html

you need to move it under an asdf section as such

content/asdf/asdf.md

While I deeply appreciate your willingness to help me figure out where to place my layouts, I don’t think I’m communicating my underlying problem well enough. What’s bothering me is that I read the docs and yet still came to incorrect conclusions about where I could put a template-layout file that would apply to a given .md file. As someone who likes Hugo and wants others’ Hugo use to be as painless as possible, it bothers me that reading the docs does not appear to be enough to understand where to put template-layout files.

Now, I will be the first person to admit that i sometimes skim documentation all too quickly and miss key bits of information, but after reading the doc pages linked to from my initial post, I’m beginning to think that the documentation isn’t communicating all aspects of the template-layout selection algorithm. As such, I’d like to use this thread to brainstorm ideas to more clearly communicate this very important part of Hugo to new(ish) users.

Of course, I’d be more than happy to contribute doc patches myself once I understand how it all works in all cases, but I’m clearly not there yet.

The docs here say:

Type

Is value of type if set in front matter, else it is the name of the root section (e.g. “blog”). It will always have a value, so if not set, the value is “page”.

content/asdf.md is not under a subdir under content, so unless set, type will be page.

And yet, content/asdf.md gets turned into /asdf/index.html, just as content/asdf/index.md or content/asdf/_index.md do (I can’t find where in the docs it says this happens, but it happens).

Because the generated index.html is in the asdf directory, I figure it has a section of asdf, and therefore layouts/section/asdf.html should apply to it, just like how layouts/section/posts.html is said to apply to “a section list for ‘posts’ section with type set to ‘blog’” in Examples: Layout Lookup for Section Pages.

In retrospect, “I don’t understand why I have to put the type: asdf bit…” is misleading when trying to communicate the main source of my confusion. I should have written “I don’t understand why I have to either move files around or add a type: asdf to make this work” or left that part out entirely.

That is a function of uglyURLs being set to false by default: https://gohugo.io/content-management/urls/#ugly-urls

Given

content
├── bar
│   └── index.md
├── baz
│   └── _index.md
└── foo.md

you will by default get

public
├── bar
│   └── index.html
├── baz
│   └── index.html
├── foo
│   └── index.html
└── index.html

With uglyURLs = true, the same content structure would render:

uglypublic
├── bar
│   └── index.html
├── baz.html
├── foo.html
└── index.html


Expanding on my response above.

From https://gohugo.io/content-management/sections/

A Section is a collection of pages that gets defined based on the organization structure under the content/ directory.

By default, all the first-level directories under content/ form their own sections (root sections).

Whether a page is a section or a regular page depends on the structure in your content, not the generated output. As in my example above, setting uglyURLs = true shows that content/foo.md will be generated at example.com/foo.html: just under the root.

Expanding further:

  1. A page’s type is determined by default by the Section that contains it.

  2. foo.md is a top-level content page; it is not a directory; it is not contained by a sub-directory under content;

  3. Therefore it is not a Section, it is not in a Section;

  4. Therefore foo.md will get the default type value “page”–

  5. –unless specified implicitly in its front matter.

1 Like

Thanks for explaining. Unfortunately, I’m getting mixed signals from Hugo itself for vaguely similar pages:

  • content/asdf.md has a section of <nil> and a type of page, as you said.
    No surprises here.

  • content/aoeu/index.md also has a section of <nil> and a type of page.
    This isn’t what I’d expect given that I’m accessing it as /aoeu/ and index.md is in the aoeu/ directory.

  • content/underscore-ijkl/_index.md straight-up 404s, which is a complete surprise to me. public/underscore-ijkl/ just doesn’t get generated.

  • content/underscore-zxcv-and-friend/_index.md, accessed through /underscore-zxcv-and-friend/, also doesn’t get generated.
    Also, the built-in Hugo browser generates a blank page for this (a 403 page?) instead of the usual 404 page, but that’s not at all important now.

  • content/underscore-zxcv-and-friend/friend.md, accessed through /underscore-zxcv-and-friend/friend/, has a section of and a type of underscore-zxcv-and-friend.
    I’d expect a section of underscore-zxcv-and-friend and a type of page.

  • content/qwer/index.md, accessed through /qwer/, has a section of and a type of page (surprising section, unsurprising type)

  • content/qwer/roommate.md doesn’t generate anything that shows up in public/.

Sample project demonstrating this: more-unpredictable.zip.

Are the .CurrentSection and .Type of all these pages exactly what all the knowledgable users expect? I feel like I’m one of a handful of users getting regularly surprised by how Hugo appears to do things differently than how I’d predict it to do them just by reading the docs.

You have index.md here, which means it is a Leaf Bundle, ie the (single) page bundle version of content/aoeu.md.

content/underscore-ijkl/_index.md is a section. Your config.yaml:

disableKinds:
- section # This is why
- taxonomy
- taxonomyTerm
- RSS
- sitemap

underscore-zxcv-and-friend is the root section under content. Therefore it is also its type, and section.

Again, equivalent to leaf bundle = single page = page bundle version of single top-level page qwer.md

Because content/qwer/index.md is a leaf bundle, page-type resources (eg .md files) under it do not get permalinks: https://gohugo.io/content-management/page-resources/#readout

2 Likes

Thanks a lot for your help. I think it mostly all makes sense now.

…well, that explains a lot of the trouble I’ve been having. I copied over a config.yaml from a site where disabling sections made sense and then relied on sections being there.

After reenabling sections I’m still a little confused by some of what I’m seeing. In particular, this paragraph from https://gohugo.io/content-management/sections/ seems like it’s been misleading me a lot:

By default, all the first-level directories under content/ form their own sections (root sections).

This seems to be true only if there’s a _index.something (with an underscore!) in the first-level directory under content/. If my new, current understanding is correct, wouldn’t it be clearer to say

By default, all the first-level directories under content/ that are branch bundles (i.e. have an _index.md in them) form their own sections (root sections).

Also, if the only way to disable this default behavior is to disable sections entirely, then the following should be even clearer still:

Unless explicitly disabled with disableKinds in the config file, all the first-level directories under content/ that are branch bundles (i.e. have an _index.md in them) form their own sections (root sections).

Are any of these proposed wording changes clearer and truer than what’s there currently? I’d be happy to send in a patch this weekend or shortly thereafter.