Version 2.0

JSON Layout Engine v2

Complete Guide & Migration Documentation

Table of Contents

Overview & What's New

The RSL JSON Layout Engine v2 is a complete evolution of the v1 API, bringing powerful new capabilities while maintaining 100% backward compatibility with existing v1 configurations.

100% Backward Compatible

All existing v1 configurations will continue to work without any changes. You can upgrade to v2 immediately without breaking anything!

Key Improvements

17+ Content Types

Semantic components (card, button, badge, alert, etc.) PLUS interactive wrappers (select, modal, tooltip) AND custom HTML for anything else

Template System

Render arrays of data with {{interpolation}} - no more repetitive JSON configurations

8 Presets

Hero, features, pricing, testimonials, gallery, stats, CTA, and team layouts in one line of code

Event Handlers

Add onClick and custom events directly in your JSON configuration

Enhanced Styling

Inline styles, spacing utilities, alignment, and responsive visibility controls

Nested Layouts

Build complex layouts with grids inside grids using the new grid content type

Backward Compatibility

The v2 engine automatically detects the version in your configuration and handles it appropriately. All v1 features are fully supported:

Version Detection

If no version is specified, v1 is assumed for backward compatibility. To use v2 features, simply add version: 2 to your configuration.

Comparison: v1 vs v2

Feature v1 v2
Content Types 4 types (html, text, slot, component) 17+ semantic types + custom HTML
Template System ❌ Not available ✅ Full support with {{interpolation}}
Component Presets ❌ Not available ✅ 8 ready-to-use presets
Event Handlers ❌ Not available ✅ onClick and custom events
Inline Styles ❌ Not available ✅ Full CSS-in-JSON support
Auto-generated IDs ❌ Required ✅ Optional (auto-generated)
Nested Grids Manual HTML only ✅ Native grid content type

New Content Types

v2 introduces 14 powerful content types that cover most UI needs without writing HTML:

1. Card Component

Beautiful, flexible card layouts with images, titles, text, buttons, and badges.

Card Component Example: • JavaScript
{
  version: 2,
  layoutId: "cards",
  breakpoints: { xs: 1, md: 2, lg: 3 },
  items: [
    {
      content: {
        type: "card",
        image: "image.jpg",
        title: "Card Title",
        subtitle: "Optional subtitle",
        text: "Card description goes here",
        badge: { text: "New", variant: "success" },
        button: { text: "Learn More", variant: "primary" }
      }
    }
  ]
}

Card Variants

2. Button Component

Buttons with multiple variants, sizes, and icons.

Button Component: • JavaScript
content: {
  type: "button",
  text: "Click Me",
  variant: "primary",           // primary, secondary, success, danger, warning, info
  size: "md",                    // sm, md, lg
  icon: "fa fa-rocket",
  onClick: function(event, element) {
    alert('Button clicked!');
  }
}

3. Badge Component

Small status indicators and labels.

Badge Component: • JavaScript
content: {
  type: "badge",
  text: "New Feature",
  variant: "success"             // primary, success, warning, danger, info
}

4. Alert Component

Notification boxes with icons and optional dismiss button.

Alert Component: • JavaScript
content: {
  type: "alert",
  text: "This is an important message!",
  variant: "info",               // success, info, warning, danger
  icon: "fa fa-info-circle",
  dismissible: true
}

5. Image Component

Responsive images with captions and aspect ratio control.

Image Component: • JavaScript
content: {
  type: "image",
  src: "photo.jpg",
  alt: "Description",
  caption: "Image caption",
  aspectRatio: "16/9"            // 1/1, 4/3, 16/9, or custom
}

6-8. Typography Components

Heading, paragraph, and list components for semantic content.

Typography Components: • JavaScript
// Heading
content: {
  type: "heading",
  level: 2,                      // 1-6
  text: "Section Title"
}

// Paragraph
content: {
  type: "paragraph",
  text: "Lorem ipsum dolor sit amet..."
}

// List
content: {
  type: "list",
  items: ["Item 1", "Item 2", "Item 3"],
  ordered: false,
  icon: "fa fa-check"
}

9. Table Component

Data tables with headers and responsive styling.

