Content Modeling
Navigations & Redirects
Navigations and redirects are managed per environment in the CMS and consumed on the frontend via brease-next.
Navigations
A navigation is a named container of navigation items, scoped per environment and localized per locale.
Item Types
In the CMS, each navigation item is one of: page (internal link), url (external link), media (file link), entry (collection entry link), or group (dropdown container with children).
On the frontend, all items arrive as BreaseNavigationItem:
interface BreaseNavigationItem {
uuid: string
label: string // Display text
isExternal: boolean // false for pages, true for external URLs
value: string // The URL or slug
target: '_blank' | '_self' | null
children: BreaseNavigationItem[] // Nested items
}
Use the isExternal flag and value to determine link behavior — or simply pass the item to BreaseLink which handles this automatically.
Ordering and Nesting
Items are reordered via drag-and-drop in the CMS. Nesting is supported — drag items under a group or another item to create multi-level dropdown menus. Nested items appear in the children array.
On the Frontend
Configure navigations in BreaseContext:
// src/lib/brease-config.ts
export const contextData = {
navigations: [
{ key: 'header', id: 'nav-a01c4cbb-21f7-46d5-a89c-564307998128' },
{ key: 'footer', id: 'nav-b02d5ecc-32f8-57e6-b9ad-675418009239' },
],
collections: [],
}
Access in client components via useBrease() and render items with BreaseLink:
'use client'
import { useBrease, BreaseLink } from 'brease-next'
export default function Header() {
const { navigations } = useBrease()
const headerNav = navigations.header
if (!headerNav) return null
return (
<nav className="flex items-center gap-6">
{headerNav.items.map((item) => (
<BreaseLink key={item.uuid} linkData={item} className="text-sm font-medium">
{item.label}
</BreaseLink>
))}
</nav>
)
}
BreaseLink handles internal vs external links automatically — it renders a Next.js Link for internal URLs and a native <a> with rel="noopener noreferrer" for external ones. Since BreaseNavigationItem extends BreaseLinkData, you can pass navigation items directly as linkData.
For nested items (dropdowns), iterate item.children:
{item.children.map((child) => (
<BreaseLink key={child.uuid} linkData={child}>
{child.label}
</BreaseLink>
))}
Finding navigation UUIDs
Open the Brease dashboard, go to Navigations, select your navigation, and copy the UUID from the settings panel or URL.
Redirects
Redirects are source/destination URL pairs with an HTTP status type, managed per environment in the CMS.
Redirect Types
| Type | Name | Behavior |
|---|---|---|
| 301 | Moved Permanently | Browsers and search engines cache this permanently |
| 302 | Found (Temporary) | Temporary redirect, not cached |
| 307 | Temporary Redirect | Like 302, but preserves the HTTP method (POST stays POST) |
| 308 | Permanent Redirect | Like 301, but preserves the HTTP method |
On the Frontend
Fetch redirects and apply them in next.config.ts:
// next.config.ts
import type { NextConfig } from 'next'
import { fetchRedirects } from 'brease-next/server'
const nextConfig: NextConfig = {
async redirects() {
const result = await fetchRedirects()
if (!result.success) {
console.error('Failed to fetch redirects:', result.error)
return []
}
return result.data.map((redirect) => ({
source: redirect.source,
destination: redirect.destination,
permanent: redirect.type === '301' || redirect.type === '308',
}))
},
}
export default nextConfig
Build-time only
Next.js redirects are evaluated at build time. After adding or changing redirects in the CMS, you need to rebuild and redeploy your site for the changes to take effect.
Redirect Format
When creating redirects in the CMS:
- Source: the path to redirect from (e.g.,
/old-page) - Destination: the path to redirect to (e.g.,
/new-page) - Both must include leading slashes
- Supports Next.js path matching patterns (e.g.,
/blog/:slug)