Collections
Schema-first structured data with 16 field types and flexible storage adapters

Overview

Collections are structured data sets defined by a schema. Think of them like database tables but stored as JSON files (or MongoDB documents in Pro mode). Each collection has a name, a URL slug, and a list of typed fields that define the shape of every entry.

Collections power the content layer of Domma CMS. Once defined, each collection automatically gets an admin UI for managing entries and a REST API for reading and writing data.

Common use cases

Blog Posts
Articles with rich text, tags, and author
Products
E-commerce catalogue with pricing and stock
Team Members
Staff profiles with bios and photos
FAQs
Question and answer pairs by category

Schema Definition

Each collection is defined in the admin panel with a name, slug, storage adapter, and a list of fields. The schema is stored as a JSON file in data/schemas/{slug}.schema.json and can be version-controlled alongside your project.

Below is the full schema for a typical Blog Posts collection. Each field specifies its name, type, and optional constraints such as required or default.

{
  "name": "Blog Posts",
  "slug": "posts",
  "adapter": "file",
  "fields": [
    { "name": "title",       "type": "string",   "required": true },
    { "name": "content",     "type": "richtext"                   },
    { "name": "published",   "type": "boolean",  "default": false },
    { "name": "publishedAt", "type": "date"                       },
    { "name": "tags",        "type": "tags"                       },
    { "name": "image",       "type": "media"                      }
  ]
}
Tip: Collection schemas can be exported from the admin panel and committed to your repository, making schema changes part of your normal development workflow.

16 Field Types

Domma CMS supports 16 built-in field types covering text, media, relational, and specialised inputs. Every field type renders an appropriate input in the admin entry editor and applies the correct validation and serialisation.

