✨ Publier v1 is live — a polished docs platform built for the open web.
Skip to content

Navigation

Data-driven nav variants and pathRules routing, plus the filesystem escape hatch for exotic layouts.

Publier’s top navigation has two layers:

  1. Datapublier.config.yaml#nav describes content (title, logo, links, CTA) per variant plus URL routing rules.
  2. Layout — Publier renders the variant you picked. Drop your own src/components/TopNav.astro to replace it entirely.

The data layer covers the 90% case. The filesystem escape hatch covers the other 10%.

Flat form — one nav, whole site

Start here if you only need one nav across every page:

publier.config.yaml
nav:
title: My Site
logo: /logo.svg
links:
- { label: Docs, href: /docs }
- { label: GitHub, href: https://github.com/acme/product, external: true }
cta:
label: Get started
href: /docs/getting-started

Publier coerces this into a single default variant. Every page renders the same nav.

Variants + pathRules — per-path auto-routing

When your site has distinct zones (landing / docs / blog) with different navs, use named variants plus a URL routing table:

nav:
# Name of the fallback variant when no pathRule matches.
default: default
# First-match-wins routing. Evaluated against the current pathname
# when a page doesn't pass an explicit `nav` prop.
pathRules:
- { path: /docs/**, variant: docs }
- { path: /docs, variant: docs }
- { path: /blog/**, variant: blog }
- { path: /, variant: marketing }
- { path: /pricing, variant: marketing }
- { path: /login, variant: false } # disable nav entirely
- { path: /*, variant: default }
variants:
default:
title: Acme
logo: /logo.svg
links: [{ label: Docs, href: /docs }]
cta: { label: Get started, href: /signup }
docs:
title: Acme Docs
logo: /logo.svg
tabs:
- { label: Documentation, href: /docs }
- { label: Guides, href: /docs/guides }
cta: { label: Get started, href: /signup }
marketing:
title: Acme
logo: /logo.svg
links:
- { label: Features, href: /#features }
- { label: Pricing, href: /pricing }
cta: { label: Start free, href: /signup }
blog:
title: Acme Blog
links: [{ label: Docs, href: /docs }]

Path glob vocabulary

  • * — any single path segment ([^/]+)
  • ** — any depth (.*, matches nested segments)
  • literal text — verbatim; regex metacharacters escaped

Patterns are anchored on both sides, so /docs/* matches /docs/intro but not /docs/guides/diagrams — use /docs/** for subtree matching.

variant: false disables the nav

A rule with variant: false renders no <TopNav> for matching paths. This is the same effect as <BaseLayout nav={false}> in a page, but declarative.

Per-page override (legacy escape hatch)

Any page can still pass nav="variantName" or nav={false} to override the path-based routing:

---
import { BaseLayout } from '@publier/shell/layouts';
---
<BaseLayout title="Checkout" nav={false}>
<!-- no nav on this page regardless of pathRules -->
</BaseLayout>

Explicit props always win over pathRules.

Filesystem override — full control

YAML is data for the common cases. If you need layout logic the data model can’t express — custom zone layouts, per-variant CTA animations, conditional greetings, an A/B test — drop your own src/components/TopNav.astro file in your project:

src/components/TopNav.astro
---
interface Props {
variant: string;
currentPath: string;
}
const { variant, currentPath } = Astro.props;
---
<header class="navbar …">
<!-- whatever markup you need -->
</header>

Astro’s filesystem resolution picks your copy over the default. No configuration flag required — the file’s existence is the opt-in.

When NOT to reach for YAML

Don’t try to express positioning, animation, or conditional logic in publier.config.yaml. The schema intentionally stays lean — bloating it into a layout DSL would trade Publier’s zero-config DX for a brittle config surface. The filesystem override is the right lever for anything beyond “here’s my list of links and my CTA.”