Skip to content

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:

typescript
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:

  1. 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.)
  2. Consistent Identification: Content is addressed using a URI-based system that provides consistent identification across storage backends.

  3. Extensible Metadata: The metadata system allows for flexible, domain-specific attributes while providing common fields like title and timestamps.

  4. 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:

typescript
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:

typescript
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:

typescript
// 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:

typescript
// 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:

typescript
// 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:

typescript
// 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:

typescript
interface ContentReference {
  uri: ContentURI
  type: 'embed' | 'link' | 'dependency'
}

// Content with references
const contentWithRefs: Content<string> & {
  references: ContentReference[]
} = {
  data: '# Post with Image\n\n![Image](images/sample.png)',
  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:

typescript
// 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 })

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

typescript
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

typescript
// Create a blog post with embedded images
const post = {
  data: `# My Vacation\n\n![Beach](images/beach.jpg)\n\n![Mountains](images/mountains.jpg)`,
  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`)
  }
}

Released under the MIT License.