Appearance
Slots and References
The CMS API supports powerful schema composition through slots and references ($ref). These features allow you to build complex, reusable, and nested content structures by combining multiple schemas.
Table of Contents
Slots
Slots allow you to define placeholder areas in a component where other content can be dynamically inserted. This enables flexible, composable content structures.
Defining a Slot
Slots are defined using a $ref with a special slot URL pattern:
json
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"items": {
"$ref": "http://access.flatnode.io/slot/items#"
}
}
}The slot name (items in this example) can be any identifier you choose.
Creating Content with Slots
When creating content, slots are optional. You can create content without providing slot data:
json
{
"DocumentId": 123,
"ComponentId": 456,
"position": "first",
"data": {
"name": "Test User"
// Note: 'items' slot is not provided - this is valid
}
}Adding Content to Slots
To add content to a slot, create a separate content instance with a parent parameter:
json
{
"DocumentId": 123,
"ComponentId": 789,
"parent": {
"HostContentId": "550e8400-e29b-41d4-a716-446655440000",
"Slot": "items"
},
"position": "first",
"data": {
"title": "Slot Item Title",
"description": "Slot Item Description"
}
}Parameters:
HostContentId- The UUID of the content instance that contains the slotSlot- The name of the slot (must match the$refin the component schema)position- Where to insert the content:"first"or"last"
Example: Simple Slot
Step 1: Create Component with Slot
bash
curl -X POST "https://access.flatnode.io/api/v1/component" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Example object with Slot Ref",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "This is the full name of the user"
},
"items": {
"$ref": "http://access.flatnode.io/slot/items#"
}
}
}'Step 2: Create Host Content (without slot data)
bash
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 456,
"position": "first",
"data": {
"name": "Test User"
}
}'Step 3: Create Slot Component
bash
curl -X POST "https://access.flatnode.io/api/v1/component" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Slot Content Component",
"type": "object",
"properties": {
"title": {
"type": "string"
},
"description": {
"type": "string"
}
}
}'Step 4: Add Content to Slot
bash
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 789,
"parent": {
"HostContentId": "550e8400-e29b-41d4-a716-446655440000",
"Slot": "items"
},
"position": "first",
"data": {
"title": "Slot Item Title",
"description": "Slot Item Description"
}
}'References
References ($ref) allow you to reuse and compose schemas in multiple ways. The API supports several types of references.
File References
Reference the built-in file reference schema for file attachments:
json
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"image": {
"$ref": "http://access.flatnode.io/file-reference.schema.json#"
}
}
}When creating content, provide file data as:
json
{
"name": "Lilalaunebär",
"image": {
"id": 123
}
}Component References (UUID)
Reference another component by its UUID:
json
{
"$schema": "http://access.flatnode.io/component.schema.json",
"title": "refref",
"type": "object",
"properties": {
"myitem": {
"$ref": "http://access.flatnode.io/uuid/550e8400-e29b-41d4-a716-446655440000"
}
}
}Example Workflow:
- Create first component and get its UUID
- Create second component that references the first
- Create content using the nested structure
bash
# Step 1: Create base component
curl -X POST "https://access.flatnode.io/api/v1/component" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Base Component",
"type": "object",
"properties": {
"name": {"type": "string"},
"image": {"$ref": "http://access.flatnode.io/file-reference.schema.json#"}
}
}'
# Response: {"data": {"Id": 456, "Uuid": "550e8400-e29b-41d4-a716-446655440000"}}
# Step 2: Create component that references the base
curl -X POST "https://access.flatnode.io/api/v1/component" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"$schema": "http://access.flatnode.io/component.schema.json",
"title": "Container Component",
"type": "object",
"properties": {
"myitem": {
"$ref": "http://access.flatnode.io/uuid/550e8400-e29b-41d4-a716-446655440000"
}
}
}'
# Step 3: Create content with nested structure
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 789,
"position": "first",
"data": {
"myitem": {
"name": "Mein Test",
"image": {"id": 321}
}
}
}'Local References
Reference definitions within the same schema using #/definitions/:
json
{
"definitions": {
"image": {
"type": "object",
"properties": {
"id": {"type": "integer"}
},
"required": ["id"]
}
},
"type": "object",
"properties": {
"image": {
"$ref": "#/definitions/image"
}
}
}Array Items with References
You can use references for array items:
json
{
"definitions": {
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"zipcode": {"type": "string"}
},
"required": ["street", "city"]
}
},
"type": "object",
"properties": {
"name": {"type": "string"},
"addresses": {
"type": "array",
"items": {"$ref": "#/definitions/address"}
}
}
}Content Example:
json
{
"name": "John Doe",
"addresses": [
{
"street": "123 Main St",
"city": "New York",
"zipcode": "10001"
},
{
"street": "456 Oak Ave",
"city": "Boston",
"zipcode": "02101"
}
]
}Circular References
Circular references are supported and useful for tree structures, linked lists, and nested hierarchies:
json
{
"definitions": {
"node": {
"type": "object",
"properties": {
"value": {"type": "string"},
"next": {"$ref": "#/definitions/node"}
}
}
},
"$ref": "#/definitions/node"
}Content Example (Linked List):
json
{
"value": "first",
"next": {
"value": "second",
"next": {
"value": "third",
"next": {
"value": "fourth"
}
}
}
}Chained References
References can be chained - one definition can reference another:
json
{
"definitions": {
"contactInfo": {
"type": "object",
"properties": {
"email": {"type": "string"},
"phone": {"type": "string"}
},
"required": ["email"]
},
"user": {
"type": "object",
"properties": {
"name": {"type": "string"},
"contact": {"$ref": "#/definitions/contactInfo"}
},
"required": ["name", "contact"]
},
"profile": {
"type": "object",
"properties": {
"user": {"$ref": "#/definitions/user"},
"bio": {"type": "string"},
"avatar": {"$ref": "http://access.flatnode.io/file-reference.schema.json#"}
},
"required": ["user"]
}
},
"type": "object",
"properties": {
"profile": {"$ref": "#/definitions/profile"}
}
}Stacking Schemas
The real power comes from combining slots and references together. You can create deeply nested, flexible content structures.
Nested Slots
Slots can be nested to create hierarchical content structures:
Example: Page → Sections → Blocks → Elements
Step 1: Create Page Component (with sections slot)
json
{
"title": "Page Component",
"type": "object",
"properties": {
"title": {"type": "string"},
"description": {"type": "string"},
"sections": {
"$ref": "http://access.flatnode.io/slot/sections#"
}
}
}Step 2: Create Section Component (with blocks slot)
json
{
"title": "Section Component",
"type": "object",
"properties": {
"heading": {"type": "string"},
"subheading": {"type": "string"},
"blocks": {
"$ref": "http://access.flatnode.io/slot/blocks#"
}
}
}Step 3: Create Block Component (with elements slot)
json
{
"title": "Block Component",
"type": "object",
"properties": {
"type": {"type": "string"},
"content": {"type": "string"},
"elements": {
"$ref": "http://access.flatnode.io/slot/elements#"
}
}
}Step 4: Build the Structure
bash
# 1. Create page content
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 1,
"position": "first",
"data": {
"title": "My Test Page",
"description": "A page with nested slots"
}
}'
# Response includes page UUID: pageUuid
# 2. Add section to page's "sections" slot
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 2,
"parent": {
"HostContentId": "pageUuid",
"Slot": "sections"
},
"position": "first",
"data": {
"heading": "First Section",
"subheading": "This section contains blocks"
}
}'
# Response includes section UUID: sectionUuid
# 3. Add block to section's "blocks" slot
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 3,
"parent": {
"HostContentId": "sectionUuid",
"Slot": "blocks"
},
"position": "first",
"data": {
"type": "text",
"content": "First block inside a section"
}
}'
# Response includes block UUID: blockUuid
# 4. Add element to block's "elements" slot
curl -X POST "https://access.flatnode.io/api/v1/content" \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"DocumentId": 123,
"ComponentId": 3,
"parent": {
"HostContentId": "blockUuid",
"Slot": "elements"
},
"position": "first",
"data": {
"type": "nested-1",
"content": "First nested block inside first block"
}
}'Combining References and Slots
You can combine component references with slots for maximum flexibility:
Example: Component with both a reference and a slot
json
{
"title": "Rich Content Block",
"type": "object",
"properties": {
"title": {"type": "string"},
"image": {
"$ref": "http://access.flatnode.io/file-reference.schema.json#"
},
"content": {
"$ref": "http://access.flatnode.io/uuid/550e8400-e29b-41d4-a716-446655440000"
},
"widgets": {
"$ref": "http://access.flatnode.io/slot/widgets#"
}
}
}This component:
- Has a direct property (
title) - References a file schema (
image) - References another component (
content) - Has a slot for dynamic content (
widgets)
Examples
Complete Example: Blog Post with Comments
Component 1: Comment (with nested comments slot)
json
{
"title": "Comment Component",
"type": "object",
"properties": {
"author": {"type": "string"},
"text": {"type": "string"},
"replies": {
"$ref": "http://access.flatnode.io/slot/replies#"
}
}
}Component 2: Blog Post (with comments slot)
json
{
"title": "Blog Post Component",
"type": "object",
"properties": {
"title": {"type": "string"},
"content": {"type": "string"},
"author": {
"$ref": "http://access.flatnode.io/uuid/user-component-uuid"
},
"featuredImage": {
"$ref": "http://access.flatnode.io/file-reference.schema.json#"
},
"comments": {
"$ref": "http://access.flatnode.io/slot/comments#"
}
}
}Workflow:
- Create blog post content
- Add comments to the post's
commentsslot - Add replies to comments'
repliesslot
This creates a nested structure: Post → Comments → Replies
Example: Product Catalog
Component: Product (with variants slot and category reference)
json
{
"title": "Product Component",
"type": "object",
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"price": {"type": "number"},
"images": {
"type": "array",
"items": {
"$ref": "http://access.flatnode.io/file-reference.schema.json#"
}
},
"category": {
"$ref": "http://access.flatnode.io/uuid/category-component-uuid"
},
"variants": {
"$ref": "http://access.flatnode.io/slot/variants#"
}
}
}Best Practices
- Use slots for dynamic, user-added content - Slots are perfect for areas where users can add/remove items
- Use references for reusable structures - References are ideal for shared schemas (user profiles, addresses, etc.)
- Combine both for maximum flexibility - Use references for fixed structure, slots for dynamic areas
- Name slots descriptively - Use clear names like
sections,blocks,itemsrather than generic names - Keep slot hierarchies shallow when possible - Deep nesting (4+ levels) can be harder to manage
- Document your slot and reference patterns - Help other developers understand your schema architecture
Response Structure
When retrieving documents with slots and references, the response includes metadata:
json
{
"_uuid": "550e8400-e29b-41d4-a716-446655440000",
"_type": "component",
"_component": {...},
"_value": {
"title": "My Page",
"sections": [
{
"_uuid": "...",
"_type": "component",
"_component": {...},
"_value": {
"heading": "Section Title",
"blocks": [...]
}
}
]
}
}Each slotted item includes _uuid, _type, _component, and _value fields for full context.