SiteNav

Nav

nav is the single primitive refrakt uses for every kind of structural navigation — sidebars, header menubars, footer link columns, and section landing pages. The content model is identical in every case (grouped or flat lists of links / page slugs); the layout attribute selects the presentation.

Basic usage

Define groups with headings and page slugs as list items. Items before the first heading become top-level items rendered above any groups.

{% nav %}
- [Documentation](/docs/getting-started)

## Getting Started
- [Getting started](/docs/getting-started)
- [Configuration](/docs/configuration/overview)

## Reference
- [CLI overview](/docs/cli/cli-overview)
- [Inspect](/docs/cli/inspect)
{% /nav %}
<nav data-rune="nav" data-source-path="runes/nav.md">
  <div data-name="top-level">
    <ul>
      <li data-field="item" data-rune="nav-item">
        <a href="/docs/getting-started">
          <span data-field="slug">Documentation</span>
        </a>
      </li>
    </ul>
  </div>
  <section data-field="group" data-rune="nav-group">
    <h2 id="getting-started" data-field="title">Getting Started</h2>
    <div data-name="panel">
      <ul>
        <li data-field="item" data-rune="nav-item">
          <a href="/docs/getting-started">
            <span data-field="slug">Getting started</span>
          </a>
        </li>
        <li data-field="item" data-rune="nav-item">
          <a href="/docs/configuration/overview">
            <span data-field="slug">Configuration</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
  <section data-field="group" data-rune="nav-group">
    <h2 id="reference" data-field="title">Reference</h2>
    <div data-name="panel">
      <ul>
        <li data-field="item" data-rune="nav-item">
          <a href="/docs/cli/cli-overview">
            <span data-field="slug">CLI overview</span>
          </a>
        </li>
        <li data-field="item" data-rune="nav-item">
          <a href="/docs/cli/inspect">
            <span data-field="slug">Inspect</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
</nav>

Getting Started

Reference

<rf-nav class="rf-nav" data-source-path="runes/nav.md" data-elevation="flush" data-rune="nav" data-density="compact">
  <div data-name="top-level" class="rf-nav__top-level">
    <ul>
      <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
        <a href="/docs/getting-started" class="rf-nav-item__link">
          <span data-field="slug">Documentation</span>
        </a>
      </li>
    </ul>
  </div>
  <section data-field="group" class="rf-nav-group" data-rune="nav-group" data-density="full">
    <h2 id="getting-started" data-field="title">Getting Started</h2>
    <div data-name="panel" class="rf-nav-group__panel">
      <ul>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/docs/getting-started" class="rf-nav-item__link">
            <span data-field="slug">Getting started</span>
          </a>
        </li>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/docs/configuration/overview" class="rf-nav-item__link">
            <span data-field="slug">Configuration</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
  <section data-field="group" class="rf-nav-group" data-rune="nav-group" data-density="full">
    <h2 id="reference" data-field="title">Reference</h2>
    <div data-name="panel" class="rf-nav-group__panel">
      <ul>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/docs/cli/cli-overview" class="rf-nav-item__link">
            <span data-field="slug">CLI overview</span>
          </a>
        </li>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/docs/cli/inspect" class="rf-nav-item__link">
            <span data-field="slug">Inspect</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
</rf-nav>

Each list item is a page slug (e.g., getting-started). Slugs resolve at build time against the nav's source file — a {% nav %} in site/content/docs/_layout.md resolves - getting-started to /docs/getting-started. The page's title frontmatter becomes the link text.

For pages in subdirectories, write a multi-segment slug: themes/configuration resolves to /extend/theme-authoring/configuration. For external URLs or anything outside the nav's source directory, use an explicit Markdown link [Label](/path). Full rules and the build error format are documented in Nav slug resolution.

Each rendered page evaluates every nav against its current URL. The exact-match item gets aria-current="page"; the longest-strict-prefix item (if any) gets data-active="ancestor". Themes style both — Lumina ships visually-distinct treatments by default.

Layouts

The layout attribute switches the presentation. All four layouts accept the same group + items content model.

Vertical (sidebar)

The default — vertical sidebar with groups stacked top to bottom. This is the layout you place in your _layout.md nav region.

{% nav %}
## Getting Started
- [Getting started](/docs/getting-started)
- [Configuration](/docs/configuration/overview)