Code Example: • JavaScript
content: {
  type: "table",
  headers: ["Name", "Email", "Role"],
  rows: [
    ["John Doe", "john@example.com", "Admin"],
    ["Jane Smith", "jane@example.com", "User"]
  ],
  striped: true,
  hoverable: true
}

10. Icon Component

Font Awesome icons with size and color control.

Code Example: • JavaScript
content: {
  type: "icon",
  icon: "fa fa-heart",
  size: "3x",                    // 1x, 2x, 3x, 4x, 5x
  color: "#e74c3c"
}

11-12. Layout Helpers

Divider and spacer components for layout control.

Code Example: • JavaScript
// Divider
content: {
  type: "divider",
  text: "Optional section text"
}

// Spacer
content: {
  type: "spacer",
  height: "3rem"
}

13. Link Component

Styled links with icons.

Code Example: • JavaScript
content: {
  type: "link",
  text: "Learn More",
  href: "/docs",
  icon: "fa fa-arrow-right",
  external: true                 // Opens in new tab
}

14. Grid (Nested Layout)

Create nested grids within items.

Code Example: • JavaScript
content: {
  type: "grid",
  breakpoints: { xs: 2 },
  gap: "1rem",
  items: [
    { content: { type: "card", title: "Nested Card 1" } },
    { content: { type: "card", title: "Nested Card 2" } }
  ]
}

15-17. Interactive Component Wrappers

v2 provides semantic wrappers for existing v1 interactive components. These make it much easier to use complex components without writing HTML strings.

15. Select Dropdown

Custom select dropdowns with search, multi-select, and more.

Code Example: • JavaScript
content: {
  type: "select",
  placeholder: "Choose option...",
  searchable: true,              // Enable search
  multi: false,                  // Multi-select mode
  clearable: true,               // Show clear button
  options: [
    { value: "1", label: "Option 1" },
    { value: "2", label: "Option 2", selected: true },
    { value: "3", label: "Option 3", disabled: true }
  ],
  onChange: function(e, select) {
    console.log('Selected:', select.value);
  }
}

Uses v1 Select Component

The select content type wraps the existing v1 Select component, so all v1 features work: search, multi-select, chips, keyboard navigation, etc.

16. Modal Dialog

Dialog windows and overlays with flexible content and actions.

Code Example: • JavaScript
content: {
  type: "modal",
  id: "my-modal",
  title: "Modal Title",
  size: "default",               // small, default, large
  showCloseButton: true,
  content: "Modal body content goes here",  // String or nested content
  buttons: [
    {
      text: "Cancel",
      variant: "outline",
      classes: ["close-modal"]
    },
    {
      text: "Confirm",
      variant: "primary",
      onClick: function() {
        alert('Confirmed!');
      }
    }
  ],
  buttonAlign: "right",          // left, center, right
  show: false                    // Auto-show on render
}

Advanced: Nested Content in Modal

You can use any v2 content type inside the modal body:

Code Example: • JavaScript
content: {
  type: "modal",
  id: "form-modal",
  title: "User Profile",
  content: {
    type: "card",
    title: "Edit Profile",
    text: "Update your information below"
  },
  buttons: [...]
}

17. Tooltip

Contextual tooltips with positioning and variants.

Code Example: • JavaScript
content: {
  type: "tooltip",
  text: "This is helpful information!",
  position: "top",               // top, bottom, left, right
  variant: "default",            // default, dark, light
  size: "md",                    // sm, md, lg
  trigger: '',
  // Or use triggerText for simple text
  triggerText: ''
}

Advanced: Nested Content as Trigger

You can use any v2 content type as the tooltip trigger:

Code Example: • JavaScript
content: {
  type: "tooltip",
  text: "Additional information about this button",
  position: "top",
  trigger: {
    type: "button",
    text: "Need Help?",
    variant: "outline",
    icon: "fa fa-question-circle"
  }
}

Semantic & Powerful

These v2 wrappers give you all the power of v1 components with the clean, semantic syntax of v2. No more writing HTML strings with data attributes!

Custom HTML Content

When you need complete control over markup or want to create designs not covered by the semantic content types, use type: "html". This is not a legacy feature—it's the intentional escape hatch for custom content.

