Redefining blocks in page paths outputs a blank site

Hello!

I have the following folder structure in my project:

content/
├── red-style/
│   └── _index.md
└── green-style/
    └── _index.md

layouts/
├── red-style/
│   └── baseof.html
├── green-style/
│   └── baseof.html
└── baseof.html

The theme of the site is mostly in a blue color, except for the localhost/red-style and localhost/green-style subpages, which have a seperate baseof.html that overwrites parts of the “blue” baseof.html.

Ever since 0.146.0 this approach no longer works and just outputs a blank html page (even with the old layout-folder structure).

Did I miss some breaking changes or is this a bug?

hugo v0.148.2-40c3d8233d4b123eff74725e5766fc6272f0a84d+extended windows/amd64 BuildDate=2025-07-27T12:43:24Z VendorInfo=gohugoio

You can find my repository under: https://github.com/MinecraftTAS/minecrafttas.com/tree/main/layouts
With the “red-style” being named “tas-battle” and “green-style” being “tas-comp”

I haven’t looked at your repo yet, but the structure you describe above works as expected with v0.148.2. Try it:

git clone --single-branch -b hugo-forum-topic-55456 https://github.com/jmooring/hugo-testing hugo-forum-topic-55456
cd hugo-forum-topic-55456
hugo && grep -r "base template" public
hugo server

I tested your project with both v0.145.0 and v0.146.0 and I see the difference you describe.

layouts/
├── _default/
│   ├── baseof.html
│   ├── list.html
│   └── single.html
├── s1/
│   └── baseof.html
└── index.html

With v0.146.0 public/s1/index.html is blank.

The layouts/s1/baseof.html template looks something like this:

{{ define "style" }}
	...
{{ end }}
{{ define "logo" }}
	...
{{ end }}
{{ define "potionicon" }}
	...
{{ end }}

Although it is a base template, it is not a stand-alone base template, and the demonstrated v0.145.0 behavior is:

  1. layouts/s1/baseof.html is applied to single.html and list.html
  2. layouts/baseof.html is applied to the result

This allows you to redefine blocks in one base template with blocks defined in a base template with higher specificity. I didn’t know this was even possible with v0.145.0 and earlier, but I can see how this construct this is very useful.

Not sure what to do about this yet…

Right? This is super useful! Was this an unintended feature in the previous templating engine?

Well, as far as I can tell it was not documented, but the way it works seems like an intended feature. So… not sure.

Alright, I will downgrade to 0.145.0 for the time being or redo my styles… Thank you for your time!

With v0.146.0 and later you can define templates to be symmetrical with a page’s logical path, so it seems like we’d need to recursively apply base templates going from most to least specific. For example:

content/
├── s1/
│   ├── s2/
│   │   ├── s3/
│   │   │   ├── _index.md
│   │   │   └── p1.md 
│   │   └── _index.md
│   └── _index.md
└── _index.md
layouts/
├── s1/
│   ├── s2/
│   │   ├── s3/
│   │   │   ├── p1/
│   │   │   │   └── baseof.html  <-- step 1: apply to layouts/page.html
│   │   │   └── baseof.html      <-- step 2: apply to result of step 1
│   │   └── baseof.html          <-- step 3: apply to result of step 2
│   └── baseof.html              <-- step 4: apply to result of step 3
├── baseof.html                  <-- step 5: apply to result of step 4
└── page.html

That makes my head hurt.

@bep

Disregard.

When you have a moment, please begin reading this thread starting at this comment.

We lost an undocumented (but useful) capability with the new template system introduced in v0.146.0. Is this something we want to restore? Note my previous comment about recursive application of higher specificity base templates.

I’ve spot-checked our documentation going back to v0.54.0 and cannot find any reference to this capability, nor could I find any reference to it in GitHub issues or PRs.

Over the years I have looked at the source for hundreds of sites, and have never seen this used before. I don’t think the absence of this capability affects many sites; if it had it seems like we would have heard about it shortly after the release of v0.146.0.

I spent several hours this morning investigating this construct in v0.145.0 and concluded that it was an unintended behavior of the previous templating engine.

While it coincidentally works for your site, it fails with basic test cases.

You need to refactor your templates. You can have multiple base templates, but only the most specific will be applied.

2 Likes

Alright, I will do that. Thanks again for checking!

1 Like

Here is the refactor I came up with:

TL;DR of this topic: I’ve been using an unintended feature from the old templating engine, that has been “fixed” in v0.146.0, hence it outputs a blank site.

I have refactored my layouts folder like this:

layouts
├── _partials
│   ├── list.html
│   └── single.html
├── red-style
│   ├── list.html
│   └── single.html
├── green-style
│   ├── list.html
│   └── single.html
├── baseof.html
├── list.html
└── single.html

layout/baseof.html

While layouts/baseof.html has my main html, theme specific parts are marked as a block, something like this:

{{ block "style" .}}
	{{ $sass := resources.Get "/scss/main_blue.scss"}}
	{{ $style := $sass | css.Sass }}
	<link rel="stylesheet" href="{{ $style.Permalink }}" />
{{ end }}

{{ block "main" .}}
{{ end }}

green-style/list.html

Now in the green-style page path, I can redefine the block with my main_green.scss:

{{ define "style" }}
	{{ $sass := resources.Get "/scss/main_green.scss" }}
	{{ $style := $sass | css.Sass }}
	<link rel="stylesheet" href="{{ $style.Permalink }}" />
{{ end }}

_partials/list.html

But now I have a duplicate list.html and single.html in root, green, red and any future page paths that I want to add.
And for that I extract all my list and single specific code as partials, in this case
layouts/_partials/list.html and layouts/_partials/single.html:

<section>
	<article>
		<p>My cool list!</p>
	</article>
<sections>

Redefining everywhere

Now I can add this partial in every list template and just changing the partial will update the layouts in all page paths while keeping the specific list.html code relatively short:

root/baseof.html

{{ block "style" .}}
	{{ $sass := resources.Get "/scss/main_blue.scss"}}
	{{ $style := $sass | css.Sass }}
	<link rel="stylesheet" href="{{ $style.Permalink }}" />
{{ end }}

{{ block "main" .}}
{{ end }}

root/list.html

{{define "main"}}
	{{ partial "list.html" .}}
{{end}}

green-style/list.html

{{ define "style" }}
	{{ $sass := resources.Get "/scss/main_green.scss" }}
	{{ $style := $sass | css.Sass }}
	<link rel="stylesheet" href="{{ $style.Permalink }}" />
{{ end }}

{{define "main"}}
	{{ partial "list.html" .}}
{{end}}

red-style/list.html

{{ define "style" }}
	{{ $sass := resources.Get "/scss/main_red.scss" }}
	{{ $style := $sass | css.Sass }}
	<link rel="stylesheet" href="{{ $style.Permalink }}" />
{{ end }}

{{define "main"}}
	{{ partial "list.html" .}}
{{end}}

root/_partials/list.html

<section>
	<article>
		<p>My cool list!</p>
	</article>
<sections>

If I have to change something in the list, I use _partials/list.html, if I add a new page path like yellow-style I can just copy the list.html and single.html to the new folder and just change the css for the new style!

Where there is a will, there is a way

All of this can be found on my repo with “red-style” being named “tas-battle” and “green-style” being named “tas-comp”

3 Likes

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