Valkyrian Labs logo

Docs Navbar

Render or adapt nested docs group and docs set navigation.

Docs Navbar

Use the /next navigation helpers when a site header needs links into generated docs groups and docs sets.

Drop-In Navbar

PayloadMarkdownDocsNavbar is the default docs navigation UI. It reads docs groups and docs sets, renders nested navigation, and does not require your existing CMSLink component.

1import { PayloadMarkdownDocsNavbar } from 'payload-markdown-docs/next'2import type { Payload } from 'payload'3 4export function DocsNav({ payload }: { payload: Payload }) {5  return (6    <PayloadMarkdownDocsNavbar7      classNames={{8        root: 'docs-nav',9        activeLink: 'is-active',10      }}11      currentPath="/plugins/payload-markdown-docs"12      payload={payload}13    />14  )15}

Use renderLink when the app needs a framework link component, tracking, or custom link props.

Headless Tree

Use getPayloadMarkdownDocsNavItems when the app owns the markup.

1import { getPayloadMarkdownDocsNavItems } from 'payload-markdown-docs/next'2 3const docsNav = await getPayloadMarkdownDocsNavItems({4  payload,5})

The helper returns a serializable tree sorted by:

  1. order
  2. label

Top-level items are:

  • docs groups without a parent
  • docs sets without a group

Child groups and grouped docs sets are nested under their parent group.

Header Adapter

Use appendPayloadMarkdownDocsHeaderNavItems when the app already has a Header global with navItems.

1import { appendPayloadMarkdownDocsHeaderNavItems } from 'payload-markdown-docs/next'2 3const navItems = await appendPayloadMarkdownDocsHeaderNavItems({4  existingItems: header.navItems ?? [],5  maxItems: 8,6  payload,7})

Capacity only applies to top-level docs entries. When a top-level group fits, its child groups and docs sets stay intact.

The adapter emits custom URL links by default. This is the safest mode for existing CMSLink implementations.

1import { getPayloadMarkdownDocsHeaderNavItems } from 'payload-markdown-docs/next'2 3const docsItems = await getPayloadMarkdownDocsHeaderNavItems({4  mode: 'url',5  payload,6})

Use relationship mode only when the frontend renderer understands docs relationships.

1import { getPayloadMarkdownDocsHeaderNavItems } from 'payload-markdown-docs/next'2 3const docsItems = await getPayloadMarkdownDocsHeaderNavItems({4  mode: 'relationship',5  payload,6})

Caching

getPayloadMarkdownDocsNavItems (and the header adapters and PayloadMarkdownDocsNavbar, which use it) caches its docs set and docs group query in the Next data cache with unstable_cache, tagged PAYLOAD_MARKDOWN_DOCS_NAV_CACHE_TAG (payload-markdown-docs:nav). The cache key covers the collection slugs, fetchLimit and overrideAccess; maxItems, availableSlots and existingItems are applied after the cached read, so different header layouts share one entry.

Next records the tag on every prerendered page that rendered the nav, and the plugin expires it immediately (revalidateTag(tag, { expire: 0 })) whenever a docs set or docs group is created, changed or deleted and after every applied sync. Statically prerendered pages with the docs nav in their header are regenerated on the next request, with no site-level revalidation code.

  • includeDrafts: true (and Next draft mode) is never cached, so drafts stay live.
  • Pass cache: false to read directly. Outside a Next runtime (scripts, tests) the helper falls back to a direct read on its own.
  • To expire the nav from your own code, call revalidateTag(PAYLOAD_MARKDOWN_DOCS_NAV_CACHE_TAG, { expire: 0 }).