Advanced Hugo Menus Multiple Menus

In the documentation for menus, this is provided as an example:

---
menu:
  docs:
    parent: 'extras'
    weight: 20
---

I’ve set up a menus.toml alongside my config.toml. Created a menu.html partial that pulls in the menus, and I have that all working. What I want to accomplish I don’t see in the docs for advanced Hugo menus:

I want a single page of content to display in two different menus. Essentially, I want

  • Parent 1
    • content-page.md
  • Parent 2
    • content-page.md

The content-page.md would display under two menus. Is this currently possible? I know the docs show the example of menu: ["main", "footer"], but that doesn’t work for me as I need to control the weighting of the pages and the parent rather than separate menus (I want the page in two parents in the same menu).

1 Like

Edit: disregard, i misread your question.

No worries. I should have specified that I tried something like this in the frontmatter for a page:

menu:
    MyMenu:
        parent: "parent-1"
        weight: 10
    MyMenu:
        parent: "parent-2"
        weight: 20

All that did was move the content from Parent 1 down to Parent 2.

I wonder if this works: you could try defining your menu in config.toml instead, something like:

[menu]

[[menu.main]]
  identifier = "purple"
  name = "Parent 1"
  url = "/purple/"

[[menu.main]]
  identifier = "red"
  name = "Parent 2"
  url = "/red/"

[[menu.main]]
  identifier = "orange1"
  parent = "purple"
  url = "/orange/"

[[menu.main]]
  identifier = "orange2"
  parent = "red"
  url = "/orange/"
    
1 Like

May need a little more assistance than that. I have something like that set up already. Not sure I’m following the logic of this. What would my shared page point to for the parent?

orange1 and orange2 here would both have the url /orange/. They have different identifier values though, so they are technically two different menu items, with different parents, which just happen to lead to the same url.

So when you generate your menu:

{{ range site.Menus.main }}
  {{.Name}} ({{.URL}})
  {{ if .HasChildren }}
    <ul>
      {{ range .Children }}
      <li>{{.Identifier}} ({{.URL}})</li>
      {{ end }}
    </ul>
    {{ end }}
{{ end }}

You get

Parent 1 (/purple/)
  <ul>
    <li>orange1 (/orange/)</li>
  </ul>

Parent 2 (/red/)
  <ul>
    <li>orange2 (/orange/)</li>
  </ul>
  

I’m obviously missing some critical information to understand this. What would be in the page’s frontmatter? How do I control the weighting for placement? Sure, I can put in your example on the TOML, and it does make the menu as you describe. There’s a gap in my understanding or the docs on how the page’s connect.

Would this mean that the entire menu is set up in the config.toml and there’d be nothing in the frontmatter?

For content/orange/, nothing else that pertains to this particular menu definition.

As described here: Menus | Hugo

You could do it that way, sure.


You have the option of configuring your menu items either in your config or in your frontmatter (or a mix of both).

Having your menu definition in the content frontmatter allows you access to the .Page variable from the menu entry (doc).

The config menu definition allows you to include non-content menu items (eg external links) to your Menu structure.

How you configure your menus is up to your preferences and specific constraints (eg, this example of multi-parent setup)

1 Like

Confusion again: Per the docs, the identifier is the section. I need to have the pages.

For content/orange/ , nothing else that pertains to this particular menu definition.

I don’t understand, I guess.

As described here: Menus | Hugo

Here’s where the docs fail, since this says non-content entries. I do want content entries.

You could do it that way, sure.

The docs aren’t clear enough on how to use menus. There’s no tangible, working example, and I don’t think I recall seeing it explicitly called out that you would do menus solely from your frontmatter. I need every section and page to be in the menu, and that sort of setup isn’t really documented.

The config menu definition allows you to include non-content menu items (eg external links) to your Menu structure.

That isn’t what I want to do though. I want to control the order of the menus, the pages that go within a menu, and the order of the pages within those menus. Ideally, I’d like to have a section (menu) with another section (sub-menu) under that with pages under both sections. I’m still unclear on how to make this happen.

I have made the menus display and using the front matter on a page, I can get the page under a single menu, but that’s only part of what I need to do.

Alright, I’m still confused on some of the items above, but I’ve made progress in my understanding of menus (and if I get time, I’m going to create a PR to update the menu docs for Hugo).

I’m having a new problem that, I believe, if I can get over this hurdle, it should get me 80% of the way to what I’m looking for. It’s a different problem slightly.

{{ range site.Menus.main }}
  {{.Name}} ({{.URL}})
  {{ if .HasChildren }}
    <ul>
      {{ range .Children }}
      <li>{{.Identifier}} ({{.URL}})</li>
      {{ end }}
    </ul>
    {{ end }}
{{ end }}

Based on the above, I want to check on the range whether that page has children that should display at a li under that. I’m trying to make this work based on what @pointyfar provided and what I see as the menu template in the docs, as that somewhat does it.

