Skip to content

List Field ​

The List field type allows users to create and manage lists of items within the CMS entry form. It supports various configurations for defining the structure and type of items in the list, either as a simple array or as a list of complex objects.

User Interface ​

Editor ​

The List field type has four different UI modes, depending on the configuration:

  • Complex list field:
    • With the field option: A single subfield editor is shown for each item in the list.
    • With the fields option: A group of subfield editors is shown for each item in the list.
    • With the types option: A type selector is shown for each item, along with the corresponding subfield editors. This configuration is called a variable type list. It’s useful for creating flexible content structures like page builders.
  • Simple list field:
    • Without the field, fields or types option: Each item is shown as a row with a single-line text input. Spaces and commas are treated as part of the item values instead of delimiters.

Complex list field ​

  • Each item in the list can be expanded or collapsed to show or hide its subfields.
  • Each item comes with a menu that allows users to duplicate the item, insert a new item above/below it, or remove it.
  • Users can expand or collapse the entire list using the Expand All and Collapse All buttons.
  • Each item can be reordered using the drag handle in the middle of its header:
    • Dragging the handle moves the item.
    • With the handle focused, the Up and Down arrow keys move the item one position, while Home and End send it to the top or bottom of the list.
    • On a touch screen, Move Up and Move Down buttons are shown in place of the handle, because drag and drop requires a mouse.

Simple list field ​

  • Pressing Enter in an item’s input adds a new item below it. The Add button below the list appends one to the end.
  • Each item comes with a Remove button.
  • Each item can be reordered using the drag handle at the start of its row, with the same pointer, keyboard and touch screen behavior as a complex list field.
  • The list always keeps one row, so that an empty list still offers somewhere to type. The Remove and reorder controls are disabled when a single item is left.
  • Blank rows are ignored. The stored value is the list of the remaining items, each trimmed of surrounding spaces.

Preview ​

A list view displaying all items in the list. For complex list fields, grouped subfield values are shown for each item. For simple list fields, a bulleted list of string values is displayed.

Data Type ​

An array. The elements can be strings or objects, depending on the configuration.

If the required option is set to false and the field is left empty, the value will be an empty array.

Data Validation ​

  • If the required option is set to true, the list must contain at least one item.
  • If the min and/or max options are specified, the number of items in the list must be within the defined limits.
  • For a simple list, if the pattern option is provided, the list items joined with commas, e.g. foo,bar,baz, must match the regular expression. As with Decap CMS, the pattern is tested against the whole list rather than against each item, so a pattern that describes a single item has to allow for the commas: use ^[a-z]+(,[a-z]+)*$ rather than ^[a-z]+$ to accept lowercase words only.
  • Each item in the list is validated according to the subfield definitions, if applicable.

Options ​

In addition to the common field options, the List field supports the following options:

Required Options ​

widget ​

  • Type: string
  • Default: string

Must be set to list to use the List field type.

General Options ​

default ​

  • Type: array
  • Default: []

The default value for the field when creating a new entry. The shape of the array depends on how the list is configured:

  • For a simple list without field, fields or types, an array of strings.
  • For a list with a single field, an array of values for that subfield: strings for a String subfield, objects for an Object or KeyValue subfield, and so on.
  • For a list with fields, an array of objects whose keys are the subfield names.
  • For a list with types, an array of objects, each including the typeKey property (type by default) to identify its variable type.

An item that doesn’t match the configuration — an object in a simple list, a plain value in a list with fields or types, a property that isn’t a subfield name, or a type name that isn’t one of the types — is reported as a config validation error on the login screen, because it would otherwise be silently dropped or saved to the entry as-is. See the Default Values example below for each shape.

Note that the field can also be pre-filled with comma-separated dynamic default values passed via URL query parameters. Dynamic values take precedence over the default option.

label_singular ​

  • Type: string
  • Default: The value of the label option

A label used for singular items in the list, e.g., “Member” for a list labeled “Members”. It will be displayed on the Add button and in other relevant places in the UI.

min ​

  • Type: integer
  • Default: 0

The minimum number of items required in the list. If the number of items is below this value, a validation error will be shown.

max ​

  • Type: integer
  • Default: Infinity

