Implementation Patterns
Media & Images
The BreaseImage component wraps Next.js Image with automatic Brease variant support, responsive srcSet generation, and smart fallbacks. This page covers all usage patterns for rendering media from the CMS.
BreaseImage Overview
import { BreaseImage } from 'brease-next'
<BreaseImage breaseImage={media} />
BreaseImage accepts a BreaseMedia object and renders an optimized Next.js Image. It handles variant selection, responsive images, alt text fallbacks, and null safety automatically.
BreaseMedia Type
Media objects returned from the CMS have this structure:
interface BreaseMedia {
alt: string
duration: number
extension: string
height: number
mimeGroup: string
mimeType: string
name: string
path: string
size: string
thumbnail: string
uuid: string
width: number
variants: Record<string, BreaseMediaVariant>
}
interface BreaseMediaVariant {
alt: string
extension: string
height: number
mimeType: string
path: string
size: string
type: string
width: number
}
The variants object contains pre-generated sizes keyed by variant name: sm, md, lg, xl, 2xl, hd, and original.
Responsive Images (Default Behavior)
When no variant prop is provided, BreaseImage automatically builds a srcSet from all available variants, letting the browser pick the best size for the viewport:
import { BreaseImage } from 'brease-next'
// Automatic srcSet from all variants (sm through original)
<BreaseImage breaseImage={elements.heroImage} priority />
The default sizes attribute is:
(max-width: 640px) 100vw, (max-width: 1024px) 50vw, (max-width: 1440px) 33vw, 25vw
This works well for typical content layouts. Override it with the sizes prop for different grid configurations.
Single Variant
Pass a variant prop to use a specific pre-generated size instead of the full srcSet:
// Use the "lg" variant only
<BreaseImage breaseImage={elements.thumbnail} variant="md" />
// Available variants: sm, md, lg, xl, 2xl, hd, original
<BreaseImage breaseImage={elements.banner} variant="xl" />
This is useful for thumbnails, avatars, or fixed-size images where you know exactly which size is appropriate.
Custom Sizes
For grid layouts or other non-default sizing, override the sizes prop:
// Two-column layout
<BreaseImage
breaseImage={elements.photo}
sizes="(max-width: 768px) 100vw, 50vw"
className="rounded-lg"
/>
// Three-column grid
<BreaseImage
breaseImage={elements.gridImage}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>
// Full-width hero
<BreaseImage
breaseImage={elements.heroImage}
sizes="100vw"
priority
/>
Alt Text Fallbacks
BreaseImage uses a fallback chain for alt text:
- The
altprop passed directly to the component breaseImage.altfrom the CMS media objectbreaseImage.name(the file name)"Image alt."as a last resort
// Uses alt from CMS media
<BreaseImage breaseImage={media} />
// Override with custom alt text
<BreaseImage breaseImage={media} alt="Custom description" />
Set alt text in the CMS
For best accessibility, set the alt text in the Brease media library. This ensures every usage of the image across your site has meaningful alt text without needing per-component overrides.
Width and Height
BreaseImage infers width and height from the largest available variant, falling back to the original image dimensions (breaseImage.width and breaseImage.height). This prevents layout shift without requiring you to specify dimensions manually.
Priority Loading
For above-the-fold images (heroes, banners), add the priority prop to disable lazy loading and preload the image:
<BreaseImage breaseImage={elements.heroBanner} priority />
Additional Props
BreaseImage passes through standard Next.js Image props like className, style, and priority:
<BreaseImage
breaseImage={elements.photo}
variant="lg"
className="rounded-xl shadow-lg object-cover"
priority
/>
Configuring Remote Patterns
Next.js requires explicit allowlisting of external image domains. Add the Brease media CDN to your next.config.ts:
// next.config.ts
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.brease.io',
pathname: '/**',
},
],
},
}
Image loading errors
If images fail to load with a "hostname not configured" error, check that remotePatterns includes assets.brease.io.
Handling Optional Media Fields
Media fields in sections or collection entries may be null or undefined if the content editor did not upload an image. BreaseImage returns null when breaseImage is falsy, so it is safe to render unconditionally:
// Safe — renders nothing if featuredImage is null
<BreaseImage breaseImage={elements.featuredImage} variant="lg" />
For cases where you want to show a placeholder or conditional wrapper:
{elements.featuredImage ? (
<BreaseImage
breaseImage={elements.featuredImage}
variant="lg"
className="rounded-lg"
/>
) : (
<div className="bg-gray-200 rounded-lg aspect-video flex items-center justify-center">
<span className="text-gray-400">No image</span>
</div>
)}
Using BreaseMedia Directly with Next.js Image
If you need more control than BreaseImage provides, use the BreaseMedia object with Next.js Image directly:
import Image from 'next/image'
import type { BreaseMedia } from 'brease-next'
interface GalleryProps {
images: BreaseMedia[]
}
export default function Gallery({ images }: GalleryProps) {
return (
<div className="grid grid-cols-3 gap-4">
{images.map((img) => {
const variant = img.variants?.lg ?? img.variants?.original
return (
<Image
key={img.uuid}
src={variant?.path ?? img.path}
alt={img.alt || img.name || 'Image alt.'}
width={variant?.width ?? img.width}
height={variant?.height ?? img.height}
className="rounded-lg object-cover"
/>
)
})}
</div>
)
}
Next Steps
- Pages & Dynamic Routes — rendering sections that contain images
- Collection Patterns — images in collection entries
- Structured Data & Custom Code — Open Graph images and metadata