When to Use Custom HTML

  • Custom-designed components (team cards, testimonials, stats)
  • Third-party widget integrations
  • Complex layouts that need precise HTML structure
  • One-off designs that don't fit semantic types
Custom HTML Content: • JavaScript
// Custom team member card
content: {
  type: "html",
  value: `
    <div class="team-card">
      <img src="photo.jpg" alt="Jane Doe">
      <div class="team-info">
        <h4>Jane Doe</h4>
        <p>Lead Designer</p>
        <div class="social-links">
          <a href="#"><i class="fab fa-linkedin"></i></a>
          <a href="#"><i class="fab fa-twitter"></i></a>
        </div>
      </div>
    </div>
  `
}

// Custom stats display
content: {
  type: "html",
  value: `
    <div class="stat-item">
      <div class="stat-number">250+</div>
      <div class="stat-label">Projects Delivered</div>
    </div>
  `
}

Combining Semantic Types with Custom HTML

The real power comes from mixing both approaches. Use semantic types for standard components and custom HTML for unique designs:

Mixed Content Types: • JavaScript
RSL.JSONLayout.renderLayout('#page', {
  version: 2,
  breakpoints: { xs: 1, md: 2, lg: 3 },
  items: [
    // Semantic: Use built-in heading type
    { content: { type: "heading", level: 2, text: "Our Team" } },

    // Custom: Team cards with unique design
    { content: { type: "html", value: `<div class="team-card">...</div>` } },
    { content: { type: "html", value: `<div class="team-card">...</div>` } },

    // Semantic: Use built-in button type
    { content: { type: "button", text: "View All", variant: "outline" } }
  ]
});

See It In Action

Check out the v2 Full Page Template for a complete example combining semantic types with custom HTML to build an entire website page.

Other Base Content Types

In addition to html, these base content types are always available:

Type Description Example
html Raw HTML markup { type: "html", value: "<div>...</div>" }
text Plain text (escaped) { type: "text", value: "Hello World" }
slot Empty placeholder { type: "slot" }
component Reference existing DOM element { type: "component", selector: "#my-widget" }

Template System

The template system eliminates repetitive JSON by allowing you to define a single item template and render it with an array of data.

Basic Example

Code Example: • JavaScript
const products = [
  { name: "Product 1", price: "99", image: "img1.jpg" },
  { name: "Product 2", price: "149", image: "img2.jpg" },
  { name: "Product 3", price: "199", image: "img3.jpg" }
];

const config = {
  version: 2,
  layoutId: "products",
  breakpoints: { xs: 1, md: 2, lg: 3 },
  template: {
    data: products,
    item: {
      content: {
        type: "card",
        image: "{{image}}",
        title: "{{name}}",
        price: "${{price}}",
        button: { text: "Buy Now", variant: "primary" }
      }
    }
  }
};

RSL.JSONLayout.renderLayout('#container', config);

Interpolation Patterns

Pro Tip

Template interpolation works on any string value in the item configuration, including nested properties, classes, and even event handlers!

Advanced Template Example

Code Example: • JavaScript
const teamMembers = [
  {
    name: "Alex Morgan",
    role: "CEO",
    bio: "Visionary leader",
    avatar: "alex.jpg",
    twitter: "#",
    linkedin: "#"
  },
  // ... more members
];

const config = {
  version: 2,
  layoutId: "team",
  breakpoints: { xs: 1, sm: 2, lg: 4 },
  template: {
    data: teamMembers,
    item: {
      content: {
        type: "card",
        image: "{{avatar}}",
        title: "{{name}}",
        subtitle: "{{role}}",
        text: "{{bio}}",
        buttons: [
          { text: "Twitter", href: "{{twitter}}", icon: "fab fa-twitter" },
          { text: "LinkedIn", href: "{{linkedin}}", icon: "fab fa-linkedin" }
        ]
      },
      style: {
        textAlign: "center"
      }
    }
  }
};

See More Examples

Explore interactive Template System examples with live demos: Template System Examples

Component Presets

Presets are pre-configured layouts for common UI patterns. Just provide your data and the preset handles the rest.

Available Presets

1. Hero

