# Menu from Front Matter (+ multi-level)

**URL:** <https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204>\
**Category:** support\
**Created:** [November 9, 2018, 11:42am UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204 "2018-11-09T11:42:49Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![iBasher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/ibasher/32/6157_2.png) [@iBasher](https://discourse.gohugo.io/u/iBasher)\
**Post date:** [November 9, 2018, 11:42am UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/1 "2018-11-09T11:42:49Z")

</div>

I need to make a post navigation menu, and it is different for every single post, so I can`t just use regular Hugo menus.

I think that one approach for that is to use Front Matter in this way:

```
navigation:
- src: '#first'
  name: First 
- src: #second
  name: Second

```

And then just range it:

```
{{ range .Params.navigation }}
    <li>
        <a href="{{ .src }}">{{ .name }}</a>
    </li>
{{ end }}

```

But I don`t know how to make this menu multi-level.  
I think I should set a parent in Front Matter, but how to properly display that parent-child relationship in layouts template?

```
    <li>
        <a>Top-level</a>        
    </li>
    <li>
        <a>Top-level, parent</a>
        <ul>
            <li>
                <a>Submenu, child</a>
            </li>
        </ul>
    </li>
```

---

<div class="post-metadata">

**Author:** ![Leo\_Merkel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/leo_merkel/32/3321_2.png) [@Leo\_Merkel](https://discourse.gohugo.io/u/Leo_Merkel)\
**Post date:** [November 9, 2018, 12:18pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/2 "2018-11-09T12:18:44Z")

</div>

Did you read [https://gohugo.io/templates/menu-templates/](https://gohugo.io/templates/menu-templates/)? Should answer all your questions.

---

<div class="post-metadata">

**Author:** ![iBasher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/ibasher/32/6157_2.png) [@iBasher](https://discourse.gohugo.io/u/iBasher)\
**Post date:** [November 9, 2018, 2:10pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/3 "2018-11-09T14:10:55Z")

</div>

I did. But looks like {{ if .HasChildren }} / {{ range .Children }} doesn`t work with Front Matter menus.  
Not sure or it is because it works only with .Site menus, or something else is on my way…

Front Matter:

```
navigation:
  basics:
    name: Basics
    src: '#basics'
  controls:
    name: controls
    src: '#controls'
    parent: basics

```

template:

```
{{ range .Params.navigation }}
    {{ if .HasChildren }} has children {{end}} /* no reaction */
{{end}}
```

---

<div class="post-metadata">

**Author:** ![iBasher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/ibasher/32/6157_2.png) [@iBasher](https://discourse.gohugo.io/u/iBasher)\
**Post date:** [November 19, 2018, 3:44pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/4 "2018-11-19T15:44:21Z")

</div>

Is it even possible to create nested menu from Front Matter?

---

<div class="post-metadata">

**Author:** ![pointyfar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pointyfar/32/5797_2.png) [@pointyfar](https://discourse.gohugo.io/u/pointyfar)\
**Post date:** [November 19, 2018, 10:57pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/5 "2018-11-19T22:57:26Z")

</div>

> [@iBasher](#):
>
> Is it even possible to create nested menu from Front Matter?

> [@iBasher](#):
>
> looks like {{ if .HasChildren }} / {{ range .Children }} doesn`t work with Front Matter menus.

Both should work fine. You just need to define your menus in the front matter as in the docs linked above:

```auto
menu:
  docs:
    title: "how to use menus in templates"
    parent: "templates"
    weight: 130

```

In the above example from the docs, the page containing that front matter definition would have its own menu item as a child of the `templates` menu item. Assuming no other parent defined on the `templates` page, the `templates` page would then be the top level menu item of the `docs` menu, ie `.Site.menus.docs`.

> [@iBasher](#):
>
> ```md
> navigation:
> basics:
> name: Basics
> src: '#basics'
> controls:
> name: controls
> src: '#controls'
> parent: basics
> 
> ```

Your example front matter does not seem to be defined as a menu, so menu-specific properties such as `.HasChildren` would not work: [Menu entry variables | Hugo](https://gohugo.io/variables/menus/#menu-entry-functions) .

---

<div class="post-metadata">

**Author:** ![iBasher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/ibasher/32/6157_2.png) [@iBasher](https://discourse.gohugo.io/u/iBasher)\
**Post date:** [November 20, 2018, 11:42am UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/6 "2018-11-20T11:42:18Z")

</div>

Thanks for the explanation, but it is still a bit confusing.  
I have changed front matter to this state:

```
menu:
  templates:
    title: "templates"
  docs:
    title: "Documentation"
    parent: "templates"

```

Now when i do **{{ range .Site.Menus.docs }}** i can get the Docs menu item as a child, but the parent field is empty:

```
<ul class="top-level">              
    <li>
        <a href="#"></a>
    </li>
    <ul class="sub-menu">            
        <li>
        <a href="/blog/dota2-guide/">Documentation</a>
        </li>            
    </ul>   
</ul>

```

And if i do **{{ range .Site.Menus.templates }}** i get only Templates menu item as parent, with no children

---

<div class="post-metadata">

**Author:** ![pointyfar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pointyfar/32/5797_2.png) [@pointyfar](https://discourse.gohugo.io/u/pointyfar)\
**Post date:** [November 20, 2018, 10:44pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/7 "2018-11-20T22:44:21Z")

</div>

Hi,

So, the `templates` parent here would be a different menu item (ie different page) whose identifier or title is `template`.

something like:

```auto
# content/lorem.md:
menu: 
  mymenu:
    title: "lorem"
    parent: "ipsum"

```

```auto
# content/ipsum.md:
menu: 
  mymenu:
    title: "ipsum"

```

`.Site.Menus.mymenu` would have `ipsum` as a top level menu item, and `lorem` as its child menu item.

Your above example, as you have found, puts that page in two menus: `.Site.Menus.templates` and `.Site.Menus.docs`.

You need to go to whichever page should be the parent menu item, and ‘attach’ it to the relevant menu.

---

<div class="post-metadata">

**Author:** ![iBasher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/ibasher/32/6157_2.png) [@iBasher](https://discourse.gohugo.io/u/iBasher)\
**Post date:** [November 21, 2018, 9:38am UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/8 "2018-11-21T09:38:12Z")

</div>

Ok, now that’s make sense. But apparently I forgot to clarify that I need links leading to the same page.

> [@pointyfar](#):
>
> So, the `templates` parent here would be a different menu item (ie different page) whose identifier or title is `template`

This approach forces me to create other pages, while I only need to create links to anchor on same page(i.e. navigation inside of content of one particular post):

```
# content/longread.md

<nav>
    <a href="#part1"...
    <a href="#part2"...

<content>
    <h2 id="part1">
    <h1 id="part2">...

```

---

<div class="post-metadata">

**Author:** ![pointyfar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pointyfar/32/5797_2.png) [@pointyfar](https://discourse.gohugo.io/u/pointyfar)\
**Post date:** [November 21, 2018, 10:52pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/9 "2018-11-21T22:52:21Z")

</div>

> [@iBasher](#):
>
> links leading to the same page.

Oh, ok. Hmm, I’m not sure then that the front matter menu is the best approach.

Option 1: you could define everything in your `config.toml` file instead like here: [Menus | Hugo](https://gohugo.io/content-management/menus/#add-non-content-entries-to-a-menu)

So something like (untested)

```auto
menu:
  main: 
    - name: longread
      url: "/longread/"
    - name: partone
      url: "/longread#part1"
      parent: longread
    - name: parttwo
      url: "/longread#part2"
      parent: longread

```

Or Option 2: you build custom navigation from `.Params` in front matter. Note that you would not have .HasChildren (and other menu-specific variables) available, so you would have to treat these as regular (ie non-menu) front matter.

---

<div class="post-metadata">

**Author:** ![aklahoti](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/aklahoti/32/11550_2.png) [@aklahoti](https://discourse.gohugo.io/u/aklahoti)\
**Post date:** [June 25, 2020, 5:31pm UTC](https://discourse.gohugo.io/t/menu-from-front-matter-multi-level/15204/10 "2020-06-25T17:31:07Z")

</div>

I have generated my [blog website](https://codingnconcepts.com/) using Hugo and created a multi-level menu structure.

> **[Add Sub Menu in Hugo Website](https://codingnconcepts.com/hugo/nested-menu-hugo/)**
>
> Guide to create a nested menu structure in your Hugo website.

I use tags to map my posts to submenus like this:

```auto
[[menu.main]]
    identifier = "java"
    name = "Java"
    url = "/java/"
    weight = 1
  [[menu.main]]
    identifier = "java-core"
    name = "Core Java"
    url = "/tags/java-core/"
    parent = "java"
    weight = 10
  [[menu.main]]
    identifier = "java-collection"
    name = "Collections"
    url = "/tags/java-collection/"
    parent = "java"
    weight = 20
  [[menu.main]]
    identifier = "java-design-pattern"
    name = "Design Patterns"
    url = "/tags/java-design-pattern/"
    parent = "java"
    weight = 30

```
