Custom Fields

The _admin.yml file lives at the root of your site's source directory and defines how editable content is presented to site owners. It controls which files are editable, what form fields appear, and how the site's Jekyll config is managed across environments.

Top-Level Sections

collections:   # Editable content collections
forms:         # Form submission handling (optional)
roles:         # User role definitions (optional)

All sections are optional. An _admin.yml is not required.

Collections

Collections define groups of editable content. There are two types: file collections (edit specific named files) and folder collections (edit a directory of documents).

collections:
  - name: data
    files: [...]       # File collection

  - name: posts
    folder: _posts     # Folder collection
    create: true
    fields: [...]

File Collections

Edit specific, named files. Used for single pages and data files with unique structures.

collections:
  - name: pages
    label: Pages
    basedir: _pages
    i18n: [en, es]
    files:
      - file: frontpage.html
        label: Front Page
        readonly:
          - layout
          - permalink
        fields:
          - name: title
            widget: string
          - name: hero
            widget: object
            fields:
              - { name: heading, widget: trix }
              - { name: description, widget: textarea }

File collection properties:

  • name (required) — Unique identifier for the collection.
  • label — Display name. Auto-generated from name if omitted.
  • files (required) — List of file definitions (see below).
  • basedir — Common base directory for all files. When set, file paths are relative to it (e.g., basedir: _pages + file: frontpage.html_pages/frontpage.html).
  • i18n — List of language codes. First language is the default. Non-default languages store files under <lang>/ relative to basedir.
  • protected — If true, built pages require authentication to view.

File definitions

Each entry in files describes one editable file:

  • file (required) — Path to the file (relative to basedir, or absolute like _data/hero.yml).
  • name — Identifier. Defaults to the filename stem.
  • label — Display name. Auto-generated from name if omitted.
  • fields (required) — List of field definitions.
  • readonly — List of field names whose values are preserved from the source file and not shown in the editor.

Supported file formats: .html, .md, .yml, .yaml, .json.

For frontmatter files (.html, .md), the field named content maps to the body text below the YAML front matter.

Folder Collections

Edit a directory of documents that share the same field structure. New documents can be created from the CMS.

collections:
  - name: projects
    label: Projects
    label_singular: Project
    folder: _projects
    create: true
    output: true
    path: ""
    protected: true
    i18n: [en, es]
    permalink: /projects/:title/
    i18n_permalinks:
      es: /es/proyectos/:title/
    readonly:
      - name: layout
        value: project
      - name: lang
        template: ""
      - name: ref
        template: "-"
    fields:
      - name: title
        widget: string
      - name: content
        widget: trix

Folder collection properties:

  • name (required) — Unique identifier.
  • label — Display name. Auto-generated from name if omitted.
  • label_singular — Singular display name (e.g., "Project"). If omitted, strips trailing "s" from label.
  • folder (required) — Directory path relative to site root (e.g., _posts, _projects).
  • create (required) — Whether users can create new documents.
  • fields (required) — List of field definitions shared by all documents.
  • path — Filename template for new documents. Supports Liquid variables: , , , . Default: ``.
  • identifier_field — Field used for document display name in lists.
  • output — If true, documents generate standalone pages. Triggers Jekyll collections config with output: true.
  • protected — If true, built pages require authentication to view.
  • readonly — List of auto-populated fields (see Readonly Fields below).
  • i18n — List of language codes. Default-language docs live in the folder root; other languages go in <folder>/<lang>/ subdirectories.
  • permalink — URL pattern for output collections (e.g., /projects/:title/).
  • i18n_permalinks — Map of language code to permalink override. If a language is not listed, the platform auto-generates one by prepending /<lang>/ to the base permalink.

Readonly Fields

Readonly fields are auto-populated and hidden from the editor. They work differently in file vs. folder collections.

File collectionsreadonly is a flat list of field names. Their existing values in the source file are preserved:

readonly:
  - layout
  - permalink
  - lang

Folder collectionsreadonly is a list of objects with a name and either a static value or a Liquid template:

readonly:
  - name: layout
    value: project
  - name: lang
    template: ""
  - name: ref
    template: ""

Template context includes all frontmatter fields plus:

  • slug — Slugified title
  • lang — Current language code
  • filename — File stem (without extension)

Templates support Liquid filters (e.g., ``).

Field Types (Widgets)

Every field requires a name. The widget property determines the input type and defaults to string if omitted.

Common Field Properties

- name: title              # Required — field key in the data file
  label: Page Title         # Display name (auto-generated from name if omitted)
  widget: string            # Input type (default: string)
  required: true            # Whether the field must have a value (default: true)
  hint: "Keep it short"     # Help text shown below the input
  default: ""               # Default value for new documents
  i18n: true                # Internationalization mode (see i18n section)

Text Widgets

string — Single-line text input. This is the default widget.

- name: title
  widget: string

textarea — Multi-line plain text.

- name: description
  widget: textarea

markdown — Markdown editor.

- name: body
  widget: markdown

trix — Rich text editor (Trix). Produces HTML.

- name: bio
  widget: trix

Data Widgets

number — Numeric input.

- name: price
  widget: number

date — Date picker.

- name: dob
  label: Date of Birth
  widget: date

datetime — Date and time picker.

- name: published_at
  widget: datetime

boolean — Checkbox toggle.

- name: featured
  widget: boolean
  default: false

hidden — Not displayed in the editor. Used for fixed metadata like layout.

- name: layout
  widget: hidden
  default: post

Media Widgets

image — Image upload/selector.

- name: hero
  label: Hero image
  widget: image

