JSON Component Extension¶
Build custom UI components using a simple JSON design language. Create rich, data-driven content blocks without writing HTML or Thymeleaf templates—with optional AI assistance to generate components from natural language descriptions.
Overview¶
The JSON Component extension enables business users and developers to create custom UI components using a declarative JSON schema. Components are:
- Theme-agnostic: Semantic tokens map to theme-specific CSS automatically
- Data-driven: Bind content to user, order, and site context data
- AI-assisted: Generate components from natural language prompts using Claude
Why JSON Components?¶
For Business Users - Create custom content blocks without developer help - Use familiar concepts (headings, text, images, buttons) - AI assistant helps generate component JSON from descriptions - Preview changes before publishing
For Developers - Consistent, validated component structure - Theme-aware styling with semantic tokens - Data binding with JSON Pointer syntax - Extensible component catalog
Quick Start¶
Adding a JSON Component¶
- Navigate to any page in the admin panel
- Click Add Extension
- Select JSON Component
- Use the JSON editor or AI assistant to create your component
- Save and preview
Basic Example¶
{
"version": "1.0",
"component": {
"type": "container",
"props": {
"style": { "padding": "lg", "background": "surface" }
},
"children": [
{
"type": "heading",
"props": {
"level": 2,
"text": "Welcome to Our Store",
"style": { "variant": "heading-lg", "color": "primary" }
}
},
{
"type": "text",
"props": {
"text": "Discover our latest products and exclusive offers.",
"style": { "variant": "body-md", "color": "muted" }
}
},
{
"type": "button",
"props": {
"text": "Shop Now",
"action": { "type": "navigate", "href": "/collections/new-arrivals" },
"style": { "variant": "button-primary" }
}
}
]
}
}
Layout Modes¶
Control how the component fills the page by adding a layout property at the top level:
| Mode | Description | Use Case |
|---|---|---|
fluid |
Full-width, edge-to-edge (default) | Hero sections, full-width backgrounds |
contained |
Constrained to page container width | Standard content sections |
Full-Width (Fluid) Layout¶
For hero sections and full-bleed backgrounds:
{
"version": "1.0",
"layout": "fluid",
"component": {
"type": "container",
"props": {
"style": {
"backgroundImage": "media/hero.jpg",
"backgroundOverlay": "dark",
"padding": "xl"
}
},
"children": [...]
}
}
Contained Layout¶
For standard content that should respect page margins:
{
"version": "1.0",
"layout": "contained",
"component": {
"type": "container",
"props": {
"style": { "padding": "lg" }
},
"children": [...]
}
}
Full-Width with Constrained Content¶
For full-width backgrounds with readable text:
{
"version": "1.0",
"layout": "fluid",
"component": {
"type": "container",
"props": {
"style": { "backgroundImage": "media/hero.jpg", "padding": "xl" }
},
"children": [
{
"type": "container",
"props": {
"style": { "maxWidth": "prose" }
},
"children": [...]
}
]
}
}
Component Catalog¶
Layout Components¶
Container¶
A wrapper for grouping components with spacing, background options, and optional background images for hero sections.
{
"type": "container",
"props": {
"style": { "spacing": "md", "padding": "lg", "background": "surface" }
},
"children": [...]
}
Style tokens: spacing, padding, background, radius, shadow, maxWidth
Background Images:
Create hero sections with image backgrounds and text overlays:
{
"type": "container",
"props": {
"style": {
"backgroundImage": "media/hero.jpg",
"backgroundOverlay": "dark",
"backgroundPosition": "center",
"backgroundSize": "cover",
"padding": "xl"
}
},
"children": [
{
"type": "heading",
"props": {
"text": "Welcome",
"style": { "color": "white" }
}
}
]
}
| Token | Values | Description |
|---|---|---|
backgroundImage |
URL string | Image URL or media library path |
backgroundOverlay |
none, light, medium, dark, heavy |
Semi-transparent overlay for text readability |
backgroundPosition |
center, top, bottom, left, right |
Image positioning |
backgroundSize |
cover, contain, auto |
Image sizing behavior |
Row¶
A horizontal flex container for side-by-side layouts with responsive stacking control.
{
"type": "row",
"props": {
"stackOnMobile": true,
"style": { "gap": "md", "align": "center", "justify": "between" }
},
"children": [...]
}
Props:
- stackOnMobile: Whether columns stack vertically on mobile (default: true)
Style tokens: gap, align, justify
Responsive Behavior:
- By default (stackOnMobile: true), row children stack vertically on screens < 768px
- Set stackOnMobile: false to keep columns side-by-side on all screen sizes
Column¶
A vertical flex container for stacking components with optional width control.
{
"type": "column",
"props": {
"width": "2/3",
"mobileWidth": "full",
"style": { "gap": "sm", "align": "start" }
},
"children": [...]
}
Props:
- width: Column width - 1/4, 1/3, 1/2, 2/3, 3/4, full, auto (default: auto)
- mobileWidth: Width on mobile screens - 1/2, full, auto (default: full)
Style tokens: gap, align, maxWidth
Example - Asymmetric Two-Column Layout:
{
"type": "row",
"props": { "style": { "gap": "lg" } },
"children": [
{
"type": "column",
"props": { "width": "2/3" },
"children": [...]
},
{
"type": "column",
"props": { "width": "1/3" },
"children": [...]
}
]
}
| Width | Description |
|---|---|
1/4 |
25% width |
1/3 |
33.3% width |
1/2 |
50% width |
2/3 |
66.6% width |
3/4 |
75% width |
full |
100% width |
auto |
Flexible width (default) |
Content Components¶
Heading¶
A text heading (h1-h6) for titles and section headers.
{
"type": "heading",
"props": {
"level": 2,
"text": "Section Title",
"style": { "variant": "heading-lg", "color": "primary" }
}
}
Props:
- level (1-6): Heading level, default 2
- text: The heading text (supports data binding)
- style: Styling tokens
Style tokens: variant, color, align, transform, tracking
Text¶
A paragraph or inline text element.
{
"type": "text",
"props": {
"text": "Your paragraph content here.",
"style": { "variant": "body-md", "color": "muted", "align": "center" }
}
}
Props:
- text: The text content (supports data binding)
- style: Styling tokens
Style tokens: variant, color, align, transform, tracking
Text Transform & Letter Spacing:
Create label-style text with uppercase and letter-spacing:
{
"type": "text",
"props": {
"text": "About this demo",
"style": {
"transform": "uppercase",
"tracking": "wide",
"variant": "body-sm",
"color": "muted"
}
}
}
| Token | Values | Description |
|---|---|---|
transform |
uppercase, lowercase, capitalize, none |
Text transformation |
tracking |
tight, normal, wide, wider, widest |
Letter spacing |
Image¶
An image element with optional styling.
{
"type": "image",
"props": {
"src": "/images/hero.jpg",
"alt": "Hero banner image",
"style": { "radius": "md", "shadow": "lg" }
}
}
Props:
- src: Image URL (supports data binding)
- alt: Alt text for accessibility (supports data binding)
- style: Styling tokens
Divider¶
A horizontal line separator for visual breaks between content sections.
{
"type": "divider",
"props": {
"thickness": "thin",
"lineStyle": "dashed",
"style": { "color": "muted" }
}
}
Props:
- thickness: Line thickness - thin, md, thick (default: md)
- lineStyle: Line style - solid, dashed, dotted (default: solid)
- style: Styling tokens
Style tokens: color, spacing
Blockquote¶
A styled quote block with optional author attribution, ideal for testimonials.
{
"type": "blockquote",
"props": {
"quote": "This platform transformed our business.",
"author": "Jane Smith",
"role": "CEO, Acme Corp",
"avatar": "media/avatars/jane.jpg"
}
}
Props:
- quote: The quote text (required, supports data binding)
- author: Author name (supports data binding)
- role: Author title/role (supports data binding)
- avatar: Author avatar image URL (supports data binding)
- style: Styling tokens
Style tokens: variant, color, background
Icon¶
A Lucide icon component with customizable size and color.
{
"type": "icon",
"props": {
"name": "shopping-cart",
"size": "lg",
"style": { "color": "primary" }
}
}
Props:
- name: Icon name from the curated Lucide set (required)
- size: Icon size - xs, sm, md, lg, xl (default: md)
- style: Styling tokens
Style tokens: color
Available Icons:
| Category | Icons |
|---|---|
| Navigation | arrow-right, arrow-left, arrow-up, arrow-down, chevron-right, chevron-left, chevron-up, chevron-down, menu, x |
| Actions | check, plus, minus, search, settings, edit, trash, copy, download, upload, external-link |
| E-commerce | shopping-cart, shopping-bag, credit-card, tag, gift, percent, truck, package |
| Communication | mail, phone, message-circle |
| Social | share, heart, star, thumbs-up |
| Status | info, alert-circle, check-circle, x-circle, help-circle |
| User | user, users, log-in, log-out |
| Misc | home, calendar, clock, map-pin, eye, lock, shield, award, zap, sparkles, rocket |
Icon Size Reference:
| Size | Pixels |
|---|---|
xs |
12px |
sm |
16px |
md |
24px |
lg |
32px |
xl |
48px |
Interactive Components¶
Carousel¶
A simple image carousel with auto-advance.
{
"type": "carousel",
"props": {
"images": [
{ "src": "media/slide1.jpg", "alt": "Slide 1", "caption": "Welcome to our store" },
{ "src": "media/slide2.jpg", "alt": "Slide 2", "caption": "Summer collection" }
],
"autoPlay": true,
"interval": 5000,
"showIndicators": true,
"showControls": true,
"style": { "radius": "lg" }
}
}
Props:
- images: Array of image objects with src, alt, and optional caption
- autoPlay: Enable automatic sliding (default: true)
- interval: Time between slides in milliseconds (default: 5000)
- showIndicators: Show slide indicators (default: true)
- showControls: Show prev/next buttons (default: true)
- style: Styling tokens
Tabs¶
A tabbed content container for organizing content into panels.
{
"type": "tabs",
"children": [
{
"type": "tab",
"props": { "label": "Description", "active": true },
"children": [
{ "type": "text", "props": { "text": "Product description here." } }
]
},
{
"type": "tab",
"props": { "label": "Reviews" },
"children": [
{ "type": "text", "props": { "text": "Customer reviews here." } }
]
}
]
}
Tabs Props:
- style: Styling tokens
- children: Must contain tab components
Tab Props:
- label: Tab label text (supports data binding)
- active: Whether this tab is active by default (default: false)
- children: Content to display when tab is active
Accordion¶
A collapsible content container for expandable sections.
{
"type": "accordion",
"props": { "allowMultiple": false },
"children": [
{
"type": "accordionItem",
"props": { "title": "Shipping Information", "expanded": true },
"children": [
{ "type": "text", "props": { "text": "We ship worldwide..." } }
]
},
{
"type": "accordionItem",
"props": { "title": "Return Policy" },
"children": [
{ "type": "text", "props": { "text": "30-day returns..." } }
]
}
]
}
Accordion Props:
- allowMultiple: Allow multiple sections open at once (default: false)
- style: Styling tokens
- children: Must contain accordionItem components
AccordionItem Props:
- title: Section title (supports data binding)
- expanded: Whether expanded by default (default: false)
- children: Content to display when expanded
Link¶
A navigation link to another page or URL.
{
"type": "link",
"props": {
"text": "View All Products",
"href": "/collections/all",
"style": { "variant": "link" }
}
}
Props:
- text: Link text (supports data binding)
- href: Target URL (supports data binding)
- action: Alternative navigation action
- style: Styling tokens
Button¶
A clickable button for navigation actions with optional icon.
{
"type": "button",
"props": {
"text": "Add to Cart",
"icon": "shopping-cart",
"iconPosition": "left",
"action": { "type": "navigate", "href": "/cart" },
"style": { "variant": "button-primary" }
}
}
Props:
- text: Button text (supports data binding)
- icon: Optional icon name (uses same icons as the icon component)
- iconPosition: left or right (default: right)
- action: Navigation action with type and href
- style: Styling tokens
Available button icons:
arrow-right, arrow-left, chevron-right, chevron-left, shopping-cart, shopping-bag, heart, star, check, plus, minus, search, download, upload, external-link, mail, phone, user, log-in, log-out
Example - Button with icon:
{
"type": "button",
"props": {
"text": "Shop Now",
"icon": "arrow-right",
"iconPosition": "right",
"action": { "type": "navigate", "href": "/collections" },
"style": { "variant": "button-primary" }
}
}
Spacer¶
An empty space element for adding gaps between components.
Props:
- size: One of xs, sm, md, lg, xl
Data Binding¶
Bind component content to dynamic data using the $ref syntax with JSON Pointer paths.
Syntax¶
{
"text": {
"$ref": "/user/personalDetails/firstName",
"fallback": "Guest",
"format": "capitalize"
}
}
Properties:
- $ref: JSON Pointer path to the data
- fallback: Value to use if data is not available
- format: Optional transformation (capitalize, uppercase, lowercase)
Available Data Contexts¶
| Path | Description | Example |
|---|---|---|
/user/personalDetails/firstName |
User's first name | "John" |
/user/personalDetails/lastName |
User's last name | "Smith" |
/user/personalDetails/emailAddress |
User's email | "[email protected]" |
/order/orderReference |
Current order reference | "ORD-12345" |
/order/totalPrice |
Order total | "99.99" |
/siteContext/siteName |
Site name | "My Store" |
/item/name |
Current item name | "Product Name" |
Example: Personalized Welcome¶
{
"type": "heading",
"props": {
"level": 1,
"text": {
"$ref": "/user/personalDetails/firstName",
"fallback": "Welcome",
"format": "capitalize"
}
}
}
Semantic Tokens¶
Style components using semantic tokens that automatically map to your theme's design system.
Typography Variants¶
| Token | Description |
|---|---|
heading-xl |
Extra large heading |
heading-lg |
Large heading |
heading-md |
Medium heading |
heading-sm |
Small heading |
body-lg |
Large body text |
body-md |
Medium body text |
body-sm |
Small body text |
button-primary |
Primary button style |
button-secondary |
Secondary button style |
link |
Link text style |
Colors¶
Base Colors
| Token | Description |
|---|---|
primary |
Primary brand color |
secondary |
Secondary color |
muted |
Muted/subtle text |
success |
Success state |
error |
Error state |
warning |
Warning state |
Light/Dark Variants
| Token | Description |
|---|---|
primary-light |
Lighter shade of primary |
primary-dark |
Darker shade of primary |
secondary-light |
Lighter shade of secondary |
secondary-dark |
Darker shade of secondary |
success-light |
Lighter shade of success |
success-dark |
Darker shade of success |
error-light |
Lighter shade of error |
error-dark |
Darker shade of error |
warning-light |
Lighter shade of warning |
warning-dark |
Darker shade of warning |
Gray Scale
| Token | Description |
|---|---|
gray-light |
Light gray |
gray |
Medium gray |
gray-dark |
Dark gray |
white |
White |
black |
Black |
Spacing¶
| Token | Description |
|---|---|
none |
No spacing |
xs |
Extra small (4px) |
sm |
Small (8px) |
md |
Medium (16px) |
lg |
Large (24px) |
xl |
Extra large (32px) |
Layout¶
| Category | Tokens |
|---|---|
padding |
none, xs, sm, md, lg, xl |
gap |
none, xs, sm, md, lg, xl |
align |
left, center, right, start, end |
justify |
start, center, end, between, around |
radius |
none, sm, md, lg, full |
shadow |
none, sm, md, lg |
Max Width¶
Constrain content width for optimal readability:
| Token | Description |
|---|---|
prose |
Optimal reading width (~65 characters) |
sm |
Small max-width (640px) |
md |
Medium max-width (768px) |
lg |
Large max-width (1024px) |
xl |
Extra large max-width (1280px) |
full |
100% max-width |
none |
No max-width constraint |
Example - Readable text container:
{
"type": "container",
"props": {
"style": { "maxWidth": "prose", "padding": "lg" }
},
"children": [...]
}
Typography Transforms¶
| Category | Tokens | Description |
|---|---|---|
transform |
uppercase, lowercase, capitalize, none |
Text case transformation |
tracking |
tight, normal, wide, wider, widest |
Letter spacing |
Background Images¶
| Category | Tokens | Description |
|---|---|---|
backgroundImage |
URL string | Image URL or media library path |
backgroundOverlay |
none, light, medium, dark, heavy |
Semi-transparent overlay opacity |
backgroundPosition |
center, top, bottom, left, right |
Image positioning |
backgroundSize |
cover, contain, auto |
Image sizing behavior |
Backgrounds¶
| Token | Description |
|---|---|
surface |
Light gray surface |
surface-light |
Very light surface |
surface-dark |
Slightly darker surface |
primary |
Primary brand color |
primary-light |
Light primary tint |
primary-dark |
Dark primary shade |
success |
Success background |
success-light |
Light success tint (for alerts) |
error |
Error background |
error-light |
Light error tint (for alerts) |
warning |
Warning background |
warning-light |
Light warning tint (for alerts) |
gray-light |
Very light gray |
gray |
Light gray |
gray-dark |
Medium gray |
transparent |
No background |
white |
Pure white |
dark |
Near-black section |
gradient-dark |
The Design Brief's brand gradient, darkened where needed for light text (a primary-tinted dark wash when the brief has no gradient) |
mesh-dark |
Dark section, tinted with the brand primary, with soft brand-colour glows |
Dark sections (Nova and the themes layered on it). dark, gradient-dark, mesh-dark,
primary and primary-dark are dark scopes, as are the dark hero presets (centered,
gradient, video-bg). Inside one, headings read white, body text light gray, overline
variants and the hero accent rule use --color-on-dark-accent, and primary buttons switch to
--color-on-dark-accent with dark text, so a navy button never disappears into a navy section.
Secondary and outline buttons become white outline buttons. You don't need "color": "white"
on headings in these sections.
How it works: the heading variants colour through var(--color-text-strong) rather than a fixed
gray, and the dark scopes re-point that token (.nova-on-dark and the nova-bg-*-dark classes in
bdgr.css). --color-on-dark-accent is compiled from the Design Brief: the first of secondary,
accent and primary that is light enough to read on dark, or a lightened primary. Without a brief
it is the theme's --color-primary-light.
AI Assistant¶
Generate JSON components from natural language descriptions using Claude AI.
Using with API Key¶
If your site has a Claude API key configured:
- Type your component description in the AI prompt field
- Click Generate
- Review and edit the generated JSON
- Save when satisfied
Example prompts: - "Create a hero section with a welcome heading, description text, and a shop now button" - "Build a two-column layout with an image on the left and text on the right" - "Make a personalized greeting that shows the user's first name"
Using without API Key (Copy/Paste Workflow)¶
If you don't have an API key configured:
- Type your component description
- Click Copy Prompt to copy the full system prompt and your request
- Paste into claude.ai or the Claude app
- Copy the JSON response
- Click Paste Response and paste the JSON
- The editor will validate and apply the component
Configuring the API Key¶
Site administrators can configure the Claude API key:
- Go to Admin → Site Configuration
- Find Claude API Key in the AI settings section
- Enter your Anthropic API key
- Save changes
Examples¶
Hero Section¶
{
"version": "1.0",
"component": {
"type": "container",
"props": {
"style": { "padding": "xl", "background": "surface" }
},
"children": [
{
"type": "column",
"props": {
"style": { "gap": "md", "align": "center" }
},
"children": [
{
"type": "heading",
"props": {
"level": 1,
"text": "Summer Collection",
"style": { "variant": "heading-xl", "align": "center" }
}
},
{
"type": "text",
"props": {
"text": "Discover our latest arrivals for the season",
"style": { "variant": "body-lg", "color": "muted", "align": "center" }
}
},
{
"type": "button",
"props": {
"text": "Shop Now",
"action": { "type": "navigate", "href": "/collections/summer" },
"style": { "variant": "button-primary" }
}
}
]
}
]
}
}
Hero with Background Image¶
Full-width hero using "layout": "fluid" for edge-to-edge coverage:
{
"version": "1.0",
"layout": "fluid",
"component": {
"type": "container",
"props": {
"style": {
"backgroundImage": "media/hero-banner.jpg",
"backgroundOverlay": "dark",
"backgroundPosition": "center",
"backgroundSize": "cover",
"padding": "xl"
}
},
"children": [
{
"type": "column",
"props": {
"style": { "gap": "md", "align": "center" }
},
"children": [
{
"type": "text",
"props": {
"text": "NEW ARRIVAL",
"style": {
"transform": "uppercase",
"tracking": "widest",
"variant": "body-sm",
"color": "white"
}
}
},
{
"type": "heading",
"props": {
"level": 1,
"text": "Winter Collection 2025",
"style": { "variant": "heading-xl", "color": "white", "align": "center" }
}
},
{
"type": "button",
"props": {
"text": "Explore Now",
"action": { "type": "navigate", "href": "/collections/winter" },
"style": { "variant": "button-primary" }
}
}
]
}
]
}
}
Two-Column Feature¶
{
"version": "1.0",
"component": {
"type": "row",
"props": {
"style": { "gap": "xl", "align": "center" }
},
"children": [
{
"type": "image",
"props": {
"src": "/images/feature.jpg",
"alt": "Feature image",
"style": { "radius": "lg", "shadow": "md" }
}
},
{
"type": "column",
"props": {
"style": { "gap": "md" }
},
"children": [
{
"type": "heading",
"props": {
"level": 2,
"text": "Quality Craftsmanship",
"style": { "variant": "heading-lg" }
}
},
{
"type": "text",
"props": {
"text": "Each product is carefully crafted with attention to detail and premium materials.",
"style": { "variant": "body-md", "color": "secondary" }
}
},
{
"type": "link",
"props": {
"text": "Learn more about our process",
"href": "/about/craftsmanship",
"style": { "variant": "link" }
}
}
]
}
]
}
}
Personalized Welcome Banner¶
{
"version": "1.0",
"component": {
"type": "container",
"props": {
"style": { "padding": "md", "background": "primary" }
},
"children": [
{
"type": "row",
"props": {
"style": { "justify": "between", "align": "center" }
},
"children": [
{
"type": "text",
"props": {
"text": {
"$ref": "/user/personalDetails/firstName",
"fallback": "Welcome back!",
"format": "capitalize"
},
"style": { "variant": "body-md" }
}
},
{
"type": "link",
"props": {
"text": "View your orders",
"href": "/account/orders",
"style": { "variant": "link" }
}
}
]
}
]
}
}
Testimonial with Blockquote¶
{
"version": "1.0",
"component": {
"type": "container",
"props": {
"style": { "padding": "lg", "background": "surface" }
},
"children": [
{
"type": "blockquote",
"props": {
"quote": "The quality of these products exceeded all my expectations. Will definitely be ordering again!",
"author": "Sarah Johnson",
"role": "Verified Customer",
"avatar": "media/avatars/sarah.jpg"
}
}
]
}
}
Feature Card with Icon¶
{
"version": "1.0",
"component": {
"type": "container",
"props": {
"style": { "padding": "lg", "background": "surface", "radius": "lg" }
},
"children": [
{
"type": "column",
"props": {
"style": { "gap": "md", "align": "center" }
},
"children": [
{
"type": "icon",
"props": {
"name": "truck",
"size": "xl",
"style": { "color": "primary" }
}
},
{
"type": "heading",
"props": {
"level": 3,
"text": "Free Shipping",
"style": { "variant": "heading-md", "align": "center" }
}
},
{
"type": "text",
"props": {
"text": "On all orders over $50. Fast, reliable delivery to your door.",
"style": { "variant": "body-sm", "color": "muted", "align": "center" }
}
}
]
}
]
}
}
Feature Grid with Icons¶
{
"version": "1.0",
"component": {
"type": "row",
"props": {
"style": { "gap": "lg" }
},
"children": [
{
"type": "column",
"props": { "width": "1/3" },
"children": [
{
"type": "column",
"props": { "style": { "gap": "sm", "align": "center" } },
"children": [
{ "type": "icon", "props": { "name": "shield", "size": "lg", "style": { "color": "success" } } },
{ "type": "heading", "props": { "level": 4, "text": "Secure Payment", "style": { "variant": "heading-sm" } } },
{ "type": "text", "props": { "text": "256-bit SSL encryption", "style": { "variant": "body-sm", "color": "muted" } } }
]
}
]
},
{
"type": "column",
"props": { "width": "1/3" },
"children": [
{
"type": "column",
"props": { "style": { "gap": "sm", "align": "center" } },
"children": [
{ "type": "icon", "props": { "name": "package", "size": "lg", "style": { "color": "primary" } } },
{ "type": "heading", "props": { "level": 4, "text": "Easy Returns", "style": { "variant": "heading-sm" } } },
{ "type": "text", "props": { "text": "30-day return policy", "style": { "variant": "body-sm", "color": "muted" } } }
]
}
]
},
{
"type": "column",
"props": { "width": "1/3" },
"children": [
{
"type": "column",
"props": { "style": { "gap": "sm", "align": "center" } },
"children": [
{ "type": "icon", "props": { "name": "phone", "size": "lg", "style": { "color": "secondary" } } },
{ "type": "heading", "props": { "level": 4, "text": "24/7 Support", "style": { "variant": "heading-sm" } } },
{ "type": "text", "props": { "text": "Always here to help", "style": { "variant": "body-sm", "color": "muted" } } }
]
}
]
}
]
}
}
Theme Support¶
JSON Components automatically adapt to your site's theme:
| Theme | Behavior |
|---|---|
| Nova | Uses CSS custom properties (--font-size-xl, --color-primary, etc.) |
| Bootstrap | Uses Bootstrap utility classes (display-4, text-primary, p-4, etc.) |
| Other themes | Falls back to Bootstrap classes |
The semantic token system ensures your components look correct regardless of which theme is active.
Best Practices¶
Structure¶
- Use
containeras the root for consistent padding - Nest
rowandcolumnfor complex layouts - Keep component hierarchies shallow (3-4 levels max)
Data Binding¶
- Always provide a
fallbackfor data bindings - Use
formatto ensure consistent text presentation - Test with logged-out users to verify fallbacks work
Styling¶
- Prefer semantic tokens over custom CSS
- Use consistent spacing tokens throughout
- Test on both desktop and mobile viewports
Performance¶
- Avoid deeply nested component trees
- Use images with appropriate sizes
- Keep JSON payloads under 50KB
Troubleshooting¶
Component Not Rendering¶
Check:
- JSON is valid (use the editor's validation)
- Component types are spelled correctly
- Required props (text, src) are provided
Data Binding Not Working¶
Check:
- Path starts with / (e.g., /user/personalDetails/firstName)
- User is logged in (for user data)
- Fallback is provided for testing
Styling Looks Wrong¶
Check:
- Token names are correct (e.g., heading-lg not large-heading)
- Theme is properly configured
- Browser developer tools for CSS conflicts
Support¶
- Documentation: This guide
- Example Components: See the examples above
- Developer Reference: Check
commerce-core/.../extensions/jsoncomponent/for implementation details - Component Catalog: View
ComponentCatalog.javafor all available components and props