JSON Schema Reference

Quick reference guide for the RSL JSON Layout format

Note: RSL supports two schema versions. V2 is recommended for new projects.

Table of Contents

V2 Schema (Recommended) V2

Complete V2 Structure

{
  // REQUIRED FIELDS
  version: 2,                     // Must be 2
  layoutId: string,               // Unique ID (e.g., "my-layout")
  breakpoints: {                  // At least one breakpoint required
    xs?: number,                  // Columns at <480px
    sm?: number,                  // Columns at >=480px
    md?: number,                  // Columns at >=768px
    lg?: number,                  // Columns at >=1024px
    xl?: number,                  // Columns at >=1280px
    xxl?: number                  // Columns at >=1600px
  },

  // OPTIONAL FIELDS
  gap?: string,                   // Gap between items (e.g., "1.5rem")
  pageMode?: boolean,             // Full page rendering mode

  // CONTENT (choose one)
  items?: LayoutItem[],           // Array of layout items
  template?: {                    // OR template system
    data: any[],                  // Array of data objects
    item: LayoutItem              // Template for each item
  },

  // ADVANCED
  gridAreas?: {                   // Named grid areas per breakpoint
    xs?: GridAreaConfig,
    sm?: GridAreaConfig,
    md?: GridAreaConfig,
    lg?: GridAreaConfig
  }
}

V2 Layout Item

Item Structure

{
  // OPTIONAL (V2 doesn't require id)
  id?: string,                    // Unique ID
  classes?: string[],             // CSS classes
  order?: number,                 // Flex order
  visible?: boolean,              // Show/hide (default: true)
  area?: string,                  // Grid area name (for gridAreas)

  // RESPONSIVE SPANNING
  span?: {                        // Column span per breakpoint
    xs?: number,
    sm?: number,
    md?: number,
    lg?: number,
    xl?: number,
    xxl?: number
  },

  // GRID POSITIONING (alternative to span)
  grid?: {
    rowStart?: number,
    rowEnd?: number,
    columnStart?: number,
    columnEnd?: number
  },

  // CONTENT
  content?: ContentConfig,        // Item content (see Content Types)

  // STYLING
  style?: {                       // Inline styles
    [property: string]: string
  },

  // DATA ATTRIBUTES
  data?: {
    [key: string]: string         // Becomes data-{key}="{value}"
  }
}

V2 Content Types

V2 supports 50+ semantic content types:

Layout Types

// Card
{ type: "card", title: string, body?: string, image?: string,
  titleIcon?: string, subtitle?: string, price?: string,
  button?: ButtonConfig, buttons?: ButtonConfig[] }

// Nested Grid
{ type: "grid", breakpoints: object, gap?: string, items: LayoutItem[] }

// Balanced (Masonry)
{ type: "balanced", breakpoints: object, gap?: string, items: LayoutItem[] }

// Divider
{ type: "divider" }

// Spacer
{ type: "spacer", height?: string }

Typography Types

// Heading
{ type: "heading", text: string, level?: 1|2|3|4|5|6 }

// Paragraph
{ type: "paragraph", text: string }

// Text
{ type: "text", value: string }

// List
{ type: "list", items: string[], ordered?: boolean }

// Badge
{ type: "badge", text: string, variant?: string }

Interactive Types

// Button
{ type: "button", text: string, variant?: string, href?: string,
  icon?: string, onClick?: string }

// Link
{ type: "link", text: string, href: string, target?: string }

// Accordion
{ type: "accordion", variant?: "classic"|"modern", allowMultiple?: boolean,
  items: { title: string, content: string, open?: boolean }[] }

// Tabs
{ type: "tabs", variant?: "horizontal"|"vertical",
  tabs: { id: string, label: string, content: string, active?: boolean }[] }

// Modal
{ type: "modal", id: string, title: string, body: string,
  trigger?: { text: string, variant?: string } }

// Select
{ type: "select", options: { value: string, label: string }[],
  placeholder?: string, multi?: boolean, searchable?: boolean }