Type Description Storage
string Single-line text input String
text Multi-line textarea String
richtext Rich text editor (WYSIWYG) — outputs HTML HTML string
number Numeric value — integer or decimal Number
boolean True/false toggle switch Boolean
date Date picker (no time component) ISO 8601 date string
datetime Date and time picker ISO 8601 datetime string
select Single-choice dropdown from a defined options list String
multiselect Multiple-choice dropdown from a defined options list Array of strings
tags Free-form tag input — type and press Enter to add Array of strings
media File or image picker from the Media Library Media ID / URL string
relation Link to an entry in another collection Entry ID string
email Email address with format validation String
url URL with format validation String
color Colour picker — outputs hex value Hex string (e.g. #3b82f6)
json Raw JSON input with syntax validation Parsed JSON object/array

Creating Collections

New collections are created through the admin panel. Once saved, the collection is immediately available via the REST API and appears in the admin navigation under Collections.

Steps to create a collection

  1. Navigate to Admin panel → Collections → New Collection
  2. Enter a human-readable Name (e.g. Blog Posts)
  3. The Slug is auto-generated from the name (e.g. posts) — edit if needed
  4. Choose a Storage adapter: file (default) or mongo (Pro)
  5. Click Add Field to define each field — set its name, type, and constraints
  6. Reorder fields by dragging the row handle
  7. Click Save Collection — the schema is written to data/schemas/{slug}.schema.json

Import & export schemas

Collections can be exported as JSON schema files and re-imported into any Domma CMS instance. This is useful for sharing schemas between projects or seeding a fresh installation.

# Export a schema from the CLI
npx domma cms schema:export posts

# Import a schema file
npx domma cms schema:import ./posts.schema.json
After saving, visit Collections → Blog Posts → Entries to start adding content, or call GET /api/collections/posts/entries to read from the API.

Entry CRUD

Every collection gets a full Create, Read, Update, Delete interface in the admin panel and a matching REST API. Both surfaces are generated automatically from the field schema — no additional configuration is needed.

Admin panel operations

  • Create: Admin → Collections → [Name] → New Entry → fill fields → Save
  • Read: Entries are listed in a paginated, searchable admin table
  • Update: Click any entry row to open the edit form → make changes → Save
  • Delete: Select one or more entries → Delete (confirmation dialog shown)
  • Bulk delete: Tick the header checkbox to select all visible entries → Delete

REST API endpoints

GET    /api/collections/{slug}/entries
POST   /api/collections/{slug}/entries
GET    /api/collections/{slug}/entries/{id}
PUT    /api/collections/{slug}/entries/{id}
DELETE /api/collections/{slug}/entries/{id}

All endpoints require a valid JWT bearer token unless the collection is marked public: true.

Example: create an entry via the API

const response = await H.post('/api/collections/posts/entries', {
    title:       'Hello World',
    content:     '<p>My first post.</p>',
    published:   true,
    publishedAt: '2026-03-13',
    tags:        ['intro', 'news']
});

E.toast('Post created', { type: 'success' });

FileAdapter vs MongoAdapter

Domma CMS supports two storage adapters. The default FileAdapter requires zero configuration and is ideal for small-to-medium collections. The MongoAdapter (Pro) unlocks unlimited scale and advanced query capabilities.

Feature FileAdapter Default MongoAdapter Pro
Setup required None MongoDB connection string in .env
Storage format JSON file — data/{slug}.json MongoDB collection
Recommended entry limit Up to ~1,000 entries Unlimited
Complex queries Basic filter/sort only Full MongoDB query language
Transactions Not supported Supported
Views & aggregations Not supported Supported
Row-level access control Not supported Supported
Version-controllable Yes — commit data/ to git Via mongodump snapshots

Switching adapters

To switch an existing collection to MongoDB, update the adapter field in the schema and run the migration command. Pro mode must be active.

// In data/schemas/posts.schema.json — change:
{ "adapter": "file" }

// To:
{ "adapter": "mongo" }
# Migrate existing JSON data into MongoDB
npx domma cms migrate:adapter posts --from=file --to=mongo
Pro mode required. Attempting to use adapter: "mongo" without a valid Pro licence will fall back to the FileAdapter with a warning in the console.

8 Preset Collections

Domma CMS ships with 8 optional preset collections. These cover the most common content modelling patterns and can be seeded into a fresh installation with a single command — complete with schemas and sample data.

npm run seed
Posts slug: posts

Blog posts with title, content, author, tags, and published status.

string, richtext, relation, tags, boolean, date
Products slug: products

E-commerce items with name, price, description, image, and stock level.

string, text, number, media, boolean
Team slug: team

Team members with name, role, bio, photo, and social links.

string, text, media, url
Events slug: events

Events with title, date, location, and description.

string, datetime, text
FAQs slug: faqs

Question and answer pairs with category grouping.

string, text, select
Testimonials slug: testimonials

Customer reviews with name, company, star rating, and review text.

string, number, text, media
Gallery slug: gallery

Media gallery items with title, image, and description.

string, media, text
User Profiles slug: profiles

Extended user data that links to authenticated users via a relation field.

relation, string, media, text, url

Import & Export

Collection entries can be exported to CSV or JSON and re-imported at any time. This is useful for data migrations, backups, bulk edits in a spreadsheet, or seeding a staging environment from production data.

Export entries

  1. Admin → Collections → [Name]
  2. Click Export in the toolbar
  3. Choose CSV or JSON
  4. The file downloads immediately

Import entries

  1. Admin → Collections → [Name]
  2. Click Import in the toolbar
  3. Upload a CSV or JSON file
  4. Review the preview, then confirm

Format requirements

CSV

title,published,tags
"Hello World",true,"intro,news"
"Second Post",false,""

Column headers must match field name values exactly. Array fields are comma-separated within a quoted cell.

JSON

[
  {
    "title": "Hello World",
    "published": true,
    "tags": ["intro", "news"]
  },
  {
    "title": "Second Post",
    "published": false,
    "tags": []
  }
]

An array of entry objects. Unknown fields are ignored; missing required fields will fail validation.

Collection Shortcode

Collection entries can be embedded directly in Markdown pages using the [collection] shortcode. The shortcode fetches entries at build time (or at request time in server-rendered mode) and renders them using the collection's configured block template.

[collection slug="posts" limit="5" orderBy="publishedAt" order="desc"]
[collection slug="team" template="card"]
[collection slug="products" filter="published:true" limit="12"]

Shortcode attributes

Attribute Default Description
slug — (required) The collection slug to fetch entries from
limit 10 Maximum number of entries to render
orderBy createdAt Field name to sort by
order desc asc or desc
filter Simple equality filter: field:value — multiple filters separated by spaces
template list Block template name: list, card, grid, or a custom template path
Custom block templates are stored in templates/blocks/{name}.html and have access to the full entry object as template variables.

Public API Access

By default all collection API endpoints require a valid JWT bearer token. Collections marked public: true in their schema are also accessible via a separate unauthenticated public API — useful for reading content in front-end applications without exposing credentials.

Public API (no auth)

Available when the collection schema includes "public": true. Read-only.

GET /api/public/collections/{slug}/entries
GET /api/public/collections/{slug}/entries/{id}

Supports ?limit, ?offset, ?orderBy, and ?order query parameters.

Authenticated API (JWT required)

Full CRUD access. Pass the token in the Authorization header.

GET    /api/collections/{slug}/entries
POST   /api/collections/{slug}/entries
PUT    /api/collections/{slug}/entries/{id}
DELETE /api/collections/{slug}/entries/{id}

Example: fetch public posts with Domma HTTP

// Read public collection — no auth needed
const { entries } = await H.get('/api/public/collections/posts/entries', {
    params: { limit: 5, orderBy: 'publishedAt', order: 'desc' }
});

T.create('#posts-table', {
    data: entries,
    columns: [
        { key: 'title',       label: 'Title'      },
        { key: 'publishedAt', label: 'Published'  },
        { key: 'tags',        label: 'Tags'       }
    ]
});

Enabling public access on a collection

// In data/schemas/posts.schema.json — add:
{
  "name":    "Blog Posts",
  "slug":    "posts",
  "adapter": "file",
  "public":  true,
  "fields":  [ ... ]
}
Note: Public collections expose all entries to unauthenticated requests. Do not mark collections public if they contain sensitive or user-specific data. Use the authenticated API with scoped permissions for anything non-public.