Eye-catching hero sections with title, subtitle, image, and CTA buttons.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#hero', 'hero', {
  id: "hero-section",
  title: "Welcome to Our Product",
  subtitle: "The best solution for your needs",
  image: "hero-bg.jpg",
  buttons: [
    { text: "Get Started", variant: "primary", icon: "fa fa-rocket" },
    { text: "Learn More", variant: "secondary" }
  ]
});

2. Features

Feature highlights with icons, titles, and descriptions.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#features', 'features', {
  id: "features-section",
  breakpoints: { xs: 1, md: 2, lg: 3 },
  features: [
    {
      icon: "fa fa-bolt",
      title: "Lightning Fast",
      description: "Optimized for performance"
    },
    {
      icon: "fa fa-shield-alt",
      title: "Secure",
      description: "Enterprise-grade security"
    },
    // ... more features
  ]
});

3. Pricing

Pricing tables with plans, features, and CTA buttons.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#pricing', 'pricing', {
  id: "pricing-section",
  breakpoints: { xs: 1, lg: 3 },
  plans: [
    {
      name: "Starter",
      price: "9",
      period: "month",
      description: "Perfect for individuals",
      features: ["Feature 1", "Feature 2", "Feature 3"],
      button: { text: "Get Started", variant: "primary" }
    },
    {
      name: "Professional",
      price: "29",
      period: "month",
      description: "For growing teams",
      features: ["All Starter features", "Feature 4", "Feature 5"],
      button: { text: "Get Started", variant: "primary" },
      featured: true                  // Highlights this plan
    }
    // ... more plans
  ]
});

4. Testimonials

Customer testimonials with quotes, avatars, and ratings.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#testimonials', 'testimonials', {
  id: "testimonials-section",
  breakpoints: { xs: 1, md: 2, lg: 3 },
  testimonials: [
    {
      quote: "This product changed everything for us!",
      author: "Sarah Johnson",
      role: "CEO",
      company: "TechCorp",
      avatar: "sarah.jpg",
      rating: 5
    }
    // ... more testimonials
  ]
});

5. Gallery

Image galleries with captions.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#gallery', 'gallery', {
  id: "gallery-section",
  breakpoints: { xs: 1, sm: 2, md: 3, lg: 4 },
  images: [
    { src: "img1.jpg", caption: "Beautiful landscape" },
    { src: "img2.jpg", caption: "City lights" }
    // ... more images
  ]
});

6. Stats

Key metrics and statistics display.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#stats', 'stats', {
  id: "stats-section",
  breakpoints: { xs: 2, md: 4 },
  stats: [
    { value: "10K+", label: "Active Users", icon: "fa fa-users" },
    { value: "99.9%", label: "Uptime", icon: "fa fa-server" }
    // ... more stats
  ]
});

7. CTA (Call to Action)

Conversion-focused call-to-action sections.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#cta', 'cta', {
  id: "cta-section",
  title: "Ready to Get Started?",
  subtitle: "Join thousands of satisfied customers",
  button: { text: "Sign Up Now", variant: "primary", icon: "fa fa-arrow-right" }
});

8. Team

Team member profiles with photos and social links.

Code Example: • JavaScript
RSL.JSONLayout.renderPreset('#team', 'team', {
  id: "team-section",
  breakpoints: { xs: 1, sm: 2, lg: 4 },
  members: [
    {
      name: "Alex Morgan",
      role: "CEO & Founder",
      bio: "Visionary leader with 15 years in tech",
      avatar: "alex.jpg",
      social: {
        twitter: "#",
        linkedin: "#",
        github: "#"
      }
    }
    // ... more members
  ]
});

Event Handlers

v2 allows you to add interactivity directly in your JSON configuration using event handlers.

onClick Event

Code Example: • JavaScript
content: {
  type: "button",
  text: "Click Me",
  onClick: function(event, element) {
    // event: the click event
    // element: the button element
    alert('Button clicked!');
  }
}

Counter Example