video — Video URL or embed.

- name: intro
  widget: video

file — General file upload.

- name: document
  widget: file

Structured Widgets

select — Dropdown with predefined options.

Options can be simple strings (value is auto-slugified) or objects with explicit label and value:

# Simple string options
- name: breed
  widget: select
  options:
    - Mini Goldendoodle
    - Standard Goldendoodle

# Explicit label/value options
- name: category
  widget: select
  options:
    - value: tv-commercials
      label: TV Commercials
    - value: brand-marketing
      label: Brand marketing

relation — Dropdown populated from another collection's documents. The document slug is stored as the value.

- name: case_study
  widget: relation
  collection: case-studies
  required: false

list — Repeatable group of sub-fields. Renders as an ordered list of items the user can add, remove, and reorder.

- name: hero_slides
  widget: list
  fields:
    - name: title
      widget: string
    - name: image
      widget: image
    - name: description
      widget: trix

Lists can be nested:

- name: questions
  widget: list
  fields:
    - name: text
    - name: options
      widget: list
      fields:
        - name: value
        - name: label

object — Group of sub-fields rendered as a single unit. Unlike list, there is exactly one instance.

- name: details
  widget: object
  fields:
    - name: location
      widget: string
    - name: size
      widget: string
    - name: service
      widget: string

Objects can nest other objects and lists:

- name: contact
  widget: object
  fields:
    - name: phone
      widget: string
    - name: hours
      widget: object
      fields:
        - name: monday_friday
          widget: string
        - name: saturday
          widget: string
    - name: social
      widget: object
      fields:
        - { name: facebook, widget: string, required: false }
        - { name: instagram, widget: string }

Internationalization (i18n)

Collections with an i18n property support multilingual content.

collections:
  - name: pages
    basedir: _pages
    i18n: [en, es]
    files:
      - file: frontpage.html
        fields:
          - name: title
            widget: string
          - name: coat
            widget: string
            i18n: true

How it works

  • The first language in the list is the default. Its files live in the normal location.
  • Other languages store files in a subdirectory named by language code:
    • File collections with basedir: _pages → default in _pages/, Spanish in es/
    • Folder collections with folder: _puppies → default in _puppies/, Spanish in _puppies/es/
  • When editing a non-default language, only fields with i18n: true (or i18n: translate) are shown.
  • The platform auto-generates Jekyll defaults entries to set lang on each page.

Field-level i18n

  • i18n: true or i18n: translate — Field appears when editing any language.
  • i18n: duplicate — Field value is copied from the default language (shown but pre-filled).
  • i18n: false (default) — Field only appears when editing the default language.

Forms

Define form submission handlers. Forms capture data submitted from site visitors.

forms:
  - name: contact
    label: Contact Form
    webhook: https://hooks.zapier.com/hooks/catch/55555555/xxxxxxx/
    default: true

  - name: interest
    label: General interest form

  - name: member_onboarding
    role: member

Form properties:

  • name (required) — Identifier matching the form's name attribute in HTML.
  • label — Display name.
  • webhook — URL to POST submission data to.
  • default — If true, this is the site's default form.
  • role — Links the form to a role. Submissions trigger user registration with that role.

Roles

Define user roles for gated content and registration workflows.

roles:
  - name: member
    email_confirmation: true
    admin_approval: true

  - name: coach
    email_confirmation: true
    admin_approval: true

Role properties:

  • name (required) — Role identifier (referenced by forms and protected collections).
  • email_confirmation — Require email verification before granting access.
  • admin_approval — Require manual admin approval before granting access.

YAML Formatting Tips

Fields can be written in expanded or compact flow syntax. Both are equivalent:

# Expanded
- name: title
  widget: string

# Compact (flow)
- { name: title, widget: string }

Flow syntax works well for simple fields. Use expanded syntax when fields have hint, options, nested fields, or other multi-line properties.

Complete Example

site:
  base:
    title: Sutton Film Productions
    url: "https://suttonfp.com"
    baseurl: ""
    plugins:
      - jekyll-sitemap
      - jekyll-seo-tag
  prod:
  stg:
    url: "http://suttonfp-rev.rpstg.lan"
  dev:
    url: "http://suttonfp-rev.rpdev.lan:5050"

forms:
  - name: contact
    label: Contact Form
    webhook: https://hooks.zapier.com/hooks/catch/55555555/xxxxxxx/
    default: true

collections:
  - name: data
    label: Site data
    files:
      - label: Team
        name: team
        file: _data/team.yml
        fields:
          - name: items
            widget: list
            fields:
              - { name: name, widget: string }
              - { name: title, widget: string }
              - { name: img, label: Image, widget: image }
              - { name: desc, label: Description, widget: trix }
              - { name: linkedin, widget: string }

      - label: Services
        name: services
        file: _data/services.yml
        fields:
          - name: items
            widget: list
            fields:
              - { name: title, widget: string }
              - { name: description, widget: trix }

  - name: case-studies
    folder: _case-studies
    label_singular: Case study
    create: true
    fields:
      - { name: layout, widget: hidden, default: case-study }
      - { name: title, widget: string }
      - { name: image, widget: image }
      - { name: content, widget: trix }
      - name: videos
        widget: list
        fields:
          - { name: video, widget: video }
          - { name: poster, widget: image }

  - name: playlists
    folder: _playlists
    create: true
    protected: true
    fields:
      - name: title
      - name: items
        widget: list
        fields:
          - { name: title, widget: string }
          - { name: video, widget: video }
          - { name: image, widget: image }
          - { name: desc, label: Description, widget: trix }