Collections

What are collections?#

A collection is a content type definition. Think of it like a database table schema, but described in TypeScript. Each collection defines:

  • What fields the content has (title, body, image, etc.)
  • What types those fields are (string, richtext, media, etc.)
  • Which fields appear in the admin list view
  • Which fields are searchable

Collections are defined as TypeScript files in packages/cms/src/collections/ and are automatically synced to the database on startup.

Defining a collection#

Here's a complete collection definition:

import type { CollectionConfig } from '@flare-cms/core'
 
export default {
  name: 'blog-posts',
  displayName: 'Blog Posts',
  description: 'Manage your blog posts',
  icon: '๐Ÿ“',
 
  schema: {
    type: 'object',
    properties: {
      title: {
        type: 'string',
        title: 'Title',
        required: true,
        maxLength: 200
      },
      slug: {
        type: 'slug',
        title: 'URL Slug',
        required: true,
        maxLength: 200
      },
      excerpt: {
        type: 'textarea',
        title: 'Excerpt',
        maxLength: 500,
        helpText: 'A short summary of the post'
      },
      content: {
        type: 'quill',
        title: 'Content',
        required: true
      },
      featuredImage: {
        type: 'media',
        title: 'Featured Image'
      },
      author: {
        type: 'string',
        title: 'Author',
        required: true
      },
      publishedAt: {
        type: 'datetime',
        title: 'Published Date'
      },
      status: {
        type: 'select',
        title: 'Status',
        enum: ['draft', 'published', 'archived'],
        enumLabels: ['Draft', 'Published', 'Archived'],
        default: 'draft'
      },
      tags: {
        type: 'string',
        title: 'Tags',
        helpText: 'Comma-separated tags'
      }
    },
    required: ['title', 'slug', 'content', 'author']
  },
 
  listFields: ['title', 'author', 'status', 'publishedAt'],
  searchFields: ['title', 'excerpt', 'author'],
  defaultSort: 'createdAt',
  defaultSortOrder: 'desc'
} satisfies CollectionConfig

CollectionConfig interface#

PropertyTypeRequiredDescription
namestringYesMachine name, kebab-case (e.g., blog-posts)
displayNamestringYesHuman-readable name for the admin UI
descriptionstringNoOptional description
iconstringNoEmoji or icon name for the admin sidebar
colorstringNoHex color for the admin UI
schemaCollectionSchemaYesField definitions (see below)
managedbooleanNoIf true, can't be edited in the UI (default: true for config-based)
isActivebooleanNoEnable/disable the collection (default: true)
listFieldsstring[]NoFields shown in the admin list view
searchFieldsstring[]NoFields included in search
defaultSortstringNoDefault sort field
defaultSortOrder'asc' | 'desc'NoDefault sort direction
metadataRecord<string, any>NoArbitrary metadata

Schema definition#

The schema property uses a JSON Schema-like format:

schema: {
  type: 'object',
  properties: {
    fieldName: {
      type: 'string',      // FieldType
      title: 'Field Name', // Label in admin UI
      required: true,      // Validation
      // ...more options
    }
  },
  required: ['fieldName']  // Array of required field names
}

Field types#

Flare CMS supports 23 field types through the FieldType union:

Text fields#

TypeDescriptionUse Case
stringSingle-line text inputTitles, names, short text
textareaMulti-line text inputExcerpts, descriptions
slugURL-safe string (auto-generated)URL paths
emailEmail address with validationContact fields
urlURL with validationLinks, external references

Rich content#

TypeDescriptionUse Case
richtextBasic rich text editorSimple formatted content
markdownMarkdown editorTechnical content
quillQuill rich text editorBlog posts, articles
tinymceTinyMCE editorComplex content editing
mdxeditorMDX editorDocumentation, interactive content

Data types#

TypeDescriptionUse Case
numberNumeric inputPrices, quantities, ratings
booleanTrue/false toggleFlags, toggles
dateDate picker (no time)Birth dates, deadlines
datetimeDate and time pickerPublish dates, events
jsonRaw JSON editorStructured data, config

Selection fields#

TypeDescriptionUse Case
selectSingle-choice dropdownStatus, category
multiselectMultiple-choice dropdownTags, categories
checkboxCheckbox inputAgreement, opt-in
radioRadio button groupExclusive choices
colorColor pickerTheme colors, branding

Relational fields#

TypeDescriptionUse Case
referenceLink to another collection entryAuthor, category
mediaLink to uploaded mediaImages, files
fileFile upload fieldDocuments, downloads

Composite fields#

TypeDescriptionUse Case
arrayList of itemsRepeated elements
objectNested objectGrouped fields
Note

The select field type has a known issue: the default value in the field config is ignored by the admin UI. The field will always start empty regardless of what you set as the default.

FieldConfig options#

Each field can have these configuration options:

interface FieldConfig {
  type: FieldType           // Required โ€” the field type
  title?: string            // Label in the admin UI
  description?: string      // Help text below the field
  required?: boolean        // Is the field required?
  default?: any             // Default value
  placeholder?: string      // Placeholder text
  helpText?: string         // Additional help text
 
  // Validation
  min?: number              // Minimum value (numbers) or min length
  max?: number              // Maximum value (numbers) or max length
  minLength?: number        // Minimum string length
  maxLength?: number        // Maximum string length
  pattern?: string          // Regex pattern for validation
 
  // Selection options (select, radio, multiselect)
  enum?: string[]           // Available options
  enumLabels?: string[]     // Display labels for options
 
  // Reference fields
  collection?: string | string[]  // Target collection(s)
 
  // Composite fields (array, object)
  items?: FieldConfig             // Schema for array items
  properties?: Record<string, FieldConfig>  // Schema for nested object
  blocks?: BlockDefinitions       // Block definitions for structured content
  discriminator?: string          // Discriminator field for blocks
 
  // UI hints
  format?: string           // Display format hint
  widget?: string           // Custom widget identifier
 
  // Conditional display
  dependsOn?: string        // Show only when this field has a value
  showWhen?: any            // Show only when dependsOn equals this value
}

Registering collections#

Collections must be registered before creating the app:

import { registerCollections } from '@flare-cms/core'
import blogPostsCollection from './collections/blog-posts.collection'
import productsCollection from './collections/products.collection'
 
// Register in order โ€” parent collections before children
registerCollections([
  blogPostsCollection,
  productsCollection,
])
Warning

Collection registration order matters. If a collection has reference fields pointing to another collection, register the referenced collection first.

Auto-sync#

When autoSync: true is set in the FlareConfig, collections are automatically synced to the database on the first request after a cold start. This means:

  1. New collections are created in the collections table
  2. Changed collections have their schema updated
  3. Removed collections are cleaned up (if cleanupRemovedCollections runs)

The sync happens in the bootstrap middleware and only runs once per Worker isolate.

const config: FlareConfig = {
  collections: {
    autoSync: true  // Enable automatic collection sync
  }
}

File naming convention#

Collection files follow the pattern {name}.collection.ts and live in packages/cms/src/collections/:

src/collections/
โ”œโ”€โ”€ blog-posts.collection.ts
โ”œโ”€โ”€ products.collection.ts
โ””โ”€โ”€ team-members.collection.ts

The file name should match the collection name property (both kebab-case).