Content Management that can withstand the plundering hoards

Site navigation

For step-by-step menu editing see navigation guide. This reference defines metadata, directives and rendered theme classes.

The site's main menu is generated from page metadata. It is independent of the CMS page list, which continues to list every draft by URL. Each page has In the menu, Menu position and Parent page controls beside the page layout. Position and parent are disabled when the page is outside the menu. Save the draft, then publish to update the public site. Preview includes the selected page's unsaved menu changes.

The same controls appear above the canvas for both HTML/GrapesJS and Markdown pages. The top-right Publish site button saves any changes to the current page, then publishes the entire saved site. All pages use one ordered menu; only the current-page highlight changes as visitors navigate.

Existing pages default to visible, position 0, at the top level. Lower positions appear first among siblings. Equal positions sort by URL, then page ID, so the result is deterministic. Position is an integer from 0 to 1000000; it is a sort weight, so consecutive numbering is unnecessary.

Choose a parent to make a submenu. The relationship is explicit: /people can be under /about without changing its URL. URI nesting does not implicitly create menu nesting. Page titles supply link labels. The parent remains a clickable page link with a separate submenu disclosure, which works with touch, mouse and keyboard. Up to 16 levels are supported; self-parenting and cycles are rejected.

Hiding a parent hides its whole menu branch. It does not unpublish the pages or restrict access to their URLs. Deleting a parent promotes its children to the top level, retaining each child's position and descendants. The editor marks a deleted parent as unavailable until another parent or Top level is selected.

Markdown directives

Markdown files can start with this block, at column one, before page content:

!! menu: true
!! menu-position: 1
!! menu-parent: /about

# Our team

This page can have any URL; its menu parent is the About page.

menu is exactly true or false. menu-parent is a local page URL, with an optional trailing slash; leave its value empty for Top level. Create the parent page before importing its children. The keys are optional; omitted keys preserve the current page's settings, or use defaults for a new page. Unknown, duplicate or invalid directives are rejected with an error. The block must be contiguous; a blank line separates it from ordinary Markdown. Directive examples inside paragraphs, fenced code or indented code remain content.

Upload .md reads the block and updates the controls. Visual editing displays only the body and preserves the directive block while editing. Saving normalizes the block into page metadata and stores just the Markdown body as source. Download .md adds current menu directives, including the parent's current URL, so the file is portable to another site. Source mode also accepts these leading directives. The renderer strips them defensively before Markdown conversion, so older/imported source documents cannot display the metadata as page content.

Leading directives in older saved documents are also resolved across the whole site when listing pages, previewing and publishing. They do not require opening or re-saving each page to take effect in other pages' menus. Reads preserve the original source; the next save normalizes it into JSON menu metadata as usual.

Themes and responsive behaviour

A theme's Navigation binding renders the generated menu. This also works in existing saved/custom themes without modifying their component source or bundle schema. Hand-authored links elsewhere in a page remain ordinary page content. Themes without a navigation binding do not acquire a menu automatically.

Above 1024 pixels the menu shows its top-level links with submenu disclosures. At tablet and mobile widths it starts collapsed behind ☰ Menu. Native details/summary elements provide keyboard access and announced expanded states without JavaScript, external assets or theme executable code. Hidden desktop or mobile alternatives are removed from keyboard navigation by CSS. The current page link has aria-current="page".

The renderer supplies neutral .viking-navigation, .viking-nav-list, .viking-nav-item, .viking-nav-toggle and .viking-nav-submenu styles before the theme stylesheet, so themes can customise their appearance. Navigation decoration is outside the page's editable document and never becomes page source.