The maximum number of items allowed in the list. If the number of items exceeds this value, a validation error will be shown.

A list limited to one item with max: 1, which is how a single object is stored in an array, is shown like an Object field rather than a list, so users don’t have to deal with the array:

  • The item count, the list toggle and the reorder controls are hidden, and the item is kept expanded.
  • If the field is required, the item is there from the start, filled with the default values of the subfields, and it can’t be removed. It’s added to a new entry, and to an existing entry that doesn’t have one yet. This doesn’t apply to a variable type list, where the user chooses the type of the item, and can remove it to choose another.
  • If the field is optional, the Add button is shown until the item is added, and the item can be removed again.
  • A simple list field shows a single input, without the Remove and reorder controls.
  • A list holding more items than that, e.g. because the file was edited outside the CMS, is shown as a regular list, so that the extra items can be removed.

root ​

  • Type: boolean
  • Default: false

Whether to store the list at the root level of the output file, without a parent key. This is useful for creating top-level lists in files. It works with both simple and complex lists.

The root option is ignored in the following cases:

  • The collection or file contains other fields. You can still have subfields under the List field.
  • The file format is TOML, because TOML doesn’t support top-level arrays.

See the Top-Level List example below for details.

Subfield Definition ​

These options are mutually exclusive; you can only use one of them at a time:

field ​

fields ​

types ​

  • Type: array of variable type definitions

Each type definition is an object with the following properties:

  • name (string, required): The unique identifier for the type.
  • label (string, optional): The display label for the type. Defaults to name.
  • widget (string, optional): The field type for this type. It must be object if not omitted. Another field type is reported as a config validation error on the login screen.
  • summary (string, optional): A template for the summary shown on a collapsed item of this type. Overrides the field-level summary.
  • fields (array of field definitions, optional): The subfields for this type.

Subfield Options ​

These options are effective only when the field, fields, or types option is used:

summary ​

  • Type: string
  • Default: ""

A template string used to generate a summary for each item in the collapsed view. It can include subfield values using the {{subfield_name}} syntax. String transformations can be applied in this option. If omitted, the summary will be automatically generated based on the first textual subfield found.

See the Using Summary and Thumbnail example below for details.

thumbnail ​

  • Type: string
  • Default: ""

The name of an Image or File subfield to be used as the thumbnail for each list item in the collapsed view. The thumbnail is displayed next to the summary. A File subfield holding an image, video or PDF gets a thumbnail; other kinds of files are not shown. If omitted, no thumbnail will be displayed.

A subfield of a nested object can be referenced with dot notation, e.g. mobile.src. Like the summary template tags, the name can be prefixed with fields.. A name that doesn’t point to an Image or File subfield is reported as a config validation error on the login screen. With types, a name shared by the subfields of several types is accepted as long as one of them is an Image or File field.

See the Using Summary and Thumbnail example below for details.

collapsed ​

  • Type: boolean or auto
  • Default: false

Whether each item is initially collapsed in the UI. If set to auto, the UI is collapsed if an item has any filled subfields and expanded if all the subfields are empty.

minimize_collapsed ​

  • Type: boolean or auto
  • Default: false

Whether the entire list is minimized when collapsed. If set to auto, the list is minimized if any item has any filled subfields and expanded if all items are empty.

allow_add ​

  • Type: boolean
  • Default: true

Whether to allow adding new items to the list. If set to false, the Add button will be hidden, and so will the options to duplicate an item or add one above or below it. Restore Default is also disabled for the field, as it could add items.

allow_remove ​

  • Type: boolean
  • Default: true

Whether to allow removing items from the list. If set to false, the Remove button will be hidden. Clear and Restore Default are also disabled for the field, as they could remove items, and the Clear All option in the pane and editor menus leaves the list as it is.

allow_duplicate ​

  • Type: boolean
  • Default: true

Whether to allow duplicating items in the list. If set to false, the Duplicate button will be hidden.

allow_reorder ​

  • Type: boolean
  • Default: true

Whether to allow reordering of items in the list by dragging the handle in each item’s header, by using the keyboard while the handle is focused, or by using the Move Up and Move Down buttons shown on a touch screen. If set to false, the reorder controls will be hidden.