## Authoring
- [Runes](/runes/rune-catalog)
- [Themes](/themes/themes-catalog)
{% /nav %}
<nav data-rune="nav" data-source-path="runes/nav.md">
  <section data-field="group" data-rune="nav-group">
    <h2 id="getting-started" data-field="title">Getting Started</h2>
    <div data-name="panel">
      <ul>
        <li data-field="item" data-rune="nav-item">
          <a href="/docs/getting-started">
            <span data-field="slug">Getting started</span>
          </a>
        </li>
        <li data-field="item" data-rune="nav-item">
          <a href="/docs/configuration/overview">
            <span data-field="slug">Configuration</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
  <section data-field="group" data-rune="nav-group">
    <h2 id="authoring" data-field="title">Authoring</h2>
    <div data-name="panel">
      <ul>
        <li data-field="item" data-rune="nav-item">
          <a href="/runes/rune-catalog">
            <span data-field="slug">Runes</span>
          </a>
        </li>
        <li data-field="item" data-rune="nav-item">
          <a href="/themes/themes-catalog">
            <span data-field="slug">Themes</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
</nav>

Getting Started

Authoring

<rf-nav class="rf-nav" data-source-path="runes/nav.md" data-elevation="flush" data-rune="nav" data-density="compact">
  <section data-field="group" class="rf-nav-group" data-rune="nav-group" data-density="full">
    <h2 id="getting-started" data-field="title">Getting Started</h2>
    <div data-name="panel" class="rf-nav-group__panel">
      <ul>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/docs/getting-started" class="rf-nav-item__link">
            <span data-field="slug">Getting started</span>
          </a>
        </li>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/docs/configuration/overview" class="rf-nav-item__link">
            <span data-field="slug">Configuration</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
  <section data-field="group" class="rf-nav-group" data-rune="nav-group" data-density="full">
    <h2 id="authoring" data-field="title">Authoring</h2>
    <div data-name="panel" class="rf-nav-group__panel">
      <ul>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/runes/rune-catalog" class="rf-nav-item__link">
            <span data-field="slug">Runes</span>
          </a>
        </li>
        <li data-field="item" class="rf-nav-item" data-rune="nav-item" data-density="full">
          <a href="/themes/themes-catalog" class="rf-nav-item__link">
            <span data-field="slug">Themes</span>
          </a>
        </li>
      </ul>
    </div>
  </section>
</rf-nav>

