Collections
Define content types with TypeScript schemas and field validation. Collections are the foundation of your content model in SonicJS.
Overview
Collections define your content types using TypeScript schemas. Each collection automatically gets:
- Type-safe database schema
- Automatic API endpoints
- Admin UI for content management
- Field validation and constraints
- Version control through git
Two Types of Collections
Config-Managed Collections:
- Defined in TypeScript files (
src/collections/*.collection.ts) - Version controlled with your codebase
- Automatically synced on app startup
- Locked from editing in the admin UI (marked with "Config" badge)
- Type-safe with IDE autocomplete
UI-Created Collections:
- Created and edited through the admin interface
- Stored directly in the database
- Not version controlled
- Fully editable in the UI
- Great for rapid prototyping
Creating Collections
Basic Collection
Create a new file in src/collections/ with a .collection.ts extension:
Blog Posts Collection
// src/collections/blog-posts.collection.ts
import { CollectionConfig } from '@sonicjs-cms/core'
export const blogPostsCollection: CollectionConfig = {
name: 'blog_posts',
displayName: 'Blog Posts',
description: 'Articles and blog content',
schema: {
type: 'object',
properties: {
title: {
type: 'string',
required: true,
minLength: 3,
maxLength: 200
},
slug: {
type: 'slug',
required: true
},
content: {
type: 'richtext',
required: true
},
excerpt: {
type: 'textarea',
maxLength: 500
},
author: {
type: 'reference',
collection: 'users',
required: true
},
publishDate: {
type: 'datetime',
required: true
},
status: {
type: 'select',
enum: ['draft', 'published', 'archived'],
default: 'draft'
}
}
},
icon: '📝',
color: 'blue',
managed: true,
isActive: true,
defaultSort: 'created_at',
defaultSortOrder: 'desc',
listFields: ['title', 'author', 'publishDate', 'status'],
searchFields: ['title', 'excerpt', 'content']
}
Syncing Collections
Collections are automatically synced on server startup. You can also manually sync:
Sync Collections
# Collections auto-sync on server restart
npm run dev
# Or manually sync
npm run sync-collections
Field Types
SonicJS supports 30+ field types for building rich content schemas:
Text Fields
- Name
string- Type
- string
- Description
Single-line text input. Use for titles, names, short text.
- Name
textarea- Type
- string
- Description
Multi-line plain text. Use for descriptions, notes, long text.
- Name
email- Type
- string
- Description
Email with validation. Use for contact emails, author info.
- Name
url- Type
- string
- Description
URL with validation. Use for links, external resources.
- Name
slug- Type
- string
- Description
URL-friendly identifier. Use for page URLs, SEO paths.
- Name
color- Type
- string
- Description
Color picker. Use for theme colors, UI customization.
Rich Content
- Name
richtext- Type
- string
- Description
WYSIWYG HTML editor. Use for blog posts, articles, formatted content.
- Name
markdown- Type
- string
- Description
Markdown editor. Use for documentation, technical content.
- Name
json- Type
- object
- Description
JSON editor. Use for structured data, API responses.
Numbers and Dates
- Name
number- Type
- number
- Description
Numeric input. Use for prices, quantities, ratings.
- Name
date- Type
- string
- Description
Date picker (no time). Use for birthdays, deadlines.
- Name
datetime- Type
- string
- Description
Date and time picker. Use for publish dates, events.
Selections
- Name
select- Type
- string
- Description
Dropdown (single choice). Use for categories, status fields.
- Name
multiselect- Type
- array
- Description
Dropdown (multiple choices). Use for tags, multiple categories.
- Name
radio- Type
- string
- Description
Radio buttons. Use for status, visibility options.
- Name
checkbox- Type
- boolean
- Description
Boolean checkbox. Use for feature toggles, flags.
Media and Files
- Name
media- Type
- string
- Description
Image/media picker. Use for featured images, avatars.
- Name
file- Type
- string
- Description
File upload. Use for PDFs, documents, downloads.
Relationships
- Name
reference- Type
- string
- Description
Reference to another collection. Use for authors, categories.
- Name
array- Type
- array
- Description
Array of items. Can contain any field type.
Validation
Built-in Validators
Field Validation
export const productsCollection: CollectionConfig = {
name: 'products',
displayName: 'Products',
schema: {
type: 'object',
properties: {
name: {
type: 'string',
required: true,
minLength: 3,
maxLength: 200
},
sku: {
type: 'string',
required: true,
pattern: '^[A-Z0-9-]+$' // Only uppercase, numbers, hyphens
},
price: {
type: 'number',
required: true,
minimum: 0,
maximum: 999999
},
email: {
type: 'email',
required: true
},
url: {
type: 'url',
required: false
},
status: {
type: 'select',
enum: ['draft', 'active', 'archived'],
default: 'draft'
}
}
},
managed: true,
isActive: true
}
Validation Rules
- required - Field must have a value
- minLength / maxLength - String length constraints
- minimum / maximum - Number range constraints
- pattern - Regular expression validation
- enum - Must be one of specified values
- default - Default value if not provided
Examples
E-commerce Product
Product Collection
export const productsCollection: CollectionConfig = {
name: 'products',
displayName: 'Products',
description: 'E-commerce product catalog',
schema: {
type: 'object',
properties: {
name: {
type: 'string',
required: true
},
sku: {
type: 'string',
required: true
},
price: {
type: 'number',
required: true,
minimum: 0
},
description: {
type: 'richtext'
},
images: {
type: 'array',
items: {
type: 'media',
accept: 'image/*'
}
},
category: {
type: 'select',
enum: ['electronics', 'clothing', 'home', 'sports']
},
inStock: {
type: 'boolean',
default: true
},
tags: {
type: 'array',
items: { type: 'string' }
}
}
},
icon: '🛍️',
managed: true,
isActive: true
}
Documentation Page
Docs Collection
export const docsCollection: CollectionConfig = {
name: 'documentation',
displayName: 'Documentation',
schema: {
type: 'object',
properties: {
title: {
type: 'string',
required: true
},
slug: {
type: 'slug',
required: true
},
content: {
type: 'markdown',
required: true
},
category: {
type: 'select',
enum: ['getting-started', 'api', 'guides', 'reference']
},
order: {
type: 'number',
default: 0
},
published: {
type: 'boolean',
default: false
}
}
},
icon: '📚',
managed: true,
isActive: true
}
Event Management
Events Collection
export const eventsCollection: CollectionConfig = {
name: 'events',
displayName: 'Events',
schema: {
type: 'object',
properties: {
title: {
type: 'string',
required: true
},
description: {
type: 'richtext'
},
startDate: {
type: 'datetime',
required: true
},
endDate: {
type: 'datetime',
required: true
},
location: {
type: 'string'
},
virtualLink: {
type: 'url'
},
capacity: {
type: 'number',
minimum: 1
},
registration: {
type: 'boolean',
default: false
},
organizer: {
type: 'reference',
collection: 'users'
}
}
},
icon: '📅',
managed: true,
isActive: true
}
Using Collections
Query Content
Fetch Collection Content
// Get all content from a collection
const posts = await db.select()
.from(content)
.where(eq(content.collection_id, 'blog_posts'))
.orderBy(desc(content.created_at))
.limit(10)
// Get single content item
const post = await db.select()
.from(content)
.where(eq(content.id, postId))
.get()
// Search content
const results = await db.select()
.from(content)
.where(
and(
eq(content.collection_id, 'blog_posts'),
like(content.title, '%search%')
)
)
.all()
API Endpoints
Collections automatically get REST API endpoints:
/api/collections/{collection}/content/api/content/{id}/admin/contentAuth required/admin/content/{id}Auth required/admin/content/{id}Auth requiredBest Practices
Collection Design Tips
- Use descriptive field names that reflect your content model
- Set appropriate validation rules to maintain data quality
- Use references for relationships between collections
- Enable search on fields that users will query frequently
- Set reasonable defaults for optional fields
Performance Considerations
- Limit the number of fields in
listFieldsto improve list performance - Use appropriate field types (e.g.,
selectinstead ofstringfor fixed options) - Index frequently queried fields in your database