Menus
Build site navigation with rename-stable, per-language menus.
Menus model the navigation
Menus are named, ordered, optionally-nested lists of links. The active theme picks them up by slug at render time — e.g. a layout calls {{ index .app.menus "main-nav" }} to render the primary navigation. Themes can declare placements (header, footer, sidebar, mobile-only) and pull a different menu into each.
Manage at /admin/menus. Each menu has slug, name, and an items list. Items can nest arbitrarily deep.
Item types
Static URL
A label + URL + target (_self, _blank). Use for external links or hand-crafted paths.
Node-linked
A label + a page slug. The slug is resolved to the current public URL at render time, so renaming the target node doesn't break the menu. If the node is deleted or unpublished, the item is dropped from the rendered menu.
Children
Any item can have child items. The admin UI lets you drag-nest with no depth limit; the theme decides whether to render dropdowns, accordions, or flatten beyond a certain depth.
core.menu.upsert({
slug: "main-nav",
name: "Main navigation",
items: [
{ label: "Home", page: "home" },
{ label: "Docs", page: "introduction" },
{ label: "Blog", page: "blog-index", children: [
{ label: "Engineering", url: "/blog/category/engineering" },
{ label: "Product", url: "/blog/category/product" }
]},
{ label: "GitHub", url: "https://github.com/erikkubica/squilla", target: "_blank" }
]
})
label:, but the rendered menu items expose .title. Inside templates iterate items and read .title and .url — {{ .label }} is empty. core.menu.upsert fully replaces the items list on save (no partial merging).Per-language menus
Menus are scoped per language — a menu in English and one in Slovak are separate rows that share a slug. The admin top-bar language switcher picks which menu you're editing. Themes pull the menu matching the current request's locale and fall back to the default language if it doesn't exist.
Linking translated nodes in items
Node-linked items resolve through the language-aware router. An item linking to page slug about renders /about on the English site and /o-nas on the Slovak site — assuming both translations share a translation_group_id.