Help Wanted: Method names re. sections

First: I’m going to deprecate .Site.Sections – even if it is going to be painful. I have stepped lightly around that code for a while now, but I think now is the time to do something about it. Sections are taxonomies, which made sense when @spf13 created them (easy to implement), but now it is filled with restrictions.

To the questions. To fill the gap, I’m adding another method, thinking:


Without any argument it will behave like .Site.Sections (but return an ordered list type, i.e. not a map).

.Site.GetSections "blog"

Will get the subsections below “blog” etc.

Note that to get a specific section (which is a Page), you do:

.Site.GetPage "section" "blog"

Does the name .GetSections sound OK? Note that .Sections is taken until we remove it …


I for one, support this change. The new method is more meaningful and yet simple.

Since .GetPage is already there.GetSections looks just fine. And one can understand that its scope will be broader.

I think so, and it mirrors .GetPage nicely.

So, to take an example from my blog, where I currently use this:

{{ with (index (shuffle $.Site.Sections.quotes) 0) }}
  {{ .Content }}
  — {{ .Title | safeHTML }}

I’ll need to replace it with this, correct?

{{ with (index (shuffle ($.Site.GetPage "section" "quotes").Pages) 0) }}
  {{ .Content }}
  — {{ .Title | safeHTML }}

And testing for the existence of a top-level section would be in .Site.GetSections "quotes" instead of .Site.Sections.quotes? Or would it have to be in (.Site.GetSections) "quotes"?; I’ve never quite figured out the rules about when arguments are gobbled up by the first function and you have to use parens to disambiguate.


Testing for a top-level section could use both I guess:

{{ with $.GetPage "section" "quotes" }}
{{ .Title }}
{{ end }}

On an added note, I think I’m going to do a “hard deprecation” of .Sections; making bot structures work side-by-side is too much work. I will let .Sections return an empty map and write a detailed ERROR log statement with upgrade instructions.

Surprisingly, it looks like that only breaks 8 themes in the gallery.


1 Like

I have changed my mind vs sections etc.


  • .Site.Sections is deprecated so cannot use that right now.
  • Add .Sections to Page (only set in section pages).
  • Add .Parent to Page (only set in section pages).
  • Add a Home shortcut, so to get to the top level sections you would do .Site.Home.Sections
  • To get a specific section you would use .Site.GetPage "section" "blog" etc.
  • In Hugo 0.23 we can make .Site.Sections work like expected.

This way it is almost nothing new to learn.


Awesome! This is what I was trying to articulate in the other thread, at least if my inferences are correct.

Is the idea as folllows:

  1. becomes a section and we no longer need to distinguish between section/subsection/etc?
  2. .Sections on Page refers to, for example, with content/blog/vacations/, both vacations and blog? I assume .Parent in this case would point to vacations

The idea is that a Page is a Page is a Page. Which can be a section.

The whole idea of this exercise, i.e. nested sections, is to create a proper tree that “kind of” matches what you see on disk. So at some point, to get some benefits from this, you must at least mentally, have a tree structure in mind when creating your templates.

So .Sections refer to the sections below the current page.

Your example isn’t even a proper section, but let us make it one:


With the above as the only content in the site, you would have 3 sections: blog > [vacations, trump].

  • So .Site.Home.Sections (note that this will be simpler once we get to use the .Site.Sections) => 1 section = blog
  • $blogSection := .Site.GetPage "section" "blog" will always return 1 page, in this case the section “blog”.
  • $blogSection.Sections => 2 sections = trump, vacations.
  • (.Site.GetPage "section" "blog" "vacations").Parent.Parent => Home

My only question left (before I start thinking more), is: Should .Section return blog for all the pages in the sections above? This would typically be used in where clauses on the home page, so I’m tempted to say yes: You would like to get both vacations and Trump stuff without making it any harder. So .Section = the first folder, so to speak, like it is today.

Was that clearer?

I think so, yes.

Yes. Thank you for the explanation :smile: Just to repeat the tree for what follows:

Would it be possible–assuming that every dir with an is a section–to do the following? Very similar to yours but just one tweak at the end, plus some additional notation for my own knowledge:

  • .Site.Home.Sections => blog, trump, vacations (I’m noting your comment about it being simple once we get to use .Site.Sections)
  • $blogSection := .Site.GetPage "section" "blog" returns all associated with blog/, including all pages under both vacations and trump (i.e., $blogSection.Pages and $blogSection.RegularPages). So then as a consequence, a layout at layout/blog/list.html with range .Data.Pages would also include all pages under trump and vacations (i.e., 8 pages total).

I’d actually like @budparr 's thoughts on this since he’s the guru on creating relationships between content types:

If everything with an is a section, does it make more sense—or is it possible without breaking every Hugo site—to use .GetPage "section" "vacations" instead? Then you can check for .Parent using with, etc; e.g., breadcrumbs spring to mind here. This would mean that moving sections of content within source org could be done independently of the templating since .Site.GetPage "section" "blog" "vacations" is tethered to directory structure.

What would it return when “vacations” is not unique? Suppose you have /steve/vacations and /mary/vacations.


@rdwatters I have read your post twice, and I don’t get it. But I’m pretty sure that my model is solid (I’m not making changes that makes me guess where to look for stuff, where is that vacation section again? Oh, there its is …).

Curses. Foiled again :wink:

Perhaps the second argument is optional, similar to the rel functions when there are multiple .md with the same file name…

[[EDIT: by “second argument” I mean passing in the second section (i.e., subsection)]]

Yes, I spent some time today fixing the relref func.; it is still ambigous, but at least now it works, and it is 80x faster.

1 Like

Right, but the idea is that Hugo would find it. So I think you mean you’re not making changes that would make the generator guess where a specific directory is, no?

Plus, @jgreely already pointed out the gaping, obvious flaw in what I outlined above. (Feeling a bit sheepish.)

Everything else SGTM and I think is better/more intuitive than previous convos re: underscores, etc. Thanks again, @bep.

1 Like

Seriously? WOW. Nice!

The lookup time went from about 8000 nanoseconds to 100 nanoseconds for a site with 1000 regular pages. 1 second is 1000000000 nanosecond, so these are small numbers – but it adds up.

1 Like

I would rather have the user tell me where it is. And understand this: In 99,99% of the use cases, there is no need to do .GetPage "section" "mumbo" "jumbo". You just start from the top and walk down the tree. Totally safe for changes. The GetPage approach is for the @jgreely of the world. And myself.

1 Like