Skip to Content
Navigation, payment & responsive

Navigation, payment icons & responsive requirements

The platform exposes menus on the Liquid context as linklists[handle]. Your theme must build the header nav from linklists['main-menu'].links and the footer link columns from linklists['footer-menu'].links. These are the single source of truth for what appears in the nav.

Both main-menu and footer-menu handles are platform-guaranteed to resolve on every store - hardcode those two as your defaults.

{% for link in linklists['main-menu'].links %} <a href="{{ link.url }}">{{ link.title }}</a> {% if link.links.size > 0 %} <ul class="dropdown"> {% for child in link.links %} <li><a href="{{ child.url }}">{{ child.title }}</a></li> {% endfor %} </ul> {% endif %} {% endfor %}

Each link: { title, url, type, resource, links[] }. Child links live on link.links (not link.children).

Fallback

When linklists['main-menu'].links is empty (a fresh store), fall back to auto-populated top-level collections:

{% assign nav_cols = collections | where: 'show_in_nav', true | where: 'parent_id', blank %}

Do not

  • Hardcode nav slots (nav_link_1..N section settings).
  • Read collection.parent_id / children to build the nav (that mirrors the collection tree, not the merchant’s chosen menu).
  • Default to fictional strings like “Shop / New / Sale”.

The mobile drawer follows the same rule - iterate the same linklists['main-menu'].links and render link.links indented or collapsible. Do not ship a second menu source for mobile.

Payment icons - shop.enabled_payment_types

Render the payment-method row from the platform’s single source of truth for what the store accepts, gated by one boolean setting show_payment_icons.

Either output the pre-rendered row:

{% if settings.show_payment_icons %} {{ shop.payment_icons_html }} {% endif %}

or iterate shop.enabled_payment_types and render your own icon set. Never hardcode a fixed <img src="visa.svg"> set or model it as a free-form “show Visa / hide Amex” toggle divorced from the real accepted methods.

Every link your theme ships in section defaults (header, footer, hero CTAs, collection tiles) must resolve for any store. Safe defaults:

  • /, /collections, /collections/all, /collections/all?sort_by=created-desc
  • /search, /wishlist, /account/login, /cart
  • /pages/<slug> URLs that fall through to the styled 404 when the merchant hasn’t created that page

The platform seeds four legal pages on every store, so these /pages/<slug> URLs are also safe: /pages/about-us, /pages/privacy-policy, /pages/terms-of-service, /pages/cookie-policy. The best way to surface them is via linklists['footer-menu'] - they appear automatically.

Never ship defaults like /collections/best-sellers, /collections/sale, /collections/men, /blogs/journal, or bare /about - those return a raw 404 for any store whose data doesn’t include them.

Responsive requirements

Every section must render correctly at 1440 / 768 / 375 px. Desktop-only themes are not shippable.

  • Header collapses to a drawer on mobile.
  • Multi-column grids reflow to 1-2 columns.
  • The filter sidebar becomes a slide-in drawer on mobile.
  • Sticky PDP info columns unstick / restack gracefully.
  • Touch targets stay >= 44px.

Hard prohibitions:

  • No display: none on mobile to hide a section the merchant configured - render it in a mobile-appropriate layout.
  • No hardcoded width: 1440px containers - use max-width + percentages.
  • No fixed-pixel font sizes that overflow at 375 px.

Empty & error states

Render styled HTML (never raw JSON or the browser default) for: empty cart, empty wishlist, empty search, empty collection, and the 404 page (templates/404.json must exist).