Code Example: • JavaScript
content: {
  type: "card",
  title: "Click Counter",
  text: "Clicks: 0",
  button: {
    text: "Increment",
    variant: "primary",
    onClick: function(event, element) {
      const card = element.closest('.rsl-card');
      const textEl = card.querySelector('.rsl-card-text');
      const match = textEl.textContent.match(/\d+/);
      const count = match ? parseInt(match[0]) + 1 : 1;
      textEl.textContent = `Clicks: ${count}`;
    }
  }
}

Note on JSON Serialization

Functions cannot be serialized to JSON when storing configurations in a database. For persistent configurations, use custom event names and attach handlers separately after rendering.

Custom Events

Code Example: • JavaScript
// In your config (can be stored in DB)
content: {
  type: "button",
  text: "Custom Event",
  customEvent: "myCustomEvent",
  data: { userId: 123 }
}

// After rendering, attach handler
document.addEventListener('myCustomEvent', function(event) {
  console.log('Custom event fired!', event.detail);
});

Enhanced Styling

v2 provides multiple ways to control styling beyond just CSS classes.

Inline Styles

Code Example: • JavaScript
items: [
  {
    content: { type: "card", title: "Styled Card" },
    style: {
      background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
      color: "white",
      padding: "2rem",
      borderRadius: "12px"
    }
  }
]

Spacing Utilities

Code Example: • JavaScript
items: [
  {
    content: { type: "heading", text: "Title" },
    spacing: {
      margin: "2rem 0",
      padding: "1rem"
    }
  }
]

Alignment

Code Example: • JavaScript
items: [
  {
    content: { type: "card", title: "Centered" },
    style: {
      textAlign: "center"
    }
  }
]

Responsive Visibility

Code Example: • JavaScript
items: [
  {
    content: { type: "card", title: "Desktop Only" },
    classes: ["hide-mobile", "show-desktop"]
  },
  {
    content: { type: "card", title: "Mobile Only" },
    classes: ["show-mobile", "hide-desktop"]
  }
]

Nested Layouts

Create complex layouts with grids inside grids using the new grid content type.

Code Example: • JavaScript
{
  version: 2,
  layoutId: "complex-layout",
  breakpoints: { xs: 1, lg: 2 },
  items: [
    {
      content: {
        type: "card",
        title: "Regular Card",
        text: "This is a normal card"
      }
    },
    {
      content: {
        type: "grid",
        breakpoints: { xs: 2 },
        gap: "1rem",
        items: [
          {
            content: {
              type: "card",
              title: "Nested 1",
              variant: "outlined"
            }
          },
          {
            content: {
              type: "card",
              title: "Nested 2",
              variant: "outlined"
            }
          }
        ]
      }
    }
  ]
}

Best Practices for Dynamic Rendering

When dynamically rendering layouts with JavaScript (via buttons, AJAX, etc.), you need to handle responsive column recalculation manually.

The Problem

The core layout.js file only tracks layouts that exist at DOMContentLoaded. Layouts added dynamically via renderLayout() or renderPreset() won't automatically resize when the viewport changes.

Solution 1: ResizeObserver (Recommended)

Use a ResizeObserver to watch your container for size changes. This handles window resizes, split-pane adjustments, and any container size changes.

Code Example: • JavaScript
// Setup ResizeObserver for dynamic container
const container = document.getElementById('dynamic-content');
let resizeTimeout;

if (window.ResizeObserver) {
    const observer = new ResizeObserver(entries => {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(() => {
            recalculateLayoutColumns();
        }, 100); // Debounce for performance
    });
    observer.observe(container);
}

