ComponentsRenderer
System component that dynamically renders Contentstack components based on their type.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
components | (HeroComponents | ComponentsPage | TwoColumnSide)[] | Yes | - | Array of component objects |
cslp | CSLPFieldMapping | No | - | CSLP mapping for editable fields |
cslpWrapper | string | No | - | CSLP wrapper identifier |
priorityFirstMedia | boolean | No | false | Marks the first media component as priority for faster LCP |
mediaSizes | string | No | - | Optional sizes string to pass to the prioritized media image |
noPadding | boolean | No | false | Passes noPadding to child components to remove section padding |
Supported Components
| Component Name | Component | Description |
|---|---|---|
hero | Hero | Hero section with title, CTAs, and nested components |
list | List | Grid of cards (DefaultCard or IconCard) |
media | Media | Image/media display |
rich_text | RichText | Rich text content with optional title |
two_column | TwoColumn | Two-column layout with nested components |
notice | Notice | Alert/notice box with variants |
Usage
import { ComponentsRenderer } from '@/components/system/ComponentsRenderer';
<ComponentsRenderer
components={[
{ hero: { title: "Welcome", ... } },
{ list: { title: "Features", cards: [...], ... } },
{ rich_text: { title: "About", copy: {...} } },
{ two_column: { side_a: [...], side_b: [...] } },
{ notice: { title: "Note", type: "notice", ... } }
]}
cslp={cslpData}
cslpWrapper="components"
/>Features
- Dynamic rendering: Renders components based on type using a componentMap lookup
- Type safety: Type-safe component mapping with TypeScript
- CSLP support: Wraps components with CSLP attributes in preview mode
- Error handling: Shows error message for unknown component types
- Empty state: Shows empty block in preview mode if no components
- Above-the-fold media priority: When
priorityFirstMediais true, injectspriority: trueinto the first media component for faster LCP - Above-the-fold list priority: Automatically detects list components at index 0 or 1 and injects
priorityFirstImage: trueso the first card image loads eagerly
Component Mapping
Components are mapped from Contentstack format:
[{ "hero": { ...props } }]To internal format:
{ name: "hero", props: { ...props } }Image Priority Logic
The renderer applies two automatic image priority optimizations:
-
Media priority (
priorityFirstMedia): When enabled (e.g., inside Hero), the firstmediacomponent getspriority: trueand a customsizesattribute. This is opt-in via props. -
List priority (automatic): When a
listcomponent appears at index 0 or 1 in the components array (above the fold), it automatically receivespriorityFirstImage: true, which makes the first card's image load withfetchPriority="high"andloading="eager".
Notes
- Uses componentMap for type-safe rendering
- Generates keys from component UID or index
- Shows red error box in development for unknown components
- Wraps components with CSLP divs in preview mode
- Used by Page, Hero, and TwoColumn to render their component arrays