I suppose I could be looking at this wrong. Guess I want to try to merge together using the menus in the config.toml and the frontmatter.

Quick-ish summary, before I get into your specific questions:

You define your menu structure by defining what menu items belong to your menu.

Given each menu item, you may add it to your menu:

  1. by adding the menu definition in your content files, or

  2. by adding a menu configuration in your config.

If all that belongs to your menu is content, you need not define anything in your config file. You can have all your menu definitions in your content frontmatter.

As you have seen from your experimenting however, this means that while you can attach your one content file to multiple menus, you cannot attach your one content file to the same menu multiple times.

Ie:

Yes:
---
menu:
  firstmenu:
    parent: firstmenuparent
  secondmenu:
    parent: secondmenuparent
---
No:
---
menu:
  firstmenu:
    parent: firstmenuparent
  firstmenu:
    parent: secondmenuparent
---

So. What you want is not the usual case, so what you need to do is not the “usual way”.

Enter the second way of adding menu items.

The second method comes under the header “Add Non-content Entries to a Menu”.

This does not mean that you add only non-content entries. What this means is that if you have menu items that are not attached to a content page (ie external links, which therefore implies no frontmatter), you can still add them to your menus. Do not get over fixated on the “non-content entries” part. This is what this method is able to accommodate, unlike the frontmatter method, but not the only thing it can be used for.

You have the option of defining your entire menu structure in the config, without once touching your content frontmatter, even if all your menu items point to internal pages.

1 Like

I’m looking at a similar situation as this. I’ve toying with the idea of multiple menus, with menus under menus. Is something like that possible?

e.g.,

menu1
    menu2
        content-pages
    menu3
       content-page

Is something like possible? Defining those menus in a menu.toml alongside my config.toml, then having each content page define the menu(s), parent, and weight. Is that something that’s supported in the templating language (still learning that).

No: Menu entry variables | Hugo

.Identifier

string
Value of the identifier key if set for the menu entry. This value must be unique for each menu entry. It is necessary to set a unique identifier manually if two or more menu entries have the same .Name .

As in my summary post above, do not fixate on the “non-content entries” part. It can accommodate non-content entries, as well as content entries. You can think of menu items as just pointers to urls, which can be either internal or external.

The docs have examples for simple cases. These work. What you want, ie multiparent, is not the usual simple case. We cannot document every special usecase that is possible.

Because you don’t have to. You may choose to do so. But you could just as easily define it all in your config. Or do halfsies. Up to your preferences (ie maintainance, practicality etc) and circumstances (ie your specific multiparent setup).

You can do that with either method. Again, have a read here for what menu entry properties you can configure: Menu entry variables | Hugo

1 Like

It’s probably easier if you have a sample project/structure you can share so we know what you are talking about.

I don’t have a sample project I can share. Best I can do is provide you with what I’m trying to accomplish.

As stated above, I want to be able to display a page in multiple locations in the same menu. This apparently is too difficult, so it makes sense to display it in two different menus, as that is how it appears Hugo likes it to work. So I could have menu1 and menu2 and put the same page in both of those. That should work if I can make this work.

Let me be clear that I don’t want my content folder structure to decide the structure of the menus as eventually that same content will be reused in different menu structures depending on paths and audience. Hence why I’ve been looking at the Hugo menus and becoming frustrated with the minimalist documentation.

Here’s what we’re aiming for a menu structure (just throwing in names of things to make it easier to differentiate):

Getting Started
    Setting Up
        Markdown-page1
        Markdown-page2
        Markdown-page3
    Fixing Up
        Markdown-page4
        Markdown-page5
        Markdown-page6
Advanced Tools
    Hammer
        Markdown-page7
        Markdown-page8
    Chisel
        Markdown-page9
        Markdown-page10

In the above, Getting Started and Advanced Tools are top-level. Each would be a separate menu (e.g., the menus would be [[gettingstarted]] and [[advancedtools]].

Setting Up and Fixing Up would also be separate menus ([[settingup]] and [[fixingup]]). These would ideally be displayed below the upper menus of Getting Started and Advanced Tools. Probably through the layout partial for the menu, right?

Then on each markdown page’s front matter, I can specify the menu(s) and the parent. That should mean that I could have a page that lived under Setting Up and under Fixing Up as both of those are separate menus, and I could do the following in the front matter:

---
menu:
  firstmenu:
    parent: firstmenuparent
  secondmenu:
    parent: secondmenuparent
---

Is something like that doable?

Yes, that is what I said in this post above.

Note that AFAIK you cannot nest a Hugo Menu under a parent Hugo Menu. Nesting/Parenting is done by declaring a Menu Item the parent of another Menu Item in the same Hugo Menu.

Of course, in the “generic web dev” sense of the “menu” concept, you can nest whatever you want in whichever you way you want.

Ok. Sounds like all this isn’t going to work quite as we need. Do you happen to have a recommendation on a better approach? Is there some other option?