// Recalculate columns function (mirrors layout.js logic)
function recalculateLayoutColumns() {
    const layouts = document.querySelectorAll('.slot-layout');

    layouts.forEach(layout => {
        const layoutWidth = layout.offsetWidth;

        // Get breakpoint values from data attributes
        const colsXxl = parseInt(layout.getAttribute('data-cols-xxl')) || null;
        const colsXl = parseInt(layout.getAttribute('data-cols-xl')) || null;
        const colsLg = parseInt(layout.getAttribute('data-cols-lg')) || null;
        const colsMd = parseInt(layout.getAttribute('data-cols-md')) || null;
        const colsSm = parseInt(layout.getAttribute('data-cols-sm')) || null;
        const colsXs = parseInt(layout.getAttribute('data-cols-xs')) || null;

        // Helper to find first defined value
        const firstDefined = (...values) =>
            values.find(v => v !== null && v !== undefined) ?? null;

        // Calculate columns based on width (matches layout.js breakpoints)
        let columns;
        if (layoutWidth >= 1601) {
            columns = firstDefined(colsXxl, colsXl, colsLg, colsMd, colsSm, colsXs, 4);
        } else if (layoutWidth >= 1201) {
            columns = firstDefined(colsXl, colsLg, colsMd, colsSm, colsXs, 3);
        } else if (layoutWidth >= 993) {
            columns = firstDefined(colsLg, colsMd, colsSm, colsXs, 3);
        } else if (layoutWidth >= 769) {
            columns = firstDefined(colsMd, colsSm, colsXs, 2);
        } else if (layoutWidth >= 577) {
            columns = firstDefined(colsSm, colsXs, 2);
        } else {
            columns = colsXs !== null ? colsXs : 1;
        }

        layout.style.setProperty('--dynamic-cols', columns);
    });
}

Solution 2: Window Resize Event

Alternatively, listen to window resize events. This works but won't catch container-specific resizes (like split-pane adjustments).

Code Example: • JavaScript
let resizeTimeout;

window.addEventListener('resize', function() {
    clearTimeout(resizeTimeout);
    resizeTimeout = setTimeout(() => {
        recalculateLayoutColumns();
    }, 100);
});

When to Recalculate

Call recalculateLayoutColumns() after:

Code Example: • JavaScript
// Example: Rendering layout on button click
function loadPreset(presetName) {
    const config = presets[presetName];

    // Render the layout
    RSL.JSONLayout.renderLayout('#container', config);

    // Recalculate after a short delay
    setTimeout(() => {
        recalculateLayoutColumns();
    }, 50);
}

// Example: After expanding a container
function expandPreview() {
    container.classList.add('fullwidth');

    // Wait for CSS transition (300ms) then recalculate
    setTimeout(() => {
        recalculateLayoutColumns();
    }, 350);
}
Performance Tip: Always debounce resize calculations with a 100-150ms timeout to prevent excessive recalculations during rapid resizing.

Migration Guide

No Breaking Changes

You don't need to migrate anything! All v1 configurations work in v2. This guide is for those who want to take advantage of new v2 features.

Step 1: Update Version

To use v2 features, change version: 1 to version: 2:

Code Example: • JavaScript
// Before (v1)
{
  version: 1,
  layoutId: "my-layout",
  // ...
}

// After (v2)
{
  version: 2,
  layoutId: "my-layout",
  // ...
}

Step 2: Simplify with Content Types

Replace HTML strings with semantic content types:

Code Example: • JavaScript
// Before (v1)
{
  id: "card1",
  content: {
    type: "html",
    value: `
      

Title

Description

` } } // After (v2) { content: { type: "card", title: "Title", text: "Description", button: { text: "Click", variant: "primary" } } }

Step 3: Use Templates for Repetition

Replace arrays of similar items with templates:

Code Example: • JavaScript
// Before (v1) - Repetitive
{
  items: [
    { id: "1", content: { type: "html", value: `
Product 1 - $99
` } }, { id: "2", content: { type: "html", value: `
Product 2 - $149
` } }, { id: "3", content: { type: "html", value: `
Product 3 - $199
` } } ] } // After (v2) - Template { template: { data: [ { name: "Product 1", price: "99" }, { name: "Product 2", price: "149" }, { name: "Product 3", price: "199" } ], item: { content: { type: "card", title: "{{name}}", price: "${{price}}" } } } }

Step 4: Use Presets for Common Patterns

Replace entire configurations with presets:

Code Example: • JavaScript
// Before (v1) - Manual hero configuration
{
  version: 1,
  layoutId: "hero",
  wrapper: { tag: "section", classes: ["hero"] },
  breakpoints: { xs: 1 },
  items: [{
    id: "hero-content",
    content: {
      type: "html",
      value: `
        

Welcome

Subtitle

` } }] } // After (v2) - Preset RSL.JSONLayout.renderPreset('#hero', 'hero', { title: "Welcome", subtitle: "Subtitle", buttons: [{ text: "Get Started", variant: "primary" }] });

