brease-next Package
Components
The brease-next package exports five React components for rendering CMS content.
| Component | Type | Purpose |
|---|---|---|
BreasePage | Client | Renders page sections using a component map |
BreaseImage | Client | Responsive image rendering with variant support |
BreaseLink | Client | Smart internal/external link handling |
BreaseStructuredData | Server | JSON-LD structured data injection |
BreaseCustomCode | Server | Custom HTML/script injection |
BreasePage
Client component that maps CMS page sections to React components and renders them in order.
Import
import { BreasePage } from 'brease-next'
Props
| Prop | Type | Required | Description |
|---|---|---|---|
page | BreasePage | Yes | The page object from fetchPage |
sectionMap | Record<string, ComponentType<Record<string, unknown>>> | Yes | Maps section keys to React components |
How It Works
- Iterates through
page.sections - For each section, looks up the component from
sectionMapusingsection.key - Spreads
section.elementsas props to the matched component - Renders with
section.uuidas the React key - If no matching component is found for a section key, it is skipped
When rendered inside a BreaseContext, the component automatically uses the page from context if available. This enables live preview mode where the CMS pushes page updates via PostMessage, and BreasePage re-renders with the new content without a page reload.
Usage
// src/lib/brease/brease-config.ts
import { ComponentType } from 'react'
import HeroSection from '@/sections/hero-section'
import FeaturesSection from '@/sections/features-section'
import ContactSection from '@/sections/contact-section'
export const sectionMap: Record<string, ComponentType<Record<string, unknown>>> = {
hero: HeroSection,
features: FeaturesSection,
contact: ContactSection,
}
// src/app/[[...slug]]/page.tsx
import { BreasePage, ensureSuccess } from 'brease-next'
import { sectionMap } from '@/lib/brease/brease-config'
import { getPage } from '@/lib/brease/get-page'
import { notFound } from 'next/navigation'
export default async function Page({ params }: { params: Promise<{ slug?: string[] }> }) {
const { slug } = await params
const pageSlug = slug ? slug.join('/') : ''
const result = await getPage(pageSlug)
if (!result.success) {
if (result.status === 404) return notFound()
throw new Error(result.error)
}
return <BreasePage page={result.data} sectionMap={sectionMap} />
}
Section Components
All section components must include 'use client' at the top of the file. BreasePage is a client component and renders sections within a client component tree — server components cannot be used in the section map.
Each section component receives section.elements spread as props. Type your props based on the elements you configured in the CMS:
'use client'
import { BreaseMedia, BreaseLinkData } from 'brease-next'
interface HeroSectionProps {
title: string
subtitle: string
heroImage: BreaseMedia
ctaButton: BreaseLinkData
}
export default function HeroSection({ title, subtitle, heroImage, ctaButton }: HeroSectionProps) {
return (
<section>
<h1>{title}</h1>
{subtitle && <p>{subtitle}</p>}
</section>
)
}
BreaseImage
Wraps the Next.js Image component with Brease media data. Supports responsive variant-based srcSet and named variant selection.
Import
import { BreaseImage } from 'brease-next'
Props
| Prop | Type | Required | Description |
|---|---|---|---|
breaseImage | BreaseMedia | Yes | The media object from CMS elements |
variant | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'hd' | 'original' | No | Render a specific variant instead of responsive srcSet |
alt | string | No | Override the alt text from the media object |
sizes | string | No | The sizes attribute for responsive images |
...rest | any Next.js Image props | No | All other props are passed to the underlying Image component |
Variant Behavior
When no variant is specified, the component generates a responsive srcSet from all available variants. The variants are ordered by size: sm, md, lg, xl, 2xl, hd, original.
When a specific variant is provided, only that variant is rendered.
Usage
Responsive (automatic srcSet):
import { BreaseImage, type BreaseMedia } from 'brease-next'
interface HeroProps {
heroImage: BreaseMedia
}
export default function HeroSection({ heroImage }: HeroProps) {
return (
<BreaseImage
breaseImage={heroImage}
sizes="100vw"
className="w-full h-auto"
priority
/>
)
}
Specific variant:
<BreaseImage
breaseImage={thumbnail}
variant="sm"
className="rounded-full w-12 h-12"
/>
With alt text override:
<BreaseImage
breaseImage={productImage}
alt="Product hero shot"
sizes="(max-width: 768px) 100vw, 50vw"
/>
Null Handling
Returns null if breaseImage is falsy, so you can safely pass optional media elements without conditional rendering.
BreaseLink
Smart link component that renders internal links with Next.js Link and external links with a native <a> tag.
Import
import { BreaseLink } from 'brease-next'
Props
| Prop | Type | Required | Description |
|---|---|---|---|
linkData | BreaseLinkData | Yes | Link data object from CMS elements |
children | ReactNode | Yes | Link content |
...rest | anchor/Link props | No | Additional props passed to the underlying element |
BreaseLinkData Type
interface BreaseLinkData {
label: string // Display label (you can use children instead)
isExternal: boolean // Whether the link points to an external URL
value: string // The URL or path
target: '_blank' | '_self' | null
}
Behavior
- Internal links (
isExternal: false): rendered with Next.js<Link>for client-side navigation - External links (
isExternal: true): rendered with a native<a>tag - When
targetis'_blank',rel="noopener noreferrer"is automatically added for security
Usage
import { BreaseLink, type BreaseLinkData } from 'brease-next'
interface CtaSectionProps {
heading: string
ctaLink: BreaseLinkData
}
export default function CtaSection({ heading, ctaLink }: CtaSectionProps) {
return (
<section>
<h2>{heading}</h2>
<BreaseLink linkData={ctaLink} className="btn btn-primary">
{ctaLink.label}
</BreaseLink>
</section>
)
}
With custom children:
<BreaseLink linkData={link}>
<span className="icon">-></span>
<span>Read more</span>
</BreaseLink>
BreaseStructuredData
Server component that renders JSON-LD structured data from page.structuredData as a <script type="application/ld+json"> tag.
Import
import { BreaseStructuredData } from 'brease-next'
Props
| Prop | Type | Required | Description |
|---|---|---|---|
page | BreasePage | Yes | The page object containing structuredData |
Behavior
- Reads
page.structuredData(an array of JSON-LD objects) - Renders each as a
<script type="application/ld+json">tag - Renders nothing if
page.structuredDataisnullor empty
Usage
import { BreaseStructuredData, ensureSuccess, fetchPage } from 'brease-next'
export default async function Page() {
const page = ensureSuccess(await fetchPage('about-us'))
return (
<>
<BreaseStructuredData page={page} />
{/* rest of page */}
</>
)
}
Structured data is managed in the CMS page settings. Common schemas include Organization, Article, Product, FAQ, and BreadcrumbList.
BreaseCustomCode
Server component that renders custom HTML and scripts from page.customCode. Useful for analytics snippets, third-party widgets, or page-specific scripts managed in the CMS.
Import
import { BreaseCustomCode } from 'brease-next'
Props
| Prop | Type | Required | Description |
|---|---|---|---|
page | BreasePage | Yes | The page object containing customCode |
Behavior
- Reads
page.customCode(a string of HTML/script content) - Renders the content using
dangerouslySetInnerHTML - Renders nothing if
page.customCodeisnullor empty
Usage
import { BreaseCustomCode, ensureSuccess, fetchPage } from 'brease-next'
export default async function Page() {
const page = ensureSuccess(await fetchPage('about-us'))
return (
<>
{/* page content */}
<BreaseCustomCode page={page} />
</>
)
}
Custom code is managed per page in the CMS page settings. Site-wide custom code is available via BreaseSite.customCode.
Next Steps
- Context & Hooks -- BreaseContext setup and useBrease()
- SEO & Metadata -- metadata, structured data, and robots
- API Reference -- all functions and types