Best way to adapt to new template system when using Page.Type

Prior to hugo 0.146, we were extensively using type front-matter on our section pages to drive various pieces of navigation rendering. after migrating to the new template system, i see that type is used to determine the layout used which is breaking all of our section pages. i am trying to figure out if there is a way to update our layouts to approximate the previous behavior so we do not need to refactor all of our other components.

consider the following files:

$ cat content/docs/_index.md
---
...
type: directory
---
Foo
$ cat content/help/_index.md
---
...
type: directory
---
Bar

prior to 0.146, these would render using layouts/docs/section.html and layouts/help/section.html , respectively.

post 0.146, these now both only seem to render using layouts/directory/section.html (or in our case it was falling back to the default layouts/list.html ) which results in unexpected behavior.

is there any way to override this behavior or refactor our layouts to have preserve the path specific behavior? i tried a few different ways like layouts/directory/docs/section.html but they didn’t work

The type front matter field has always set the top level section to which the page belongs, and consequently, which template was used if you had a non-default template for that section (e.g., type = 'foo' would use layouts/foo/single.html).

If you want to use type for something other than its documented purpose, you can place it under the params key in front matter.

---
title: Example
params:
  type: foo
---

Does that answer your question?

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

thanks for getting back so quickly! strangely this has never impacted our rendering and i’ve validated this all the way up to 0.145.0.

(a small clarification, prior to the upgrade testing we did not have a file located at layouts/directory/section.html, this is just something i was testing to see how to influence the rendering behavior)

this is effectively what we had before:

layouts/docs/section.html

layouts/help/section.html

layouts/_default/list.html

and rendering occurred as expected. after upgrading to 0.146, rendering of content/docs/_index.md now falls to the default layouts/_default/list.html (i have also tried migrating this to the new suggested location of layouts/list.html) but it is still falling back to this default which was unexpected.

the changes describe in the relevant PR made it sound like this was new/modified behavior but understand that may not have been the correct read:

To find the best matching template, we walk from the root down to the page’s Path. The distance is measured in directory levels from the page Path up to the template path.

Set in type front matter key. For template lookups, this effectively changes the root directory of Page.Path.

regarding moving to custom parameters, it sounds like we may have been relying on a feature of hugo in an unexpected way, but moving this particular capability to custom parameters would require touching of all the relevant section content and theme so was hoping to avoid it if at all possible

it’s not fully clear to me why prior to 0.146 this correctly resolved to the named page path but in 0.146+ it does not. it seems like if we don’t have an overriding type directory the layout discovery should still prioritize path over defaults:

layout/<type>/section.html
layout/<path>/section.html
layout/section.html
layout/list.html

was this an intentional change to no longer consider layout/<path>/section.html when type is set?

note: if i comment out type in my front-matter it correctly resolves to layout/<path>/section.html (but consequently breaks other parts of our theme due to references to .Type)

I can reproduce the behavior you’re describing with this test case:

git clone --single-branch -b hugo-forum-topic-56719 https://github.com/jmooring/hugo-testing hugo-forum-topic-56719
cd hugo-forum-topic-56719
hugo server

(Note: The template used to render each page is displayed in red at the top of the screen for easy identification.)

The lookup logic changed between versions when the front matter type doesn’t match a specific layouts subdirectory:

Hugo Version Fallback Behavior
v0.145.0 and earlier Falls back to the page’s section, then finally to the default layout.
v0.146.0 and later Falls back immediately to the default layout, skipping the section lookup.

I suspect this change in the lookup priority was unintentional.


@bep Please comment before I create a GitHub issue.


EDIT: As I think about this, the new behavior is arguably what you want anyway. If I tell Hugo this a β€œfoo” content type, and a layouts/foo/section.html file doesn’t exist, falling back to the default seems like the least surprising behavior.

1 Like

@dlch,

Regardless of whether this is a bug, you should not use the type field for something other than its intended purpose. I recognize that moving this under params generates some work for you, but it is the right way to do it. A careful regex replacement in VS Code or similar should allow you to make this change pretty quickly.

@jmooring thanks for the quick reproduction! i really appreciate the support.

at the very least seems like it was a breaking change that can hopefully be called out more explicitly if it’s going to remain. if the old behavior can’t/won’t be restored, it would be great if there could still be a way to have have layouts that are customized on both type and path like layouts/<type>/<path>/section.html for more specific configuration.

on your second point, even if this is determined to be a bug and fixed i agree we’ll want to look at removing our dependency on this capability. the change is relatively straight forward like you mentioned to do in bulk but we have some internal content validation tooling that will require a little more work to untangle. i am hoping to decouple these efforts so we can get hugo up to the latest and then separately revisit if we even want our navigation to function as it does today based on .Type (or .params.type)

To clarify, a params.type front matter field does not and will not have any affect on template selection.

If you are suggesting that we use layouts/<type>/<section>/section.html (e.g., layouts/directory/docs/section.html), where <section> is the top level content directory, that’s not going to happen.

that was just a suggestion as an alternative, potentially more β€œintuitive” hierarchical discovery (given your concern that the previous behavior may not have been as intuitive), only if the previous hierarchical discovery behavior won’t be fixed

1 Like

@jmooring just wanted to follow up on this one, is the best next step to open an issue on the main hugo repo?

If you open an issue I would vote to close it. Yes, the behavior changed, but (a) in my view the change was for the better (least surpising) and (b) you can place the type key under the params key in front matter.

Thanks for the feedback, i’ll still go ahead and open an issue in case any one else runs in to this issue; even if it is decided as a β€œwon’t fix” , it can hopefully at least be used as an opportunity to document this as a breaking change

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