Multi-level branch bundle works but doesn't use corresponding level layouts

I have a simple demo of multi-level branch bundles with corresponding layouts, but I can’t get Hugo to use the sub-section layouts. Here is a git repo (based on one that jmooring whipped up in response to an earlier related query).

simple git repo for demo

To summarize, given the following content and layouts

➜  content git:(main) ✗ tree
.
├── _index.md
├── about
│   ├── _index.md
│   ├── projects
│   │   ├── _index.md
│   │   ├── icedig
│   │   │   ├── img
│   │   │   │   └── icedig.png
│   │   │   └── index.md
│   │   └── mudwrap
│   │       ├── img
│   │       │   └── mudwrap.jpg
│   │       └── index.md
│   └── publications
│       └── _index.md
└── philosophy
    └── _index.md

➜  layouts git:(main) ✗ tree
.
├── _default
│   ├── baseof.html
│   ├── home.html
│   ├── list.html
│   └── single.html
├── about
│   ├── list.html
│   ├── projects
│   │   ├── list.html
│   │   └── single.html
│   └── single.html

Hugo ignores projects/list.html and projects/single.html, instead using about/list.html and about/single.html. How can I nudge Hugo to utilize the second level layouts under the projects folder?

Hugo’s automatic template selection (see lookup order) does not support nested directories in the layouts directory. You can:

  1. Specify a layout in front matter, or
  2. Specify a layout in a section’s _index.md file and cascade the value down the tree, or
  3. Specify a layout in your site configuration using a cascade array, targeting a given path

Same options for type in front matter.

Thanks for this very helpful tip. I (unsuccessfully) tried your method #2

Specify a layout in a section’s _index.md file and cascade the value down the tree

by specifying like so in about/projects/_index.md frontmatter

layout = 'about/projects/list.html'

That doesn’t work. My additional doubt is regarding where to specify the about/projects/single.html layout that I would like to be used for all the entries under projects? Doing so in each entry would be quite tedious, no?

I think you’re missing the “cascade the value down” bit.

https://gohugo.io/content-management/front-matter/#front-matter-cascade

ok, I’ve spent almost two days now experimenting with various permutations and combinations of #1 and #2 above but have achieved no success. I don’t even know how to begin with #3 (some examples would be great). In any case, given the following

➜  hugo-layouts git:(main) ✗ tree content
content
├── _index.md
├── about
│   ├── _index.md
│   ├── projects
│   │   ├── _index.md
│   │   ├── icedig
│   │   │   ├── img
│   │   │   │   └── icedig.png
│   │   │   └── index.md
│   │   └── mudwrap
│   │       ├── img
│   │       │   └── mudwrap.jpg
│   │       └── index.md
│   └── publications
│       └── _index.md
└── philosophy
    └── _index.md

8 directories, 9 files
➜  hugo-layouts git:(main) ✗ tree layouts
layouts
├── _default
│   ├── baseof.html
│   ├── home.html
│   ├── list.html
│   └── single.html
├── about
│   ├── list.html
│   ├── projects
│   │   ├── list.html
│   │   └── single.html
│   └── single.html
├── partials
└── shortcodes

I would like to configure it so all content under projects uses the layouts under layouts/about/projects and everything else to follow the standard Hugo order. I just can’t figure out how to coax Hugo to do this. My example git repo. Help, hints, examples will be most welcome as I can’t make any progress by myself and the existing Hugo docs/examples. Thanks.

See https://github.com/punkish/hugo-layouts/pull/1

see update below

I think I finally understand how Hugo layouts lookup works (thanks jmooring). For the benefit of others, here is a summary that is more vividly displayed by the linked github repo

  • For the most part, the directory layouts of the content and the layouts folders mirror each other. If there is a match between the two, Hugo uses the corresponding layout. But there is a major caveat – Hugo doesn’t look past the second-level of the layouts folder, and falls back to the _default/<list|single>.html layouts.
  • There is another significant caveat – any layout other than the specially called <list|single>.html need to have unique names.

Consider the following folders

➜  hugo-layouts git:(main) ✗ tree content
content
├── _index.md
├── about
│   ├── _index.md
│   ├── projects
│   │   ├── _index.md
│   │   ├── icedig
│   │   │   ├── img
│   │   │   │   └── icedig.png
│   │   │   └── index.md
│   │   └── mudwrap
│   │       ├── img
│   │       │   └── mudwrap.jpg
│   │       └── index.md
│   └── publications
│       └── _index.md
└── philosophy
    └── _index.md