Migration Checklist

Complete Examples

Example 1: Product Catalog

Code Example: • JavaScript
const products = [
  { id: 1, name: "Wireless Headphones", price: "99", image: "headphones.jpg", rating: "4.5/5" },
  { id: 2, name: "Smart Watch", price: "199", image: "watch.jpg", rating: "4.8/5" },
  { id: 3, name: "Laptop Stand", price: "49", image: "stand.jpg", rating: "4.3/5" }
];

RSL.JSONLayout.renderLayout('#products', {
  version: 2,
  layoutId: "product-catalog",
  breakpoints: { xs: 1, sm: 2, lg: 3 },
  gap: "2rem",
  template: {
    data: products,
    item: {
      content: {
        type: "card",
        image: "{{image}}",
        title: "{{name}}",
        text: "Rating: {{rating}}",
        price: "${{price}}",
        button: {
          text: "Add to Cart",
          variant: "primary",
          icon: "fa fa-shopping-cart",
          onClick: function(event, element) {
            const productId = {{id}};
            addToCart(productId);
          }
        }
      }
    }
  }
});

Example 2: Landing Page

Code Example: • JavaScript
// Hero
RSL.JSONLayout.renderPreset('#hero', 'hero', {
  title: "Build Amazing Products",
  subtitle: "The complete toolkit for modern development",
  image: "hero-bg.jpg",
  buttons: [
    { text: "Start Free Trial", variant: "primary" },
    { text: "Watch Demo", variant: "secondary" }
  ]
});

// Features
RSL.JSONLayout.renderPreset('#features', 'features', {
  breakpoints: { xs: 1, md: 2, lg: 3 },
  features: [
    { icon: "fa fa-bolt", title: "Fast", description: "Lightning fast performance" },
    { icon: "fa fa-shield-alt", title: "Secure", description: "Enterprise security" },
    { icon: "fa fa-mobile-alt", title: "Responsive", description: "Works everywhere" }
  ]
});

// Pricing
RSL.JSONLayout.renderPreset('#pricing', 'pricing', {
  plans: [
    {
      name: "Starter",
      price: "0",
      period: "month",
      features: ["5 Projects", "10 GB Storage"],
      button: { text: "Get Started", variant: "outline" }
    },
    {
      name: "Pro",
      price: "29",
      period: "month",
      features: ["Unlimited Projects", "100 GB Storage", "Priority Support"],
      button: { text: "Get Started", variant: "primary" },
      featured: true
    }
  ]
});

// Testimonials
RSL.JSONLayout.renderPreset('#testimonials', 'testimonials', {
  testimonials: [
    {
      quote: "This product is incredible!",
      author: "Sarah Johnson",
      role: "CEO",
      company: "TechCorp",
      avatar: "sarah.jpg",
      rating: 5
    }
  ]
});

Example 3: Dashboard

Code Example: • JavaScript
// Stats
RSL.JSONLayout.renderPreset('#stats', 'stats', {
  breakpoints: { xs: 2, md: 4 },
  stats: [
    { value: "1,234", label: "Total Users", icon: "fa fa-users" },
    { value: "$45K", label: "Revenue", icon: "fa fa-dollar-sign" },
    { value: "98%", label: "Satisfaction", icon: "fa fa-smile" },
    { value: "24/7", label: "Support", icon: "fa fa-headset" }
  ]
});

// Recent Activity (custom layout with template)
const activities = [
  { user: "John Doe", action: "created a new project", time: "2 mins ago" },
  { user: "Jane Smith", action: "uploaded a file", time: "5 mins ago" }
];

RSL.JSONLayout.renderLayout('#activity', {
  version: 2,
  layoutId: "activity-feed",
  breakpoints: { xs: 1 },
  gap: "1rem",
  template: {
    data: activities,
    item: {
      content: {
        type: "card",
        variant: "outlined",
        title: "{{user}}",
        text: "{{action}}",
        meta: "{{time}}"
      }
    }
  }
});

Learn More

Check out the Template System examples for data-driven rendering with {{interpolation}}, experiment with the live v2 playground to build your own layouts interactively, and browse the component examples for individual component usage.