Rendering System
How Things become Components at every level
Rendering System
The core insight of mdxui: Any Thing can render at any level.
Thing (schema.org.ai)
×
Level (Site, Page, Section, Panel, etc.)
×
Display (cards, rows, tiles, etc.)
=
ComponentThe Hierarchy
There are exactly three structural levels in each context:
| Level | Site Context | App Context | Purpose |
|---|---|---|---|
| 1 | Site | App | Root container, theme, providers |
| 2 | Page | View | Full-screen route, URL-addressable |
| 3 | Section | Panel | Region within a page/view |
Below Section/Panel, structure gives way to display modes.
Display Modes
A Section or Panel contains collections of Things. The display mode determines how those Things are laid out:
Grid Displays
| Display | Description | Best For |
|---|---|---|
cards | Card grid, responsive columns | Products, People, Projects |
tiles | Image-heavy grid, masonry-style | Photos, Portfolio, Gallery |
bento | Mixed-size grid cells | Features, Highlights |
List Displays
| Display | Description | Best For |
|---|---|---|
list | Vertical stack | Articles, Notifications |
rows | Table rows with columns | Data, Records, Admin |
feed | Social-style feed | Posts, Activity |
timeline | Chronological with dates | Events, History, Changelog |
Spatial Displays
| Display | Description | Best For |
|---|---|---|
map | Geographic markers | Locations, Directories |
calendar | Date grid | Events, Scheduling |
kanban | Columns/swim lanes | Tasks, Pipeline, Workflow |
tree | Hierarchical nodes | Files, Org charts, Categories |
Interactive Displays
| Display | Description | Best For |
|---|---|---|
carousel | Horizontal scroll | Featured, Testimonials |
gallery | Lightbox with navigation | Images, Media |
tabs | Tabbed content | Categories, Variants |
accordion | Collapsible sections | FAQ, Settings |
Thing Renderers
Each Thing type can have a renderer for each display mode:
// The renderer naming convention
type RendererName = `${ThingType}${DisplayMode}`
// Examples:
PersonCard // Person in cards display
PersonRow // Person in rows display
PersonMarker // Person on map display
ProductCard // Product in cards display
ProductTile // Product in tiles display
EventCard // Event in cards display
EventCalendarItem // Event in calendar display
AgentCard // Agent in cards display
AgentPanel // Agent as a Panel (in App)Renderer Inheritance
Renderers inherit up the schema.org type hierarchy:
Thing (base)
├── Person
│ ├── Patient
│ └── PerformingGroup → MusicGroup
├── Organization
│ ├── Corporation
│ ├── LocalBusiness → Restaurant
│ └── SportsTeam
├── Product
│ ├── Vehicle → Car
│ └── IndividualProduct
├── CreativeWork
│ ├── Article → BlogPosting
│ ├── SoftwareApplication
│ └── WebSite
├── Event
│ ├── BusinessEvent
│ └── MusicEvent
└── [AI Extensions]
├── Agent
├── Tool
├── Model
└── PromptLookup order for rendering a Car as a card:
1. CarCard // Most specific
2. VehicleCard // Parent type
3. ProductCard // Grandparent
4. ThingCard // Ultimate fallbackThe ThingRenderer Interface
Every display mode requires a base Thing renderer:
interface ThingRenderers {
// Grid displays
ThingCard: Component<ThingProps>
ThingTile: Component<ThingProps>
ThingBento: Component<ThingProps>
// List displays
ThingListItem: Component<ThingProps>
ThingRow: Component<ThingProps>
ThingFeedItem: Component<ThingProps>
ThingTimelineItem: Component<ThingProps>
// Spatial displays
ThingMarker: Component<ThingProps>
ThingCalendarItem: Component<ThingProps>
ThingKanbanCard: Component<ThingProps>
ThingTreeNode: Component<ThingProps>
// Interactive displays
ThingCarouselSlide: Component<ThingProps>
ThingGalleryItem: Component<ThingProps>
ThingTab: Component<ThingProps>
ThingAccordionItem: Component<ThingProps>
}ThingProps
Every Thing renderer receives standardized props:
interface ThingProps<T extends Thing = Thing> {
// The Thing data (from schema.org.ai)
$type: string
$id?: string
// Common Thing properties
name?: string
description?: string
image?: string | ImageObject
url?: string
// Type-specific properties spread in
...T
// Rendering context
display: DisplayMode
level: Level
index?: number
// Interaction callbacks
onClick?: () => void
onSelect?: (selected: boolean) => void
href?: string
}Collections
A Collection is a set of Things with a display mode:
// In MDX
<Collection
of="Product"
display="cards"
columns={3}
from="/api/products"
/>
// Renders as
<div className="grid grid-cols-3 gap-4">
<ProductCard {...product1} />
<ProductCard {...product2} />
<ProductCard {...product3} />
</div>Collection Props
interface CollectionProps<T extends Thing = Thing> {
// What to render
of: string // Thing type: "Product", "Person", etc.
things?: T[] // Direct data
from?: string // API endpoint to fetch from
// How to display
display: DisplayMode // "cards", "rows", "tiles", etc.
// Layout options (vary by display)
columns?: number // For grid displays
gap?: number | string
// Filtering & sorting
filter?: (thing: T) => boolean
sort?: keyof T | ((a: T, b: T) => number)
limit?: number
// Empty & loading states
empty?: ReactNode
loading?: ReactNode
// Item customization
renderItem?: (thing: T, index: number) => ReactNode
}Display Mode Components
Each display mode is also a component:
// These are equivalent:
<Collection of="Product" display="cards" />
<Cards of="Product" />
// Display-specific components
<Cards of="Product" columns={3} />
<Rows of="Product" columns={['name', 'price', 'status']} />
<Tiles of="Product" />
<List of="Product" />
<Map of="LocalBusiness" />
<Calendar of="Event" />
<Kanban of="Task" columns={['todo', 'doing', 'done']} />
<Timeline of="Event" />
<Feed of="BlogPosting" />
<Gallery of="ImageObject" />
<Carousel of="Testimonial" />
<Tree of="Category" />Putting It Together
A typical Site page:
<Page>
<Section>
<Hero {...hero} />
</Section>
<Section title="Features">
<Bento of="Feature" />
</Section>
<Section title="Testimonials">
<Carousel of="Testimonial" />
</Section>
<Section title="Team">
<Cards of="Person" columns={4} />
</Section>
<Section title="FAQ">
<Accordion of="Question" />
</Section>
</Page>A typical App view:
<View>
<Panel position="sidebar">
<Tree of="Category" />
</Panel>
<Panel position="main">
<Rows
of="Product"
columns={['name', 'category', 'price', 'status']}
selectable
/>
</Panel>
<Panel position="detail">
<ProductPanel {...selectedProduct} />
</Panel>
</View>Next: Schema.org Type Mappings
Each schema.org type has sensible defaults for:
- Which display modes it supports
- Which properties to show in each mode
- Default sorting and filtering
See Type Mappings for the complete reference.