add_to_top ​

  • Type: boolean
  • Default: false

Whether to add new items to the top of the list instead of the bottom. If set to true, the Add button will appear at the top of the list.

typeKey ​

  • Type: string
  • Default: type

This option is effective only when the types option is used. It allows you to customize the name of the field that indicates the type of each item in the list. See the Variable Type example below for details.

You cannot use a key that conflicts with any of the subfield names defined in the object.

TIP

Unlike most of other config options, typeKey is camelCased.

Examples ​

Simple List ​

Configuration example:

yaml
- name: tags
  label: Tags
  widget: list
toml
[[fields]]
name = "tags"
label = "Tags"
widget = "list"
json
{
  "name": "tags",
  "label": "Tags",
  "widget": "list"
}
js
{
  name: "tags",
  label: "Tags",
  widget: "list",
}

Output example:

yaml
tags:
  - travel
  - photography
  - food
toml
tags = ["travel", "photography", "food"]
json
{
  "tags": ["travel", "photography", "food"]
}

Single Subfield ​

Configuration example:

yaml
- name: authors
  label: Authors
  widget: list
  field:
    name: author
    label: Author
    widget: string
toml
[[fields]]
name = "authors"
label = "Authors"
widget = "list"
[field]
name = "author"
label = "Author"
widget = "string"
json
{
  "name": "authors",
  "label": "Authors",
  "widget": "list",
  "field": {
    "name": "author",
    "label": "Author",
    "widget": "string"
  }
}
js
{
  name: "authors",
  label: "Authors",
  widget: "list",
  field: {
    name: "author",
    label: "Author",
    widget: "string",
  },
}

Output example:

yaml
authors:
  - Alice
  - Bob
  - Charlie
toml
authors = ["Alice", "Bob", "Charlie"]
json
{
  "authors": ["Alice", "Bob", "Charlie"]
}

Note that the name of the subfield will not appear in the output; only the values will be included in the list, just like a simple list.

Multiple Subfields ​

Configuration example:

yaml
- name: team_members
  label: Team Members
  widget: list
  fields:
    - name: name
      label: Name
      widget: string
    - name: role
      label: Role
      widget: string
toml
[[fields]]
name = "team_members"
label = "Team Members"
widget = "list"
[[fields.fields]]
name = "name"
label = "Name"
widget = "string"
[[fields.fields]]
name = "role"
label = "Role"
widget = "string"
json
{
  "name": "team_members",
  "label": "Team Members",
  "widget": "list",
  "fields": [
    {
      "name": "name",
      "label": "Name",
      "widget": "string"
    },
    {
      "name": "role",
      "label": "Role",
      "widget": "string"
    }
  ]
}
js
{
  name: "team_members",
  label: "Team Members",
  widget: "list",
  fields: [
    {
      name: "name",
      label: "Name",
      widget: "string",
    },
    {
      name: "role",
      label: "Role",
      widget: "string",
    },
  ],
}

Output example:

yaml
team_members:
  - name: Alice
    role: Developer
  - name: Bob
    role: Designer
  - name: Charlie
    role: Product Manager
toml
[[team_members]]
name = "Alice"
role = "Developer"

[[team_members]]
name = "Bob"
role = "Designer"

[[team_members]]
name = "Charlie"
role = "Product Manager"
json
{
  "team_members": [
    {
      "name": "Alice",
      "role": "Developer"
    },
    {
      "name": "Bob",
      "role": "Designer"
    },
    {
      "name": "Charlie",
      "role": "Product Manager"
    }
  ]
}

Using Summary and Thumbnail ​

Configuration example:

yaml
- name: projects
  label: Projects
  widget: list
  summary: "{{name}} - {{status}}"
  thumbnail: "image"
  fields:
    - name: name
      label: Name
      widget: string
    - name: status
      label: Status
      widget: string
    - name: image
      label: Image
      widget: image
