Implementation Patterns
Navigation Patterns
Navigations in Brease are managed in the CMS and fetched automatically by BreaseContext. Use the BreaseLink component to render navigation items — it handles internal vs external links, targets, and security attributes automatically.
Accessing Navigation Data
Navigations are configured in your BreaseContextConfig and made available to client components through the useBrease() hook.
1. Register navigations in config
// src/lib/brease/config.ts
import { BreaseContextConfig } from 'brease-next'
export const contextData: BreaseContextConfig = {
navigations: [
{ key: 'header', id: 'your-header-nav-uuid' },
{ key: 'footer', id: 'your-footer-nav-uuid' },
],
collections: [],
userParams: {},
}
2. Access in client components
'use client'
import { useBrease } from 'brease-next'
export default function Header() {
const { navigations } = useBrease()
const headerNav = navigations.header
if (!headerNav) return null
// headerNav is a BreaseNavigation object
// headerNav.items is an array of BreaseNavigationItem
}
Navigation data shape
Each navigation item implements BreaseLinkData with added uuid and children:
interface BreaseNavigationItem {
uuid: string
label: string // Display text
isExternal: boolean // true for external URLs
value: string // The full URL or path — use as href directly
target: '_blank' | '_self' | null
children: BreaseNavigationItem[] // Nested items
}
The value field contains everything needed for the link — for internal links it's the path (e.g. /about), for external links it's the full URL (e.g. https://example.com). You never need to construct or manipulate it.
Using BreaseLink
BreaseLink is the recommended way to render any navigation item. It reads isExternal, value, target, and label from the linkData prop and renders the correct element automatically:
- Internal links → Next.js
<Link>(client-side navigation) - External links → native
<a>withrel="noopener noreferrer"whentarget="_blank"
import { BreaseLink } from 'brease-next'
<BreaseLink linkData={item} className="text-sm font-medium">
{item.label}
</BreaseLink>
Since BreaseNavigationItem extends BreaseLinkData, navigation items can be passed directly as linkData. Any extra props (className, onClick, etc.) are forwarded to the underlying element.
Header Navigation
A complete header component with dropdown support:
// src/components/header.tsx
'use client'
import { useState } from 'react'
import { useBrease, BreaseLink } from 'brease-next'
import type { BreaseNavigationItem } from 'brease-next'
import Link from 'next/link'
export default function Header() {
const { navigations } = useBrease()
const headerNav = navigations.header
if (!headerNav) return null
return (
<header className="border-b bg-white">
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-6">
<Link href="/" className="text-xl font-bold">
My Site
</Link>
<nav className="flex items-center gap-8">
{headerNav.items.map((item) => (
<NavItem key={item.uuid} item={item} />
))}
</nav>
</div>
</header>
)
}
function NavItem({ item }: { item: BreaseNavigationItem }) {
const [open, setOpen] = useState(false)
const hasChildren = item.children && item.children.length > 0
if (hasChildren) {
return (
<div
className="relative"
onMouseEnter={() => setOpen(true)}
onMouseLeave={() => setOpen(false)}
>
<button className="flex items-center gap-1 text-sm font-medium text-gray-700 hover:text-gray-900">
{item.label}
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>
{open && (
<div className="absolute left-0 top-full mt-1 w-48 rounded-md border bg-white py-1 shadow-lg">
{item.children.map((child) => (
<BreaseLink
key={child.uuid}
linkData={child}
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
{child.label}
</BreaseLink>
))}
</div>
)}
</div>
)
}
return (
<BreaseLink linkData={item} className="text-sm font-medium text-gray-700 hover:text-gray-900">
{item.label}
</BreaseLink>
)
}
Footer Navigation
Footer navigations typically use top-level items as column headings with their children as the links:
// src/components/footer.tsx
'use client'
import { useBrease, BreaseLink } from 'brease-next'
export default function Footer() {
const { navigations } = useBrease()
const footerNav = navigations.footer
if (!footerNav) return null
return (
<footer className="border-t bg-gray-50">
<div className="mx-auto max-w-7xl px-6 py-12">
<div className="grid gap-8 md:grid-cols-4">
<div>
<h3 className="text-lg font-bold">My Site</h3>
<p className="mt-2 text-sm text-gray-600">
{footerNav.description}
</p>
</div>
{footerNav.items.map((group) => (
<div key={group.uuid}>
<h4 className="text-sm font-semibold uppercase tracking-wider text-gray-900">
{group.label}
</h4>
{group.children && group.children.length > 0 && (
<ul className="mt-4 space-y-3">
{group.children.map((child) => (
<li key={child.uuid}>
<BreaseLink
linkData={child}
className="text-sm text-gray-600 hover:text-gray-900"
>
{child.label}
</BreaseLink>
</li>
))}
</ul>
)}
</div>
))}
</div>
<div className="mt-12 border-t pt-8 text-center text-sm text-gray-500">
© {new Date().getFullYear()} My Site. All rights reserved.
</div>
</div>
</footer>
)
}
Footer navigation structure
Structure your footer navigation in the CMS with top-level items as column headings (group type) and their children as the links within each column.
Fetching Navigation Directly
If you need navigation data outside of BreaseContext (e.g. in a server component or a route that does not use the catch-all layout), fetch it directly:
import { fetchNavigation } from 'brease-next/server'
const result = await fetchNavigation('your-nav-uuid', 'en')
if (result.success) {
const nav = result.data
// nav.items contains the navigation tree
}
Locale parameter required
fetchNavigation requires a locale parameter. When fetching directly (outside BreaseContext), you must supply it explicitly.
Next Steps
- Multi-Locale Sites — language switcher using navigation data
- Pages & Dynamic Routes — where to place Header and Footer components
- Collection Patterns — working with collection data