Skip to content

Grav Navigation & Menus — Organizing Your Site

DodaTech Updated 2026-06-27 4 min read

In this tutorial, you'll learn how navigation works in Grav — from folder ordering to custom menus and breadcrumbs.

What You'll Learn

  • How number prefixes control page ordering
  • How to set custom menu labels
  • How to hide pages from navigation
  • How to use Grav's menu template variable
  • How breadcrumbs work

Why It Matters

Navigation is how visitors find content. A well-organized menu makes your site usable; a confusing one makes people leave. Grav's folder-based navigation gives you precise control without a visual menu editor.

Real-World Use

Documentation sites often have a sidebar navigation showing the section hierarchy, a top nav with key pages, and breadcrumbs showing current location. Grav's folder structure maps directly to this — each folder level becomes a navigation level, and the number prefix controls order.

Folder Ordering

Grav sorts pages by their folder name. The number prefix determines position:

user/pages/
├── 01.home/              # First
├── 02.about/             # Second
├── 03.blog/              # Third
│   ├── 01.first-post/    # First child
│   └── 02.second-post/   # Second child
└── 04.contact/           # Fourth

The number prefix is stripped from the URL. The page still lives at /about, not /02.about.

Changing Order

To reorder pages, rename the folder:

# Move Contact before About
mv user/pages/04.contact/ user/pages/01.contact/
mv user/pages/01.home/ user/pages/02.home/
mv user/pages/02.about/ user/pages/03.about/
mv user/pages/03.blog/ user/pages/04.blog/

Now the order is: Contact → Home → About → Blog.

⚠️ Warning

Renaming folders changes URLs. If the site is live, set up redirects or use the route frontmatter field to keep old URLs working.

Custom Menu Labels

By default, Grav uses the page title as the menu label. Override it with the menu frontmatter field:

---
title: Frequently Asked Questions About Grav CMS
menu: FAQ
published: true
---

This shows "FAQ" in the menu but the full title on the page itself.

You can also set a different menu for different contexts:

---
title: Developer Guide
menu:
    - text: Guide
    - url: /dev-guide
---

But the simple menu: string approach covers most cases.

Page Visibility

Control whether a page appears in menus:

---
published: true
visible: true    # Shows in menus
---
---
published: true
visible: false   # Hidden from menus, but accessible via direct URL
---
---
published: false  # Completely inaccessible (404 for non-admins)
---

Use cases:

  • visible: false — Draft pages you want to share via direct link
  • published: false — Unfinished pages not ready for visitors

The Breadcrumbs plugin adds navigation breadcrumbs. Install it:

bin/gpm install breadcrumbs

Add a simple breadcrumb template to your page:

{% if config.plugins.breadcrumbs.enabled %}
    {% include 'partials/breadcrumbs.html.twig' %}
{% endif %}

Breadcrumbs automatically follow Grav's page hierarchy:

Home > Blog > My Post
Home > About
Home > Projects > Project A

Custom Menu Items

Grav's standard navigation loops over visible pages. For links that aren't real pages (external links, special pages), you can add custom menu items to site.yaml:

# user/config/site.yaml
title: My Site
menu_links:
    - text: GitHub
      url: https://github.com/myorg
    - text: API Docs
      url: /api-docs

Then in your template, merge custom links with page links.

Advanced: Nested Navigation Sidebar

For documentation sites, a sidebar showing nested page hierarchy is common. Here's a Twig partial that generates one:

{% macro nav(pages, level) %}
    {% for page in pages %}
        {% if page.visible %}
            <li class="level-{{ level }}">
                <a href="{{ page.url }}" class="{{ page.active ? 'active' : '' }}">
                    {{ page.menu }}
                </a>
                {% if page.children.count %}
                    <ul>
                        {{ _self.nav(page.children, level + 1) }}
                    </ul>
                {% endif %}
            </li>
        {% endif %}
    {% endfor %}
{% endmacro %}

<nav class="sidebar-nav">
    <ul>
        {{ _self.nav(pages.children, 0) }}
    </ul>
</nav>

This recursive macro renders nested lists for each level of the page hierarchy.

Common Navigation Mistakes

Mistake Symptom Fix
Missing number prefix Pages in wrong order or not sorted Add 01., 02. prefixes to folder names
visible: false Page not in menus but exists Set visible: true or remove the field
No menu field Menu shows full page title Add menu: Short Name to frontmatter
Folder too deeply nested URL is very long Keep nesting to 3 levels max
Breadcrumbs not showing Breadcrumbs plugin not installed bin/gpm install breadcrumbs

Learning Path

flowchart LR
  A["What is Grav?"] --> B["Installation"]
  B --> C["Pages & Content"]
  C --> D["Navigation
← You are here"]:::current D --> E["Twig Templating"] E --> F["Themes"] F --> G["Taxonomy & Blog"] G --> H["Plugins & Admin"] H --> I["Configuration & Caching"] I --> J["Deployment & Maintenance"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px

Practice Questions

  1. How does Grav determine page order in menus? Answer: By the number prefix in the folder name (01., 02., etc.). Lower numbers appear first.

  2. What's the difference between published: false and visible: false? Answer: published: false makes the page inaccessible (404). visible: false hides it from menus but the URL still works.

  3. How do you change a page's menu label without changing its title? Answer: Add menu: Short Label to the page's YAML frontmatter.

  4. What happens to URLs when you rename a folder? Answer: The URL changes to match the new folder name. Existing links and bookmarks will break unless you set up redirects.

  5. Challenge: Create a page hierarchy with 3 levels (Section > Subsection > Page), ensure all pages are visible in menus, and add breadcrumbs. Verify the breadcrumbs show the full path.

What's Next

Your site has structure. Now let's make it look good with custom templates:

Continue to Lesson 5: Twig Templating — Learn Twig, Grav's powerful template engine.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro