Linking Pages to Navigation

Hi, I would like to automatically add a nav item whenever a page is published. Right now, I have a page and config collection. In order to show a page in the navigation, I need to first create the page, and then go to config to create a navigation item with the same title and link. Is there a way, perhaps in the config.yml, to streamline this process?

collections:
  - name: 'page'
    label: 'Page'
    folder: '_pages/'
    create: true
    slug: '{{slug}}'
    editor:
      preview: false
    fields:
      - {label: "Layout", name: "layout", widget: "hidden", default: "page"}
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Permalink", name: "permalink", widget: "string"}
      - {label: 'Body', name: 'body', widget: 'markdown'}
  - name: "config"
    label: "Config"
    editor:
      preview: false
    files:
      - label: "Navigation"
        name: "navigation"
        file: "_data/navigation.yml"
        fields:
          - label: "Navigation Items"
            name: "links"
            widget: "list"
            fields:
              - {label: Title, name: title, widget: string}
              - {label: Link, name: url, widget: string}

Hi @a772bNsz!
Are you using a static site generator to build your site? If so you could read the _pages directory during the build process and generate the nav items dynamically, without needing an additional Config collection.

Hi @erez, thanks for responding. Yes, I’m using Jekyll.

# page.html might need a script
---
layout: default
---

<section class="post">
  <h2>{{ page.title }}</h2>
  {{ content }}
</section>

# script would create another item in the navigation.yml
links:
  - title: Writing
    url: /
  - title: Downloads
    url: /downloads
  - title: Search
    url: /search

# which navigation.html would then create
<header role="banner">
      <!--<h1 class="logo">{{ site.title }}</h1>-->
      <nav role="navigation">
<ul>
   {% for item in site.data.navigation.links %}
      <li><a href="{{ item.url }}" {% if item.url == page.url %} class="active"{% endif %}>{{ item.title }}</a>    </li>
       {% endfor %}
    </ul>
    </nav>
    </header>

Question is, how would I write this script and insert it into page.html?

I’m actually not that familiar with Jekyll…You might have better results reaching out in one of the options here https://jekyllrb.com/docs/support/, or wait for a more experienced Jekyll user to respond.

Thanks for the tip, @erez. I figured it out, here’s a walk through for anyone looking for something similar:

# navigation.html
<ul>
  {% assign _pages = site.pages | sort: "order" %}
    {% for pg in _pages %}
    <li><a href="{{pg.url}}" {% if {{pg.url}} == {{page.url}} %} class="active" {% endif %}>{{ pg.title }}</a></li>
    {% endfor %}
</ul>

The snippet is getting all the pages in the folder _pages with site.pages. Then looping through, creating each of the nav items, assigning the “active” class to the list item representing the active page.

What if you want to hide certain pages?

# _posts/about.md
---
layout: page
title: About
show: False
---

I added a custom Boolean variable in the front matter. Then I revised navigation.html to check if the show variable is set to true

# changed navigation.html
<ul>
  {% assign _pages = site.pages | sort: "order" %}
    {% for pg in _pages %}
        {% if {{pg.show}} == true %}  # <------Right Here
    <li><a href="{{pg.url}}" {% if {{pg.url}} == {{page.url}} %} class="active" {% endif %}>{{ pg.title }}</a></li>
        {% endif %}
    {% endfor %}
</ul>
2 Likes