Search code examples
navigationjekyllliquid

How to dynamically create a navigation based on Front Matter for Jekyll?


Goals:

  • Dynamic creation/management of a navigation without managing a data file
  • Support overridable ordering
  • Nesting of Elements
  • Hidden page support

Solution

  • Simple way to dynamically manage documentation through front matter without the need for a pesky config file.

    Three variables one can set in front matter:

    • parent: Represents if this should be nested within another page for navigation
    • hidden: false for a page to be publicly listed, it'll be accessible via direct link regardless
    • nav_priority: Weights which document to show first, 1 is highest (ie top)

    Logic

    • Can default to hide/show everything within _config.yml
    • A page shows up as a header if it:
      • has no parent OR
      • is a parent page
    • If a page has a parent, it will show up underneath the parent
      • Can only have 2 levels
    • If a parent is hidden, then all child pages are also hidden
    • Weighting can be defaulted for documents in _config.yml to 100 to keep them at the bottom, or 1 for at top

    the below assumes the files are in _docs if elsewhere change site.docs accordingly

    {% assign pages = site.docs | where: 'hidden', false %}
    {% if pages.size > 0 %}
      {% assign head_pages = pages | where: 'parent', nil | sort: 'nav_priority' %}
      {% for head_page in head_pages %}
        <h5>
          <a href="{{ head_page.url }}">{{ head_page.title }}</a>
        </h5>
    
        <ul>
          {% assign child_pages = pages | where: 'parent', head_page.title | sort: 'nav_priority' %}
          {% for child in child_pages  %}
            <li>
              <a href="{{ child.url }}">{{ child.title }}</a>
            </li>
          {% endfor %}
        </ul>
      {% endfor %}
    {% endif %}