Reference

CMS Fields Reference

Meno's CMS stores content in JSON files organized by collection. Each collection has a schema that defines its fields, and each content item is a separate JSON file. This reference covers all field types, schema configuration, system fields, and query operators.


Field Types

Type

Description

Editor Control

Value Type

string

Single-line text

Text input

string

text

Multi-line text

Textarea

string

rich-text

Formatted HTML content

Rich text editor (Tiptap)

string (HTML)

number

Numeric value

Number input

number

boolean

True/false toggle

Checkbox

boolean

image

Image file path

Image picker

string (path)

file

Any file upload

File picker

string (path)

date

Date or datetime

Date picker

string (ISO 8601)

select

Choice from options

Select dropdown

string or string[]

reference

Link to another item

Reference picker

string (item ID) or string[]

i18n

Internationalized single-line text

Per-locale text inputs

object

i18n-text

Internationalized multi-line text

Per-locale textareas

object


Field Configuration

Every field requires a type. All other properties are optional.

Property

Type

Applies To

Description

type

CMSFieldType

All

Field type (required)

label

string

All

Display label in the editor

required

boolean

All

Whether the field must have a value

default

varies

All

Default value for new items

description

string

All

Help text shown below the field

options

string[]

select

List of allowed values

multiple

boolean

select, reference

Allow multiple selections (stores an array)

accept

string

file

MIME filter (e.g. "application/pdf", "*/*")

collection

string

reference

Target collection ID for references


Field Type Details

string

Single-line text. Use for titles, names, short labels.

{
  "title": { "type": "string", "label": "Title", "required": true },
  "slug": { "type": "string", "label": "URL Slug", "required": true }
}

text

Multi-line text. Use for descriptions, excerpts, plain-text content.

{
  "excerpt": { "type": "text", "label": "Excerpt", "description": "Short summary for listing pages" }
}

rich-text

HTML content stored as a string. Edited with a Tiptap-based rich text editor. Stored internally as Tiptap JSON and converted to HTML for rendering.

{
  "body": { "type": "rich-text", "label": "Body Content", "required": true }
}

number

Numeric value. Stored as a JavaScript number.

{
  "price": { "type": "number", "label": "Price", "default": 0 },
  "sortOrder": { "type": "number", "label": "Sort Order", "default": 0 }
}

boolean

True/false toggle.

{
  "featured": { "type": "boolean", "label": "Featured", "default": false },
  "published": { "type": "boolean", "label": "Published", "default": true }
}

image

Image file path. The editor provides an image picker.

{
  "coverImage": { "type": "image", "label": "Cover Image" },
  "thumbnail": { "type": "image", "label": "Thumbnail" }
}

file

Any file upload. Use the optional accept property to restrict allowed file types by MIME pattern. Without accept, all file types are allowed.

{
  "resume": { "type": "file", "label": "Resume", "accept": "application/pdf" },
  "attachment": { "type": "file", "label": "Attachment" }
}

date

ISO 8601 date string. The editor shows a date/datetime picker.

{
  "publishedAt": { "type": "date", "label": "Publish Date" },
  "eventDate": { "type": "date", "label": "Event Date", "required": true }
}

select

Dropdown selection. Requires an options array. Set multiple: true to allow selecting more than one value (stored as an array).

{
  "category": {
    "type": "select",
    "label": "Category",
    "options": ["tech", "design", "marketing", "business"],
    "required": true
  },
  "tags": {
    "type": "select",
    "label": "Tags",
    "options": ["featured", "new", "popular", "archived"],
    "multiple": true
  }
}

reference

Link to an item in another collection. The collection property specifies the target. Set multiple: true for arrays of references.

{
  "author": {
    "type": "reference",
    "label": "Author",
    "collection": "authors",
    "required": true
  },
  "relatedPosts": {
    "type": "reference",
    "label": "Related Posts",
    "collection": "posts",
    "multiple": true
  }
}

Referenced items are resolved at render time. Access nested fields with dot notation:

{{cms.author.name}}
{{item.author.avatar}}

i18n

Internationalized single-line text. Stores a value per locale.

{
  "title": { "type": "i18n", "label": "Title", "required": true }
}

Stored value:

{
  "title": { "en": "Hello World", "pl": "Witaj" }
}

i18n-text

Internationalized multi-line text. Same structure as i18n but with textarea inputs.

{
  "description": { "type": "i18n-text", "label": "Description" }
}

System Fields

Every CMS item automatically receives these system fields. They cannot be overridden in the schema.

Field

Type

Description