toml
[[fields]]
name = "projects"
label = "Projects"
widget = "list"
summary = "{{name}} - {{status}}"
thumbnail = "image"
[[fields.fields]]
name = "name"
label = "Name"
widget = "string"
[[fields.fields]]
name = "status"
label = "Status"
widget = "string"
[[fields.fields]]
name = "image"
label = "Image"
widget = "image"
json
{
  "name": "projects",
  "label": "Projects",
  "widget": "list",
  "summary": "{{name}} - {{status}}",
  "thumbnail": "image",
  "fields": [
    {
      "name": "name",
      "label": "Name",
      "widget": "string"
    },
    {
      "name": "status",
      "label": "Status",
      "widget": "string"
    },
    {
      "name": "image",
      "label": "Image",
      "widget": "image"
    }
  ]
}
js
{
  name: "projects",
  label: "Projects",
  widget: "list",
  summary: "{{name}} - {{status}}",
  thumbnail: "image",
  fields: [
    {
      name: "name",
      label: "Name",
      widget: "string",
    },
    {
      name: "status",
      label: "Status",
      widget: "string",
    },
    {
      name: "image",
      label: "Image",
      widget: "image",
    },
  ],
}

Variable Type ​

The following example defines a variable type List field named items with two types: text_item and image_item. User can add either type of item to the list. These types can be mixed in any order.

yaml
- name: items
  label: Items
  widget: list
  types:
    - name: text_item
      label: Text Item
      fields:
        - name: text
          label: Text
          widget: string
    - name: image_item
      label: Image Item
      fields:
        - name: url
          label: Image URL
          widget: image
        - name: caption
          label: Caption
          widget: string
