CartistoDocs

Navigation menus

Merchant-built menus, resolved to localized links a theme just renders.

Navigation is data. A merchant builds named menus in the dashboard; the server resolves every link to a language-prefixed URL and a localized label before render, so a theme renders navigation without ever hardcoding a route or looking up a slug.

The menus global

Every page receives menus — the tenant’s menus resolved and keyed by handle. Each item carries a ready url, label, and children:

{% if menus.main.items.size > 0 %}
  {% for item in menus.main.items %}
    {% if item.children.size > 0 %}
      <div class="dropdown">
        <a href="{{ item.url }}">{{ item.label }}</a>
        <div class="submenu">
          {% for child in item.children %}
            <a href="{{ child.url }}">{{ child.label }}</a>
          {% endfor %}
        </div>
      </div>
    {% else %}
      <a href="{{ item.url }}">{{ item.label }}</a>
    {% endif %}
  {% endfor %}
{% endif %}

main and footer are the conventional handles. Prefer a menu when present and fall back to navCategories (the store’s top categories) so a fresh store that never built a menu still has a working header:

{% if menus.main.items.size > 0 %}
  {# render menus.main … #}
{% elsif navCategories.size > 0 %}
  {# render navCategories … #}
{% else %}
  {# static Home / Products / Categories #}
{% endif %}

A menu setting

Let a merchant choose which menu a section uses with a menu setting type — its value is a handle, resolved to the same tree shape as a menus.* entry:

{ "type": "menu", "name": "footer_menu", "label": { "en": "Footer menu" } }
{% for item in component.footer_menu.items %}
  <a href="{{ item.url }}">{{ item.label }}</a>
{% endfor %}

Each item the server hands you:

Field What it is
url Language-prefixed, ready to use in href.
label Localized text (the merchant’s label, or the linked resource’s own name).
type home, collections, blog, category, product, page, blog_post, or url.
children Nested items (same shape).
Note

Dead links disappear A link to a resource that was deleted or unpublished (a removed product, an unpublished page) resolves to nothing and is dropped from the tree — a stale menu never renders a broken link, so you don’t need to guard for it.