➜  hugo-layouts git:(main) ✗ tree layouts
layouts
├── _default
│   ├── baseof.html
│   ├── home.html
│   ├── list.html
│   └── single.html
├── about
│   ├── list.html
│   ├── projects-list.html
│   ├── projects-single.html
│   └── single.html
├── partials
└── shortcodes

content/about/_index.md uses layouts/about/list.html but content/about/projects/_index.md cannot access layouts/about/projects/list.html (which would be a third-level layout; remember, Hugo ignores everything below the second level). Additionally, the list and single layouts for the entries in the projects section have unique names (projects-<list|single>.html) which are, in turn, specified in the frontmatter of the corresponding files like so

# projects/_index.md
[cascade]
layout = 'projects-list'


# projects/<icedig|mudwrap>/index.md
layout = 'projects-single'

The one bummer seems to be that while the projects-list value can be cascaded down to all _index.md children of projects, the projects-single value has to be specified in each of the entries under projects (such as icedig and mudwrap).

Hope this helps someone else looking for similar answers.

update

So, it turns out that if you declare a cascading type value, and have corresponding second-level layout <list|single>.html, Hugo will indeed use them, and there will be no need to declare layout in each <sub-section>/index.md. So, the following would also work, but note that the layouts for projects have to be at the second-level under the layouts directory even though projects is a third-level entry under the content directory.

➜  hugo-layouts git:(main) ✗ tree content
content
├── _index.md
├── about
│   ├── _index.md
│   ├── projects
│   │   ├── _index.md
│   │   ├── icedig
│   │   │   ├── img
│   │   │   │   └── icedig.png
│   │   │   └── index.md
│   │   └── mudwrap
│   │       ├── img
│   │       │   └── mudwrap.jpg
│   │       └── index.md
│   └── publications
│       └── _index.md
└── philosophy
    └── _index.md
➜  hugo-layouts git:(main) ✗ tree layouts
layouts
├── _default
│   ├── baseof.html
│   ├── home.html
│   ├── list.html
│   └── single.html
├── about
│   ├── list.html
│   └── single.html
├── projects
│   ├── list.html
│   └── single.html
├── partials
└── shortcodes

and

# projects/_index.md
[cascade]
    type = 'projects'

Thanks jmooring

The other option is to specify “type” in front matter, and cascade that down.

do you mean like so?

# content/about/projects/_index.md
[cascade]
layout = 'projects-list'
type = 'projects'

I tried that but that must not be it – it doesn’t work as content/about/projects/<icedig|mudwrap>/index.md get rendered with _default/single.html instead of about/project-single.html.

If you specify type, you don’t necessarily need to specify layout.

content/something/foo/_index.md

[cascade]
type = 'whatever'

The children will then layouts/whatever/list.html and layouts/whatever/single.html.

You can also cascade the value down from your site configuration, using the target keyword to target paths.

Thanks, I just checked and that also works. And yes, it is simpler. I have marked your last post as the “solution” but I wish I could add a “tips and tricks” tag to my detailed entry.

(weird though that I have to explicitly declare all entries under the projects folder as type: 'projects' when they are also implicitly so by virtue of being inside the projects folder.)

In my view, this really should be documented somewhere easy to find by future users.

Many thanks again for all your help.

The default for a page’s .Type is the name of the top level section, not the current section, and there’s a Very Good Reason for that.

I am sure there is a Very Good Reason, and it is probably documented somewhere also. But I didn’t/couldn’t find it, so mentioning that somewhere prominently would be greatly helpful. That, along with the tidbit that Hugo doesn’t look beyond the second-level of layouts…

in any case, I hope my write-up (with your invaluable tips) helps others.

I’m not sure this is prominent, but…

https://gohugo.io/content-management/types/

image

If you feel strongly about this, please raise an issue here:
https://github.com/gohugoio/hugoDocs/issues

or, if not set, the first directory in the file path

While the above does mention how content type is determined, it is now that I know that Hugo doesn’t look beyond the second-level that the phrase “the first directory” makes sense to me. But, as I mentioned, it is not just this by itself. It is this fact in conjunction with the fact that Hugo doesn’t look beyond the second-level layouts is what is relevant and important in what I was trying to solve.

Perhaps it is not something that others face. But if there is someone who wants to implement what I was trying to do, then the explanation I tried to provide above could be helpful.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.