// Toast
{ type: "toast", header?: string, body: string, position?: string,
  variant?: string, autoClose?: number }

Media Types

// Image
{ type: "image", src: string, alt: string, width?: string, height?: string }

// Thumbnail
{ type: "thumbnail", src: string, alt: string, caption?: string }

// Gallery
{ type: "gallery", images: { src: string, alt: string, caption?: string }[],
  columns?: object, gap?: string, lightbox?: boolean }

// Carousel
{ type: "carousel", slides: { src: string, alt: string, caption?: string }[],
  autoPlay?: boolean, interval?: number }

// Video Player
{ type: "video-player", src: string, poster?: string, controls?: boolean }

// Icon
{ type: "icon", name: string, size?: string }

// Iframe
{ type: "iframe", src: string, width?: string, height?: string, title?: string }

Data Display Types

// Table
{ type: "table", headers: string[], rows: any[][],
  striped?: boolean, hoverable?: boolean, responsive?: boolean }

// Smart Table
{ type: "smart-table", columns: ColumnConfig[], data: any[],
  sortable?: boolean, filterable?: boolean, pagination?: boolean }

// Chart
{ type: "chart", chartType: "bar"|"line"|"area"|"pie"|"doughnut",
  data: { label: string, value: number }[], colorScheme?: string,
  showLegend?: boolean, showGrid?: boolean }

// KPI
{ type: "kpi", title: string, value: string|number,
  trend?: "up"|"down"|"neutral", change?: string }

// Progress
{ type: "progress", value: number, max?: number, variant?: string }

// Calendar
{ type: "calendar", events?: EventConfig[], view?: "month"|"week"|"day" }

// Gantt
{ type: "gantt", tasks: TaskConfig[], startDate?: string, endDate?: string }

Navigation Types

// Navbar
{ type: "navbar", brand?: { text: string, href: string },
  items: { text: string, href: string, active?: boolean }[] }

// Breadcrumb
{ type: "breadcrumb", items: { text: string, href?: string }[] }

// Pagination
{ type: "pagination", currentPage: number, totalPages: number }

// Sidebar
{ type: "sidebar", position?: "left"|"right", items: NavItem[] }

Form Types

// Form
{ type: "form", fields: FieldConfig[], submitText?: string }

// Date Picker
{ type: "datepicker", value?: string, min?: string, max?: string }

// Filter
{ type: "filter", filters: FilterConfig[] }

// Star Rating
{ type: "star-rating", value?: number, max?: number, readonly?: boolean }

Feedback Types

// Alert
{ type: "alert", message: string, variant?: "success"|"danger"|"warning"|"info",
  dismissible?: boolean }

// Inlay Alert
{ type: "inlayAlert", message: string, variant?: string, autoDismiss?: number }

// Skeleton
{ type: "skeleton", variant?: "text"|"avatar"|"card"|"table", rows?: number }

// Announcements
{ type: "announcements", items: { title: string, message: string }[] }

Specialty Types

// Hero
{ type: "hero", title: string, subtitle?: string, backgroundImage?: string,
  buttons?: ButtonConfig[], centered?: boolean }

// Testimonial
{ type: "testimonial", quote: string, author: string,
  role?: string, avatar?: string, rating?: number }

// Pricing Table
{ type: "pricing-table", plans: PlanConfig[] }

V1 Types (Backward Compatible)

// Raw HTML
{ type: "html", value: string }

// Plain Text
{ type: "text", value: string }

// Template Slot
{ type: "slot", selector: string }

// Component Reference
{ type: "component", component: string, props?: object }

V2 Template System

Render arrays of data with {{variable}} interpolation:

Template Example

{
  version: 2,
  layoutId: "products",
  breakpoints: { xs: 1, md: 2, lg: 3 },
  template: {
    data: [
      { name: "Product 1", price: "99", image: "img1.jpg" },
      { name: "Product 2", price: "149", image: "img2.jpg" }
    ],
    item: {
      content: {
        type: "card",
        image: "{{image}}",
        title: "{{name}}",
        price: "${{price}}"
      }
    }
  }
}
Interpolation Patterns:
  • {{key}} - Replace with data[key]
  • {{index}} - Current item index (0-based)
  • {{index1}} - Current item index (1-based)