Horizontal bar where each group becomes a desktop dropdown trigger. Top-level items (before the first ##) render flat as the primary links. Below the breakpoint the whole menubar collapses behind a hamburger button that the rune emits automatically.

{% nav layout="menubar" %}
- [Docs](/docs)
- [Blog](/blog)

## Product
- features
- runes

## Resources
- about
- changelog
{% /nav %}

Interaction (click to open, Escape / outside-click to close, full keyboard model) ships in @refrakt-md/behaviors — no per-page wiring needed.

Column grid where each group becomes a footer column with the heading as the column title. Stacks to one column on narrow viewports.

{% nav layout="columns" %}
## Product
- features
- runes

## Resources
- about
- blog
- changelog

## Legal
- [Privacy](/privacy)
- [Terms](/terms)
{% /nav %}

Cards (section landing)

Card grid for section landing pages. Each item is enriched at build time with the linked page's title, description, and icon from frontmatter — no per-item authoring required. Group headings become section titles above each card cluster.

{% nav layout="cards" %}
- getting-started
- runes
- layouts
- theming
{% /nav %}

Combine with auto to list the current page's children without naming each one:

{% nav layout="cards" auto=true /%}

External-URL items render as title-only cards with no enrichment.

Strip (compact secondary nav)

Flat horizontal row of items — no groups, no panels. Use as a persistent secondary nav below the menubar, or nested inside a menubar panel footer slot for per-panel secondary links. Strip is flat by design and warns on ## headings.

{% nav layout="strip" %}
- [Changelog](/releases)
- [Roadmap](https://plan.refrakt.md/refrakt-md/refrakt)
- [Status](https://status.refrakt.md)
{% /nav %}

Rich menubar panels and column flow

Menubar ## groups accept any block content — paragraphs, blockquotes, images, and nested {% nav %} runes — with a position-based intro / footer slot rule. The columns layout gains a ----between-sections column-flow rule plus a headingless mode for use inside menubar panels. Composed together they cover Linear / Vercel / Stripe-style mega menus without a separate mega layout.

See Rich menubar panels and column flow for the full composition guide.

Collapsible sidebars

Add the collapsible modifier on a vertical nav to turn each group into a disclosure. The group containing the current page automatically expands on page load; all others start collapsed. Click a group title to toggle.

{% nav collapsible=true %}
## Getting Started
- getting-started
- install

## Authoring
- runes
- layouts
- theming
{% /nav %}

For the rare case where multiple groups should open by default, pass defaultOpen with a comma-separated list of group titles:

{% nav collapsible=true defaultOpen="Getting Started, Reference" %}

The keyboard model and ARIA wiring (role="button", aria-expanded, aria-controls, focus ring) ship in @refrakt-md/behaviors.

Frontmatter fields used by cards

The cards layout reads the following from each linked page's frontmatter:

---
title: Getting Started
description: Install refrakt and build your first site
icon: rocket
---
  • title — card heading. Required for sensible output.
  • description — card body. Optional; the card renders title-only when missing.
  • icon — icon name resolvable by the {% icon %} rune. Optional; the card renders without an icon when missing.

Mobile behaviour

Lumina handles responsive behaviour without any author work:

  • menubar collapses behind a hamburger button below the breakpoint. The button is emitted by the rune itself — themes show it via media query.
  • columns stacks into a single column on narrow viewports.
  • cards shifts to a single column below ~500px.
  • vertical collapsible works the same on every viewport — the collapse / expand model is viewport-agnostic.

Attributes

AttributeTypeRequiredDescription
orderedbooleanUse numbered list for navigation items
autobooleanAutomatically generate from child pages
layout"vertical" | "menubar" | "columns" | "cards" | "strip"Presentation layout: sidebar (vertical), horizontal menubar (header), column grid (footer), cards (section landing), or strip (compact secondary nav). Defaults to vertical.
collapsiblebooleanMake each group collapsible. The group containing the current page auto-expands; others start collapsed. Only meaningful for vertical layout.
defaultOpenstringComma-separated group titles to expand by default, overriding the URL-driven auto-open behaviour.

Universal attributes

bg

The background layer (SPEC-088): image, video, gradient, flat overlay wash and legibility scrim, in a single injected layer behind the rune's content.

AttributeTypeRequiredDescription
bgstringBackground preset applied to this block
bg-fromstringGradient start colour — a semantic token name (→ var(--rf-color-*))
bg-gradient"to-t" | "to-b" | "to-l" | "to-r" | "to-tr" | "to-br" | "to-bl" | "to-tl"Gradient direction (bounded named set)
bg-gradient-type"linear" | "radial" | "conic"Gradient type
bg-tostringGradient end colour — a semantic token name
bg-viastringOptional middle gradient stop — a semantic token name
scrim"top" | "bottom" | "left" | "right" | "none"Scrim direction (heaviest edge); presence turns the scrim on, "none" opts out of the default cover scrim
scrim-blur"none" | "sm" | "md" | "lg"Frost scrim blur amount
scrim-strength"sm" | "md" | "lg"Gradient scrim strength
scrim-tone"dark" | "light"Whether the scrim darkens (for light text) or lightens (for dark text)
scrim-type"gradient" | "frost"Scrim treatment: gradient (default) or frost (backdrop blur)
elevation

The chrome/depth ladder (SPEC-107). The skin maps each rung to a chrome bundle by attribute, so there is no BEM class.

AttributeTypeRequiredDescription
elevation"sunken" | "flush" | "flat" | "raised" | "floating" | "overlay" | "none" | "sm" | "md" | "lg"Surface depth on the SPEC-107 ladder (sunken→overlay); none/sm/md/lg are deprecated aliases
inset

Internal padding override.

AttributeTypeRequiredDescription
inset"flush" | "tight" | "default" | "loose" | "breathe"Inner padding of this block
motion

Scroll-reveal entrance (SPEC-105). The author declares the character, the theme owns the choreography, a behaviour owns the timing.

AttributeTypeRequiredDescription
reveal"none" | "fade" | "slide" | "scale" | "blur"Scroll-reveal entrance character (none|fade|slide|scale|blur); the theme owns the choreography
staggerbooleanCascade this block's items in as it reveals (no-op on single-child runes)
spacing

Block-level rhythm override.

AttributeTypeRequiredDescription
spacing"flush" | "tight" | "default" | "loose" | "breathe"Vertical spacing above and below this block
substrate

Generated pattern fills (SPEC-087). Markers only — the engine sets the attributes and cell/opacity custom properties, CSS draws the pattern.

AttributeTypeRequiredDescription
substrate"dots" | "grid" | "lines" | "cross" | "checker" | "none"Generated surface pattern
substrate-fill"inherit" | "inset"Surface fill the pattern sits on (full colour stays with tint)
substrate-opacity"sm" | "md" | "lg"Pattern ink strength
substrate-size"sm" | "md" | "lg"Pattern cell size
substrate-target"self" | "media"Which surface the pattern fills (overrides the rune/theme default)
tint

Per-rune colour override (SPEC-053): a named tint from the theme registry, with inline per-token overrides layered on top.

AttributeTypeRequiredDescription
tintstringColor tint preset applied to this block
tint-mode"auto" | "dark" | "light"Whether the tint adapts to auto, dark, or light mode
width

The track a block rune occupies.

AttributeTypeRequiredDescription
width"compact" | "narrow" | "content" | "wide" | "full"Maximum width constraint for this block
Not availableWhy
dropcap, readingthis rune declares no prose body
framethis rune declares neither a `frameTarget` nor a media section
prominencethis rune has no page-section header