brease-next Package

Getting Started

This guide walks you through setting up brease-next in a Next.js project.

Reading these docs with an AI agent?

Point your coding tool at /llms.txt for a Markdown index of the whole documentation, or grab any page as raw Markdown by appending .md to its URL (e.g. /docs/getting-started.md).

Prerequisites

Before you begin, make sure you have:

  • Next.js 13+ (App Router)
  • React 18+
  • Node.js 16+
  • A Brease CMS account with a site created

Quick Start with CLI

The fastest way to get started is the CLI scaffolding tool:

npx brease-next

This interactive command creates a fully configured project with your CMS credentials, section mapping, and routing already wired up. See the CLI Scaffolding page for details.

If you prefer manual setup, continue below.


Step 1: Install the Package

npm install brease-next

Step 2: Get Your API Credentials

You need two values from the Brease CMS dashboard:

  1. Sign in at app.brease.io
  2. Open your site and navigate to Site Settings
  3. In the API Tokens section, generate a new token (or copy an existing one)
  4. Copy the Environment ID from the same settings page

Site Settings - API Credentials

Step 3: Configure Environment Variables

Create a .env.local file in your project root:

BREASE_TOKEN=your_api_token_here
BREASE_ENV=your_environment_id_here
BREASE_DEFAULT_LOCALE=en

Environment Variables Reference

VariableRequiredDefaultDescription
BREASE_TOKENYes--API authentication token from Site Settings
BREASE_ENVYes--Environment ID from Site Settings
BREASE_DEFAULT_LOCALEYes--Default locale code (e.g. en, sk)
BREASE_REVALIDATION_TIMENo30ISR revalidation interval in seconds

Step 4: Configure Next.js

Update your next.config.ts to support Brease media and redirects:

import type { NextConfig } from 'next'
import { fetchRedirects } from 'brease-next/server'

const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'assets.brease.io',
        pathname: '/**',
      },
    ],
  },

  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

Step 5: Create a Cached Page Fetcher

Create a shared, deduplicated page fetcher using React's cache():

// src/lib/brease/get-page.ts
import { cache } from 'react'
import { fetchPage } from 'brease-next'

export const getPage = cache(async (slug: string) => fetchPage(slug))

This ensures that your layout, generateMetadata, and page component all share a single request per render instead of making redundant API calls.

Step 6: Create a Section Map

Create a configuration file that maps CMS section keys to React components:

// src/lib/brease/brease-config.ts
import { ComponentType } from 'react'
import HeroSection from '@/sections/hero-section'
import TextSection from '@/sections/text-section'

export const sectionMap: Record<
  string,
  ComponentType<Record<string, unknown>>
> = {
  hero: HeroSection,
  text: TextSection,
}

export const contextConfig = {
  navigations: [
    // { key: 'header', id: 'your-navigation-uuid' },
    // { key: 'footer', id: 'your-navigation-uuid' },
  ],
  collections: [
    // { key: 'faqs', id: 'your-collection-uuid' },
  ],
  userParams: {},
}

Step 7: Set Up Root Layout

Wrap your application with BreaseContext in the root layout. The slug prop tells the context which page is currently active:

// src/app/[[...slug]]/layout.tsx
import { BreaseContext } from 'brease-next'
import { contextConfig } from '@/lib/brease/brease-config'
import { getPage } from '@/lib/brease/get-page'
import 'brease-next/styles'

export default async function SlugLayout({
  children,
  params,
}: {
  children: React.ReactNode
  params: Promise<{ slug?: string[] }>
}) {
  const { slug } = await params
  const pageSlug = slug ? slug.join('/') : ''

  return (
    <BreaseContext config={contextConfig} slug={pageSlug} getPage={getPage}>
      {children}
    </BreaseContext>
  )
}

Key points:

  • The slug prop accepts the current route slug, optionally with a locale prefix (e.g. sk/about-us).
  • The getPage prop passes your cached fetcher so the context can share page data with the page component.
  • import 'brease-next/styles' loads the styles required for CMS preview toolbar functionality.

Step 8: Create the Catch-All Page

// src/app/[[...slug]]/page.tsx
import { BreasePage, generateBreasePageMetadata, ensureSuccess } from 'brease-next'
import { sectionMap } from '@/lib/brease/brease-config'
import { getPage } from '@/lib/brease/get-page'
import { notFound } from 'next/navigation'
import type { Metadata } from 'next'

type Props = { params: Promise<{ slug?: string[] }> }

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params
  const pageSlug = slug ? slug.join('/') : ''
  const result = await getPage(pageSlug)

  if (!result.success) return {}

  return generateBreasePageMetadata(result.data)
}

export default async function Page({ params }: Props) {
  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} />
}

Verification

Start the development server and check for errors:

npm run dev

Open your browser to http://localhost:3000. If everything is configured correctly:

  • The page should render without console errors
  • You should see your CMS content (or an empty page if no sections are configured yet)

If you see errors about missing environment variables, double-check your .env.local file and restart the dev server.

Next Steps

Previous
Collection Manager