How to generate multi-level menu/tree from directories

New to Hugo and have gone through loads of documentation as well as this forum (and of course Google) but need a hand. My code is close to what I’m trying to achieve.

I don’t want to manually create a menu, but would rather have it reflect all the pages/directories within /docs (which is in /content). Over time the structure may change and rather than having to manually update lots of front matter, I’d rather the code loop over the directories/sub-directories. One thing I do think needs to be in front matter for each *.md file is the weight, so as to determine menu ordering. Code below is aimed at limiting it to three levels deep, fyi.

If I have the following example structure:

/docs
    _index.md
    docs-file1.md
    docs-file2.md
    /sub-directory
        _index.md
        sub-dir-docs-file1.md
        /sub-sub-directory
            _index.md
            sub-sub-dir-docs-file1.md

Here’s code I’m using in a sidebar partial

{{$page := .}}

<div class="docs-menu">
    <h4>{{ .Section | humanize }}</h4>
    <ul>
        {{ range (where .Site.Pages "Section" "docs") }}
                                
            {{ if eq .File.Dir "docs/"}}
                <li class="first-level">
                    <a href="{{.Permalink}}" class="{{ if eq .File.UniqueID $page.File.UniqueID }}active{{ end }}">{{ .Title }}</a>

                    <ul class="sub-menu">
                        {{ range .Sections }}                            
                            <li class="second-level">
                                <a href="{{.Permalink}}" class="{{ if eq .File.UniqueID $page.File.UniqueID }}active{{ end }}">{{ .Title }}</a>
                                
                                <ul class="sub-menu">
                                    {{ range .Sections }}
                                
                                        <li class="third-level">
                                            <a href="{{.Permalink}}" class="{{ if eq .File.UniqueID $page.File.UniqueID }}active{{ end }}">{{ .Title }}</a>
                                        </li>
                                    {{ end }}
                                </ul>   
                            </li>
                        {{ end }}
                    </ul>

                </li>
            {{ end }}

        {{ end }}

    </ul>
</div>   

Right now it’s working great for the first level directory (’/docs’). I get these all outputted fine:

/docs
    _index.md
    docs-file1.md
    docs-file2.md

But for the deeper level directories (sub-directory and sub-sub-directory), I’m only getting the index file and not the other .md pages. I’ve tried ranging over a union of .Sections .Pages but this doesn’t work. Any guidance would be appreciated.

Hi there,

It’s easier to help you with site code we can clone, instead of us trying to recreate your site ourselves. Please have a read about Requesting Help