V2 Grid Areas

Named grid areas for complex layouts:

Grid Areas Example

{
  version: 2,
  layoutId: "app-layout",
  gridAreas: {
    xs: {
      areas: [["header"], ["nav"], ["main"], ["footer"]],
      columns: "1fr",
      rows: "auto auto 1fr auto"
    },
    md: {
      areas: [
        ["header", "header"],
        ["nav", "main"],
        ["footer", "footer"]
      ],
      columns: "200px 1fr",
      rows: "auto 1fr auto"
    }
  },
  items: [
    { area: "header", content: { type: "heading", text: "App" } },
    { area: "nav", content: { type: "html", value: "<nav>...</nav>" } },
    { area: "main", content: { type: "html", value: "<main>...</main>" } },
    { area: "footer", content: { type: "text", value: "Footer" } }
  ]
}

V1 Schema (Legacy) V1

Complete V1 Structure

{
  // REQUIRED FIELDS
  version: 1,                     // Must be 1
  layoutId: string,               // Unique ID
  breakpoints: {                  // At least one required
    xs?: number,                  // Columns at <576px
    sm?: number,                  // Columns at >=576px
    md?: number,                  // Columns at >=768px
    lg?: number,                  // Columns at >=992px
    xl?: number,                  // Columns at >=1200px
    xxl?: number                  // Columns at >=1400px
  },
  items: LayoutItem[],            // Array of items (required)

  // OPTIONAL FIELDS
  gap?: string,                   // Gap between items
  wrapper?: {                     // Parent container element
    tag?: string,
    id?: string,
    classes?: string[],
    data?: object
  }
}

V1 Layout Item

{
  // REQUIRED
  id: string,                     // Unique ID (required in V1)

  // OPTIONAL
  classes?: string[],             // CSS classes
  order?: number,                 // Flex order
  visible?: boolean,              // Show/hide (default: true)

  grid?: {                        // Grid positioning
    rowStart?: number,
    rowEnd?: number,
    columnStart?: number,
    columnEnd?: number
  },

  content?: {                     // V1 content types only
    type: "html" | "text" | "slot" | "component",
    value?: string,               // For "html" or "text"
    selector?: string,            // For "slot"
    component?: string,           // For "component"
    props?: object                // For "component"
  },

  data?: {                        // Data attributes
    [key: string]: string
  }
}

Quick Comparison

Feature V1 V2
Version number 1 2
Item id Required Optional
Content types 4 (html, text, slot, component) 50+ semantic types
Template system No Yes ({{variable}})
Responsive spans No Yes (span: { xs: 1, md: 2 })
Grid areas No Yes
Page mode No Yes

Validation

V2 Validation

const result = RSL.JSONLayout.validateSchema(config);
if (!result.valid) {
  console.error('Errors:', result.errors);
  console.warn('Warnings:', result.warnings);
}
Common V2 Errors:
// ❌ Missing layoutId
{ version: 2, breakpoints: { xs: 1 }, items: [] }
// Error: layoutId is required

// ❌ Invalid content type
{ content: { type: "invalid" } }
// Warning: unknown content type "invalid"

// ❌ Template without data
{ template: { item: { content: { type: "card" } } } }
// Error: template.data is required

Migration: V1 to V2

Before (V1)

{
  version: 1,
  layoutId: "cards",
  breakpoints: { xs: 1, md: 3 },
  items: [{
    id: "card-1",
    content: {
      type: "html",
      value: "<div class='card'><h3>Title</h3><p>Body</p></div>"
    }
  }]
}

After (V2 - Semantic)

{
  version: 2,
  layoutId: "cards",
  breakpoints: { xs: 1, md: 3 },
  items: [{
    content: {
      type: "card",
      title: "Title",
      body: "Body"
    }
  }]
}

Resources

Version: 2.0.0  |  Last Updated: December 2025  |  Schema Versions: 1, 2