_id

string

Unique identifier (UUID)

_filename

string

Stable filename without .json extension. Never changes after creation.

_slug

string

Deprecated. Use _filename instead.

_createdAt

string

ISO timestamp of creation

_updatedAt

string

ISO timestamp of last update

_url

string

Computed URL path based on the collection's urlPattern. Available in list and template contexts.


Collection Schema

Each collection is defined by a schema in the page metadata. Schemas have these properties:

Property

Type

Required

Description

id

string

Yes

Unique collection identifier

name

string

Yes

Display name

slugField

string

Yes

Field used for URL slugs

urlPattern

string

Yes

URL template, e.g., "/blog/{{slug}}"

fields

Record<string, CMSFieldDefinition>

Yes

Field definitions

clientData

CMSClientDataConfig

No

Client-side data exposure for MenoFilter

Schema Example

{
  "id": "posts",
  "name": "Blog Posts",
  "slugField": "slug",
  "urlPattern": "/blog/{{slug}}",
  "fields": {
    "title": { "type": "string", "label": "Title", "required": true },
    "slug": { "type": "string", "label": "Slug", "required": true },
    "excerpt": { "type": "text", "label": "Excerpt" },
    "body": { "type": "rich-text", "label": "Body", "required": true },
    "coverImage": { "type": "image", "label": "Cover Image" },
    "author": { "type": "reference", "label": "Author", "collection": "authors" },
    "category": {
      "type": "select",
      "label": "Category",
      "options": ["tech", "design", "business"]
    },
    "published": { "type": "boolean", "label": "Published", "default": false },
    "publishedAt": { "type": "date", "label": "Publish Date" }
  }
}

Client Data Configuration

The clientData property configures how CMS data is exposed for client-side filtering with MenoFilter.

Property

Type

Default

Description

enabled

boolean

false

Enable client-side data exposure

strategy

`"auto" \

"inline" \

"static"`

"auto"

Delivery method

threshold

number

500

Item count threshold for auto strategy

fields

string[]

all

Subset of fields to expose (for security/size)

Strategies:

  • inline: embeds JSON directly in the HTML page (best for under 500 items)

  • static: generates a separate /data/{collection}/index.json file (best for large collections)

  • auto: chooses based on item count vs threshold


Filter Operators

Used in list node filter properties and in MenoFilter JavaScript API.

Operator

Description

Example

$eq

Equal to

{ "$eq": "tech" }

$neq

Not equal to

{ "$neq": "draft" }

$gt

Greater than

{ "$gt": 100 }

$gte

Greater than or equal

{ "$gte": 0 }

$lt

Less than

{ "$lt": 50 }

$lte

Less than or equal

{ "$lte": 999 }

$contains

String contains (case-insensitive) or array includes

{ "$contains": "featured" }

$notContains

String does not contain or array excludes

{ "$notContains": "archived" }

$startsWith

String starts with (case-insensitive)

{ "$startsWith": "intro" }

$endsWith

String ends with (case-insensitive)

{ "$endsWith": ".pdf" }

$in

Value is in the given array

{ "$in": ["tech", "design"] }

$nin

Value is not in the given array

{ "$nin": ["draft", "archived"] }

$empty

Is empty/null (true) or is not empty (false)

{ "$empty": true }

Filter in List Node

{
  "type": "list",
  "sourceType": "collection",
  "source": "posts",
  "filter": [
    { "field": "published", "operator": "eq", "value": true },
    { "field": "category", "operator": "eq", "value": "tech" }
  ],
  "sort": { "field": "publishedAt", "order": "desc" },
  "children": [
    { "type": "node", "tag": "h3", "children": "{{post.title}}" }
  ]
}

Filter can also be a single condition object or a shorthand record:

{
  "filter": { "field": "featured", "operator": "eq", "value": true }
}

CMS Template Pages

Template pages (stored in pages/templates/) use {{cms.field}} expressions to render content from the current CMS item. During static build, one HTML page is generated for each item in the collection.

{
  "type": "node",
  "tag": "article",
  "children": [
    { "type": "node", "tag": "h1", "children": "{{cms.title}}" },
    {
      "type": "node",
      "tag": "img",
      "attributes": { "src": "{{cms.coverImage}}", "alt": "{{cms.title}}" }
    },
    { "type": "embed", "html": "{{cms.body}}" },
    { "type": "node", "tag": "span", "children": "By {{cms.author.name}}" }
  ]
}

Next Steps

Building the future of digital experiences, one website at a time

© 2026 Company. All rights reserved.