toml
[[fields]]
name = "items"
label = "Items"
widget = "list"
[[fields.types]]
label = "Text Item"
name = "text_item"
[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"
[[fields.types]]
label = "Image Item"
name = "image_item"
[[fields.types.fields]]
name = "url"
label = "Image URL"
widget = "image"
[[fields.types.fields]]
name = "caption"
label = "Caption"
widget = "string"
json
{
  "name": "items",
  "label": "Items",
  "widget": "list",
  "types": [
    {
      "label": "Text Item",
      "name": "text_item",
      "fields": [
        {
          "name": "text",
          "label": "Text",
          "widget": "string"
        }
      ]
    },
    {
      "label": "Image Item",
      "name": "image_item",
      "fields": [
        {
          "name": "url",
          "label": "Image URL",
          "widget": "image"
        },
        {
          "name": "caption",
          "label": "Caption",
          "widget": "string"
        }
      ]
    }
  ]
}
js
{
  name: "items",
  label: "Items",
  widget: "list",
  types: [
    {
      label: "Text Item",
      name: "text_item",
      fields: [
        {
          name: "text",
          label: "Text",
          widget: "string",
        },
      ],
    },
    {
      label: "Image Item",
      name: "image_item",
      fields: [
        {
          name: "url",
          label: "Image URL",
          widget: "image",
        },
        {
          name: "caption",
          label: "Caption",
          widget: "string",
        },
      ],
    },
  ],
}

Output example:

yaml
items:
  - type: text_item
    text: This is a text item.
  - type: image_item
    url: https://example.com/image.jpg
    caption: An example image.
  - type: text_item
    text: Another text item.
toml
[[items]]
type = "text_item"
text = "This is a text item."

[[items]]
type = "image_item"
url = "https://example.com/image.jpg"
caption = "An example image."

[[items]]
type = "text_item"
text = "Another text item."
json
{
  "items": [
    {
      "type": "text_item",
      "text": "This is a text item."
    },
    {
      "type": "image_item",
      "url": "https://example.com/image.jpg",
      "caption": "An example image."
    },
    {
      "type": "text_item",
      "text": "Another text item."
    }
  ]
}

Variable Type with Nested List ​

The following example defines a variable type List field named sections with two types: text_section and image_gallery. The image_gallery type contains a nested List field for multiple images.

TIP

You cannot have a List field directly under the types option; it must be nested within a type Object field, as shown in this example.

yaml
- name: sections
  label: Sections
  widget: list
  types:
    - name: text_section
      label: Text Section
      fields:
        - name: heading
          label: Heading
          widget: string
        - name: body
          label: Body
          widget: text
    - name: image_gallery
      label: Image Gallery
      fields:
        - name: title
          label: Title
          widget: string
        - name: images
          label: Images
          widget: list
          fields:
            - name: src
              label: Image URL
              widget: image
            - name: alt
              label: Alt Text
              widget: string
toml
[[fields]]
name = "sections"
label = "Sections"
widget = "list"
[[fields.types]]
name = "text_section"
label = "Text Section"
[[fields.types.fields]]
name = "heading"
label = "Heading"
widget = "string"
[[fields.types.fields]]
name = "body"
label = "Body"
widget = "text"
[[fields.types]]
name = "image_gallery"
label = "Image Gallery"
[[fields.types.fields]]
name = "title"
label = "Title"
widget = "string"
[[fields.types.fields]]
name = "images"
label = "Images"
widget = "list"
[[fields.types.fields.fields]]
name = "src"
label = "Image URL"
widget = "image"
[[fields.types.fields.fields]]
name = "alt"
label = "Alt Text"
widget = "string"
json
{
  "name": "sections",
  "label": "Sections",
  "widget": "list",
  "types": [
    {
      "name": "text_section",
      "label": "Text Section",
      "fields": [
        {
          "name": "heading",
          "label": "Heading",
          "widget": "string"
        },
        {
          "name": "body",
          "label": "Body",
          "widget": "text"
        }
      ]
    },
    {
      "name": "image_gallery",
      "label": "Image Gallery",
      "fields": [
        {
          "name": "title",
          "label": "Title",
          "widget": "string"
        },
        {
          "name": "images",
          "label": "Images",
          "widget": "list",
          "fields": [
            {
              "name": "src",
              "label": "Image URL",
              "widget": "image"
            },
            {
              "name": "alt",
              "label": "Alt Text",
              "widget": "string"
            }
          ]
        }
      ]
    }
  ]
}
js
{
  name: "sections",
  label: "Sections",
  widget: "list",
  types: [
    {
      name: "text_section",
      label: "Text Section",
      fields: [
        {
          name: "heading",
          label: "Heading",
          widget: "string",
        },
        {
          name: "body",
          label: "Body",
          widget: "text",
        },
      ],
    },
    {
      name: "image_gallery",
      label: "Image Gallery",
      fields: [
        {
          name: "title",
          label: "Title",
          widget: "string",
        },
        {
          name: "images",
          label: "Images",
          widget: "list",
          fields: [
            {
              name: "src",
              label: "Image URL",
              widget: "image",
            },
            {
              name: "alt",
              label: "Alt Text",
              widget: "string",
            },
          ],
        },
      ],
    },
  ],
}

Output example:

yaml
sections:
  - type: text_section
    heading: Welcome to Our Site
    body: This is the first section of our site.
  - type: image_gallery
    title: Our Gallery
    images:
      - src: https://example.com/image1.jpg
        alt: Image 1
      - src: https://example.com/image2.jpg
        alt: Image 2
toml
[[sections]]
type = "text_section"
heading = "Welcome to Our Site"
body = "This is the first section of our site."
[[sections]]
type = "image_gallery"
title = "Our Gallery"
[[sections.images]]
src = "https://example.com/image1.jpg"
alt = "Image 1"
[[sections.images]]
src = "https://example.com/image2.jpg"
alt = "Image 2"
json
{
  "sections": [
    {
      "type": "text_section",
      "heading": "Welcome to Our Site",
      "body": "This is the first section of our site."
    },
    {
      "type": "image_gallery",
      "title": "Our Gallery",
      "images": [
        {
          "src": "https://example.com/image1.jpg",
          "alt": "Image 1"
        },
        {
          "src": "https://example.com/image2.jpg",
          "alt": "Image 2"
        }
      ]
    }
  ]
}

Variable Type with Custom Type Key ​

By default, the type field is named type, but you can customize it using the typeKey option. Also, the fields option can be omitted if a type has no subfields.

The following example shows a simple page builder configuration with three block types: Heading, Paragraph, and Horizontal Rule.

yaml
- name: blocks
  label: Blocks
  widget: list
  typeKey: tag
  types:
    - name: h2
      label: Heading
      fields:
        - name: text
          label: Text
          widget: string
    - name: p
      label: Paragraph
      fields:
        - name: text
          label: Text
          widget: string
    - name: hr
      label: Horizontal Rule
toml
[[fields]]
name = "blocks"
label = "Blocks"
widget = "list"
typeKey = "tag"
[[fields.types]]
name = "h2"
label = "Heading"
[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"
[[fields.types]]
name = "p"
label = "Paragraph"
[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"
[[fields.types]]
name = "hr"
label = "Horizontal Rule"
json
{
  "name": "blocks",
  "label": "Blocks",
  "widget": "list",
  "typeKey": "tag",
  "types": [
    {
      "name": "h2",
      "label": "Heading",
      "fields": [
        {
          "name": "text",
          "label": "Text",
          "widget": "string"
        }
      ]
    },
    {
      "name": "p",
      "label": "Paragraph",
      "fields": [
        {
          "name": "text",
          "label": "Text",
          "widget": "string"
        }
      ]
    },
    {
      "name": "hr",
      "label": "Horizontal Rule"
    }
  ]
}
js
{
  name: "blocks",
  label: "Blocks",
  widget: "list",
  typeKey: "tag",
  types: [
    {
      name: "h2",
      label: "Heading",
      fields: [
        {
          name: "text",
          label: "Text",
          widget: "string",
        },
      ],
    },
    {
      name: "p",
      label: "Paragraph",
      fields: [
        {
          name: "text",
          label: "Text",
          widget: "string",
        },
      ],
    },
    {
      name: "hr",
      label: "Horizontal Rule",
    },
  ],
}

Output example:

yaml
blocks:
  - tag: h2
    text: Welcome to Our Site
  - tag: p
    text: This is the first paragraph of the site.
  - tag: hr
  - tag: p
    text: This is another paragraph after the horizontal rule.
toml
[[blocks]]
tag = "h2"
text = "Welcome to Our Site"
[[blocks]]
tag = "p"
text = "This is the first paragraph of the site."
[[blocks]]
tag = "hr"
[[blocks]]
tag = "p"
text = "This is another paragraph after the horizontal rule."
json
{
  "blocks": [
    {
      "tag": "h2",
      "text": "Welcome to Our Site"
    },
    {
      "tag": "p",
      "text": "This is the first paragraph of the site."
    },
    {
      "tag": "hr"
    },
    {
      "tag": "p",
      "text": "This is another paragraph after the horizontal rule."
    }
  ]
}

Top-Level List ​

It’s possible to define a List field at the top level of an output file, using the root option. The configuration below reproduces this Jekyll data file example:

yaml
collections:
  - name: data
    label: Data Files
    files:
      - name: members
        label: Member List
        file: _data/members.yml # or members.json
        icon: group
        fields:
          - name: members
            label: Members
            label_singular: Member
            widget: list
            root: true
            fields:
              - name: name
                label: Name
              - name: github
                label: GitHub account
toml
[[collections]]
name = "data"
label = "Data Files"
[[collections.files]]
name = "members"
label = "Member List"
file = "_data/members.yml"
icon = "group"
[[collections.files.fields]]
name = "members"
label = "Members"
label_singular = "Member"
widget = "list"
root = true
[[collections.files.fields.fields]]
name = "name"
label = "Name"
[[collections.files.fields.fields]]
name = "github"
label = "GitHub account"
json
{
  "collections": [
    {
      "name": "data",
      "label": "Data Files",
      "files": [
        {
          "name": "members",
          "label": "Member List",
          "file": "_data/members.yml",
          "icon": "group",
          "fields": [
            {
              "name": "members",
              "label": "Members",
              "label_singular": "Member",
              "widget": "list",
              "root": true,
              "fields": [
                {
                  "name": "name",
                  "label": "Name"
                },
                {
                  "name": "github",
                  "label": "GitHub account"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
js
{
  collections: [
    {
      name: "data",
      label: "Data Files",
      files: [
        {
          name: "members",
          label: "Member List",
          file: "_data/members.yml",
          icon: "group",
          fields: [
            {
              name: "members",
              label: "Members",
              label_singular: "Member",
              widget: "list",
              root: true,
              fields: [
                {
                  name: "name",
                  label: "Name",
                },
                {
                  name: "github",
                  label: "GitHub account",
                },
              ],
            },
          ],
        },
      ],
    },
  ],
}

It also works with a singleton. The configuration below reproduces the same data file example using a singleton:

yaml
singletons:
  - name: members
    label: Member List
    file: _data/members.yml # or members.json
    icon: group
    fields:
      - name: members
        label: Members
        label_singular: Member
        widget: list
        root: true
        fields:
          - name: name
            label: Name
          - name: github
            label: GitHub account
toml
[[singletons]]
name = "members"
label = "Member List"
file = "_data/members.yml"
icon = "group"
[[singletons.fields]]
name = "members"
label = "Members"
label_singular = "Member"
widget = "list"
root = true
[[singletons.fields.fields]]
name = "name"
label = "Name"
[[singletons.fields.fields]]
name = "github"
label = "GitHub account"
json
{
  "singletons": [
    {
      "name": "members",
      "label": "Member List",
      "file": "_data/members.yml",
      "icon": "group",
      "fields": [
        {
          "name": "members",
          "label": "Members",
          "label_singular": "Member",
          "widget": "list",
          "root": true,
          "fields": [
            {
              "name": "name",
              "label": "Name"
            },
            {
              "name": "github",
              "label": "GitHub account"
            }
          ]
        }
      ]
    }
  ]
}
js
{
  singletons: [
    {
      name: "members",
      label: "Member List",
      file: "_data/members.yml",
      icon: "group",
      fields: [
        {
          name: "members",
          label: "Members",
          label_singular: "Member",
          widget: "list",
          root: true,
          fields: [
            {
              name: "name",
              label: "Name",
            },
            {
              name: "github",
              label: "GitHub account",
            },
          ],
        },
      ],
    },
  ],
}

Output example:

yaml
- name: Alice
  github: alicehub123
- name: Bob
  github: bobgit456
- name: Charlie
  github: charliecode789
json
[
  {
    "name": "Alice",
    "github": "alicehub123"
  },
  {
    "name": "Bob",
    "github": "bobgit456"
  },
  {
    "name": "Charlie",
    "github": "charliecode789"
  }
]

As you can see, the list is stored directly at the root level of the output file, without a parent key (members). We don’t have a TOML example here because TOML format cannot represent top-level arrays; thus, the root option is ignored for TOML files.

Default Values ​

The shape of the default option follows the shape of the list. A simple list takes an array of strings:

yaml
- name: tags
  label: Tags
  widget: list
  default: [travel, photography]
toml
[[fields]]
name = "tags"
label = "Tags"
widget = "list"
default = ["travel", "photography"]
json
{
  "name": "tags",
  "label": "Tags",
  "widget": "list",
  "default": ["travel", "photography"]
}
js
{
  name: "tags",
  label: "Tags",
  widget: "list",
  default: ["travel", "photography"],
}

A list with a single field takes an array of values for that subfield — here, objects for a KeyValue subfield:

yaml
- name: attributes
  label: Attributes
  widget: list
  field:
    name: attribute
    label: Attribute
    widget: keyvalue
  default:
    - { color: red, size: large }
    - { color: blue, size: small }
toml
[[fields]]
name = "attributes"
label = "Attributes"
widget = "list"
default = [{ color = "red", size = "large" }, { color = "blue", size = "small" }]

[fields.field]
name = "attribute"
label = "Attribute"
widget = "keyvalue"
json
{
  "name": "attributes",
  "label": "Attributes",
  "widget": "list",
  "field": {
    "name": "attribute",
    "label": "Attribute",
    "widget": "keyvalue"
  },
  "default": [
    { "color": "red", "size": "large" },
    { "color": "blue", "size": "small" }
  ]
}
js
{
  name: "attributes",
  label: "Attributes",
  widget: "list",
  field: {
    name: "attribute",
    label: "Attribute",
    widget: "keyvalue",
  },
  default: [
    { color: "red", size: "large" },
    { color: "blue", size: "small" },
  ],
}

A list with fields takes an array of objects whose keys are the subfield names. A subfield left out of an item gets its own default, if any, or is left empty, just like an item added in the editor — so external is false for the first link below:

yaml
- name: links
  label: Links
  widget: list
  fields:
    - name: label
      label: Label
      widget: string
    - name: url
      label: URL
      widget: string
    - name: external
      label: External
      widget: boolean
      default: false
  default:
    - label: Home
      url: /
    - label: GitHub
      url: https://github.com/
      external: true
toml
[[fields]]
name = "links"
label = "Links"
widget = "list"
default = [
  { label = "Home", url = "/" },
  { label = "GitHub", url = "https://github.com/", external = true },
]

[[fields.fields]]
name = "label"
label = "Label"
widget = "string"

[[fields.fields]]
name = "url"
label = "URL"
widget = "string"

[[fields.fields]]
name = "external"
label = "External"
widget = "boolean"
default = false
json
{
  "name": "links",
  "label": "Links",
  "widget": "list",
  "fields": [
    { "name": "label", "label": "Label", "widget": "string" },
    { "name": "url", "label": "URL", "widget": "string" },
    { "name": "external", "label": "External", "widget": "boolean", "default": false }
  ],
  "default": [
    { "label": "Home", "url": "/" },
    { "label": "GitHub", "url": "https://github.com/", "external": true }
  ]
}
js
{
  name: "links",
  label: "Links",
  widget: "list",
  fields: [
    { name: "label", label: "Label", widget: "string" },
    { name: "url", label: "URL", widget: "string" },
    { name: "external", label: "External", widget: "boolean", default: false },
  ],
  default: [
    { label: "Home", url: "/" },
    { label: "GitHub", url: "https://github.com/", external: true },
  ],
}

A list with types takes an array of objects, each naming its variable type with the typeKey property — type unless configured otherwise — alongside the subfields of that type. The subfields of that type left out of an item are filled in the same way:

yaml
- name: sections
  label: Sections
  widget: list
  types:
    - name: heading
      label: Heading
      fields:
        - name: text
          label: Text
          widget: string
    - name: paragraph
      label: Paragraph
      fields:
        - name: body
          label: Body
          widget: markdown
  default:
    - type: heading
      text: Introduction
    - type: paragraph
toml
[[fields]]
name = "sections"
label = "Sections"
widget = "list"
default = [{ type = "heading", text = "Introduction" }, { type = "paragraph" }]

[[fields.types]]
name = "heading"
label = "Heading"

[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"

[[fields.types]]
name = "paragraph"
label = "Paragraph"

[[fields.types.fields]]
name = "body"
label = "Body"
widget = "markdown"
json
{
  "name": "sections",
  "label": "Sections",
  "widget": "list",
  "types": [
    {
      "name": "heading",
      "label": "Heading",
      "fields": [{ "name": "text", "label": "Text", "widget": "string" }]
    },
    {
      "name": "paragraph",
      "label": "Paragraph",
      "fields": [{ "name": "body", "label": "Body", "widget": "markdown" }]
    }
  ],
  "default": [{ "type": "heading", "text": "Introduction" }, { "type": "paragraph" }]
}
js
{
  name: "sections",
  label: "Sections",
  widget: "list",
  types: [
    {
      name: "heading",
      label: "Heading",
      fields: [{ name: "text", label: "Text", widget: "string" }],
    },
    {
      name: "paragraph",
      label: "Paragraph",
      fields: [{ name: "body", label: "Body", widget: "markdown" }],
    },
  ],
  default: [{ type: "heading", text: "Introduction" }, { type: "paragraph" }],
}

Each of the following would be reported as a config validation error on the login screen, because the item would otherwise be silently dropped or saved to the entry as-is:

yaml
# An object in a simple list
- name: tags
  widget: list
  default: [{ name: travel }]

# A plain value in a list with `fields`
- name: links
  widget: list
  fields: [{ name: label }, { name: url }]
  default: [Home]

# A property that isn’t a subfield name
- name: links
  widget: list
  fields: [{ name: label }, { name: url }]
  default: [{ label: Home, href: / }]

# A type name that isn’t one of the `types`
- name: sections
  widget: list
  types: [{ name: heading }, { name: paragraph }]
  default: [{ type: title }]