Content Model
The Content Model is the fundamental structure that defines how content is represented, accessed, and manipulated in the ReX system.
Overview
The content model provides a unified approach to content representation across different environments and storage systems. It decouples content data from its storage mechanisms, enabling consistent access patterns regardless of where or how the content is stored.
Fundamentals
Core Content Interface
At the heart of the system is the Content<T>
interface, which represents a single unit of content:
interface Content<T = string> {
// Core content data (generic to support different representations)
data: T
// MIME type of the content
contentType: string
// Optional metadata for the content
metadata: ContentMetadata
}
interface ContentMetadata {
// Basic metadata fields (all optional)
title?: string
description?: string
// Temporal metadata
createdAt?: Date
updatedAt?: Date
// Custom metadata (extensible)
[key: string]: any
}
Key characteristics of the content model:
Generic Data Type: The
Content<T>
interface uses a generic type parameter to support different data representations:Content<string>
: Text-based content (Markdown, HTML, etc.)Content<Buffer>
: Binary content (images, PDFs, etc.)Content<object>
: Structured content (JSON, etc.)
Consistent Identification: Content is addressed using a URI-based system that provides consistent identification across storage backends.
Extensible Metadata: The metadata system allows for flexible, domain-specific attributes while providing common fields like title and timestamps.
Content Type Information: The
contentType
field uses MIME types to indicate the format of the content data.
Content URI System
Content is addressed using a consistent URI system:
type ContentURI = string
// Example URIs:
// blog/post-1.md
// images/logo.png
// data/config.json
The URI system:
- Is storage-agnostic, with adapters mapping URIs to storage-specific paths
- Uses path-like notation for intuitive navigation
- Does not require protocol prefixes (unlike HTTP URLs)
- Supports relative references within the content store
Content Operations
The content system defines standard operations for interacting with content:
interface ContentOperations {
// Read content from a URI
read(uri: ContentURI): Promise<Content>
// Write content to a URI
write(uri: ContentURI, content: Content): Promise<void>
// Delete content at a URI
delete(uri: ContentURI): Promise<void>
// List content matching a pattern
list(pattern?: string): Promise<ContentURI[]>
}
These operations form the foundation of the content API and are implemented by both content stores and storage adapters.
Working With the Content Model
Content Creation
Content can be created using standard TypeScript object literals:
// Create Markdown content
const markdownContent: Content<string> = {
data: '# Hello World\nThis is a sample post.',
contentType: 'text/markdown',
metadata: {
title: 'Hello World',
createdAt: new Date(),
tags: ['sample', 'markdown'],
},
}
// Create JSON content
const jsonContent: Content<object> = {
data: { key: 'value', nested: { property: true } },
contentType: 'application/json',
metadata: {
title: 'Configuration',
updatedAt: new Date(),
},
}
Content Transformation
The content system supports transformation between different representations:
// Transform Markdown to HTML
const htmlContent = await transformContent(markdownContent, 'text/html')
// Transform structured data to JSON text
const jsonStringContent = await transformContent(
jsonContent,
'application/json'
)
Content Validation
Content can be validated against schemas:
// Define a schema for blog posts
const blogSchema = {
type: 'object',
properties: {
data: { type: 'string' },
contentType: { const: 'text/markdown' },
metadata: {
type: 'object',
required: ['title', 'createdAt'],
properties: {
title: { type: 'string', minLength: 1 },
createdAt: { type: 'string', format: 'date-time' },
tags: { type: 'array', items: { type: 'string' } },
},
},
},
}
// Validate content against the schema
const isValid = validateContent(content, blogSchema)
Advanced Concepts
Content Specialization
Different parts of the system might work with specialized content types:
// MDX content with component mapping
interface MdxContent extends Content<string> {
metadata: ContentMetadata & {
components?: Record<string, string>
}
}
// Image content with dimensions
interface ImageContent extends Content<Buffer> {
metadata: ContentMetadata & {
width?: number
height?: number
format?: string
}
}
Content References
Content can reference other content through a reference system:
interface ContentReference {
uri: ContentURI
type: 'embed' | 'link' | 'dependency'
}
// Content with references
const contentWithRefs: Content<string> & {
references: ContentReference[]
} = {
data: '# Post with Image\n\n',
contentType: 'text/markdown',
metadata: { title: 'Post with Image' },
references: [{ uri: 'images/sample.png', type: 'embed' }],
}
Derived Content
The system supports derived content - content generated from other content:
// Generate a thumbnail from an image
const thumbnail = await deriveContent(imageContent, 'thumbnail', {
width: 200,
height: 150,
})
// Generate a summary from a blog post
const summary = await deriveContent(blogPost, 'summary', { maxLength: 150 })
Related Implementations
The Content Model is implemented throughout the system:
- Content Store: The high-level API for content operations (
@lib/content/store
) - Content Adapters: Storage-specific implementations (
@lib/content/adapters
) - Content Processors: Transformation and extraction utilities (
@lib/content/processors
) - Content URI utilities: URI parsing and manipulation (
@lib/content/uri
)
Examples
Basic Content Management
import { createContentStore } from '@lib/content'
// Create a content store
const store = createContentStore()
// Create and store a Markdown document
await store.write('docs/intro.md', {
data: '# Introduction\n\nWelcome to the system!',
contentType: 'text/markdown',
metadata: {
title: 'Introduction',
createdAt: new Date(),
},
})
// Read the document
const doc = await store.read('docs/intro.md')
console.log(doc.metadata.title) // "Introduction"
// Update the document
await store.write('docs/intro.md', {
...doc,
data: doc.data + '\n\nThis content has been updated.',
metadata: {
...doc.metadata,
updatedAt: new Date(),
},
})
// Delete the document
await store.delete('docs/intro.md')
Content with References
// Create a blog post with embedded images
const post = {
data: `# My Vacation\n\n\n\n`,
contentType: 'text/markdown',
metadata: {
title: 'My Vacation',
createdAt: new Date(),
references: [
{ uri: 'images/beach.jpg', type: 'embed' },
{ uri: 'images/mountains.jpg', type: 'embed' },
],
},
}
// Write the post
await store.write('blog/vacation.md', post)
// Get all references
const references = post.metadata.references?.map(ref => ref.uri) || []
// Check if referenced content exists
for (const ref of references) {
try {
await store.read(ref)
console.log(`${ref} exists`)
} catch (error) {
console.error(`${ref} is missing`)
}
}