Aphex
Schema Types

Array

Ordered lists of items with drag-and-drop reordering.

The array type stores ordered lists of items. Arrays can contain primitives (strings, numbers, booleans), images, or complex objects. Items can be reordered with drag-and-drop.

Definition

import type { ArrayField } from '@aphexcms/cms-core';
{
  name: 'tags',
  type: 'array',
  title: 'Tags',
  of: [{ type: 'string' }]
}

Properties

PropertyTypeRequiredDescription
namestringYesField identifier.
type'array'YesMust be 'array'.
titlestringYesLabel shown in the admin UI.
descriptionstringNoHelp text shown below the label.
ofTypeReference[]YesDefines what types of items the array can contain.
options{ layout?: 'grid' | 'list' }NoDisplay layout. 'grid' shows items as tiles (best for image-heavy arrays); 'list' is the default.
initialValueany[] | () => any[] | Promise<any[]>NoDefault value.
validation(Rule) => RuleNoValidation rules.

TypeReference

Each entry in the of array describes an allowed item type:

PropertyTypeRequiredDescription
typestringYesA built-in type name ('string', 'number', etc.) or the name of a registered object schema.
titlestringNoDisplay title for this type in the "Add item" dropdown.
namestringNoIdentifier for inline object definitions.
fieldsField[]NoInline field definitions. Turns this into an inline object type.

of is enforced, not advisory. Saving a document validates every item against it: an item whose _type matches nothing in of, or which is missing a required nested field, or which is a primitive where an object was declared, fails validation. An array declared with no of (or an empty one) is rejected as an invalid schema.

Item validation was not enforced before cms-core 9.8.0 — of was only used to build the "Add item" dropdown, and malformed items saved silently. Documents written under an older version may contain items that now fail to save. If a document suddenly won't save after upgrading, check its array items against their declared types.

Primitive Arrays

Arrays of simple values render inline editable rows:

String array

{
  name: 'tags',
  type: 'array',
  title: 'Tags',
  of: [{ type: 'string' }]
}

Number array

{
  name: 'scores',
  type: 'array',
  title: 'Scores',
  of: [{ type: 'number' }]
}

Boolean array

{
  name: 'flags',
  type: 'array',
  title: 'Feature Flags',
  of: [{ type: 'boolean' }]
}

Image array

Image arrays support multi-upload and an embedded media browser:

{
  name: 'gallery',
  type: 'array',
  title: 'Gallery',
  of: [{ type: 'image' }]
}

Reference Arrays

Arrays can contain references to other documents. Each item stores a { _type: 'reference', _ref, _key } wrapper — the same shape used by singular reference fields but with a stable _key for drag-and-drop.

{
  name: 'items',
  type: 'array',
  title: 'Menu Items',
  of: [{
    type: 'reference',
    to: [{ type: 'menuItem' }]
  }],
  validation: (Rule) => Rule.required().min(1)
}

The UI renders each row as a searchable inline picker (same as singular references), with drag handles for reordering. Referenced documents that aren't published will be flagged at publish time.

Stored data

{
	items: [
		{ _type: 'reference', _ref: 'menu-item-id-1', _key: 'abc' },
		{ _type: 'reference', _ref: 'menu-item-id-2', _key: 'def' }
	];
}

Generated type

// Raw (depth=0)
items: Reference<MenuItem>[];

// Resolved (depth=1)
items: MenuItem[];

Object Arrays

Arrays of objects open a modal editor when clicked:

Using a registered schema type

// First, register the object schema:
const testimonial: SchemaType = {
  type: 'object',
  name: 'testimonial',
  title: 'Testimonial',
  fields: [
    { name: 'quote', type: 'text', title: 'Quote', rows: 3 },
    { name: 'author', type: 'string', title: 'Author' },
    { name: 'role', type: 'string', title: 'Role' }
  ]
};

// Then reference it in an array:
{
  name: 'testimonials',
  type: 'array',
  title: 'Testimonials',
  of: [{ type: 'testimonial' }]
}

Inline object definition

Define the object structure directly in the array without registering a separate schema:

{
  name: 'links',
  type: 'array',
  title: 'Links',
  of: [{
    type: 'link',
    name: 'link',
    title: 'Link',
    fields: [
      { name: 'label', type: 'string', title: 'Label' },
      { name: 'url', type: 'url', title: 'URL' }
    ]
  }]
}

Multiple types

When an array accepts multiple types, the "Add item" button shows a dropdown:

{
  name: 'content',
  type: 'array',
  title: 'Content Blocks',
  of: [
    { type: 'textBlock' },
    { type: 'imageBlock' },
    { type: 'callToAction' }
  ]
}

Array Item Structure

Each item in an object array is stored with metadata:

{
  _type: 'testimonial',   // The type name
  _key: 'abc123',         // Unique key for stable ordering
  quote: '...',
  author: '...'
}

The _key is automatically generated and used for drag-and-drop stability. It is excluded from uniqueness comparisons when using unique() validation.

UI Features

  • Drag-and-drop reordering with grip handles
  • Inline editing for primitive types (strings, numbers, booleans)
  • Modal editor for object types
  • Add item button (single type) or dropdown menu (multiple types)
  • Multi-upload for image arrays
  • Media browser for selecting existing images in image arrays
  • Two-line item rows — title from the item's schema preview.select.title (or, if not configured, the first non-empty title|heading|name|label); muted subtitle below when preview.select.subtitle is configured. Dot-paths are supported (preview.select.subtitle: 'displayOptions.layout'), and a preview.prepare() function can derive title/subtitle from multiple fields. See Schemas → Preview Configuration.

Validation

// At least 1, at most 10 items
validation: (Rule) => Rule.required().min(1).max(10);

// Exactly 3 items
validation: (Rule) => Rule.length(3);

// All items must be unique
validation: (Rule) => Rule.unique();

Available rules: required(), min(count), max(count), length(count), unique(), custom(fn), error(msg), warning(msg), info(msg)

Edit on GitHub

Last updated on