Fields

A field is one key in an entry’s frontmatter and the widget Emet shows for it. You declare them per section in admin/site.yaml, and the type decides the widget: a toggle for a boolean, a date picker for a date, the media library for an image. The setup wizard guesses a reasonable set from your existing content, and this page is the reference for tidying up what it wrote.

sections:
  blog:
    fields:
      - name: title
        type: string
        required: true
      - name: date
        type: datetime
      - name: tags
        type: list
      - name: cover
        type: image
        hint: Shown at the top of the post and in listings

Fields appear in the frontmatter panel in the order you declare them. If you’d rather group them, field_groups on the section puts named, collapsible boxes around them; see Sections.

Keys in the file that you haven’t declared still show up, with a widget guessed from the value, and there’s an Add field row for adding new ones. Emet never drops a key it doesn’t know about. The system fields (slug, aliases, filename), inherited cascade values and the draft toggle are covered under Editing an entry.

Common options#

Option What it does
name The frontmatter key. Required.
type One of the types below. widget is accepted as an alias, so Netlify and Decap configs mostly drop in. Defaults to string.
label What the form calls it. Defaults to the name with underscores and hyphens turned into spaces and each word capitalised, so featured_image becomes “Featured Image”.
hint Help text under the widget.
placeholder Placeholder text, for string, text, number and relation fields.
required Adds an asterisk to the label. It doesn’t block saving, so treat it as a hint to editors rather than a rule.
hidden true leaves the field out of the form while keeping the key in the file.
condition, conditions Show the field only when another field has a given value; see below.
validation.max_length Shows a character counter on string and text fields, which turns amber past the limit. Nothing stops you saving.

A few options you might expect, or have seen in other CMS configs, exist in the config types but aren’t read by any widget: default (it’s only used for shortcode parameters; put defaults in the archetype instead), validation.min_length, validation.pattern and validation.min/max. They’re harmless but do nothing. The same goes for several per-type options noted below. Field names must be unique within a section; a duplicate logs a warning and the last one wins.

Conditional fields#

Show a field only when another field has a particular value:

- name: video_url
  type: string
  condition:
    field: type
    value: video

conditions takes a list that must all match, and condition.any takes a list of which one must match:

# all of these
conditions:
  - field: type
    value: video
  - field: featured
    value: true

# any of these
condition:
  any:
    - field: type
      value: video
    - field: type
      value: podcast

field can be a dotted path into an object (author.role). Matching is forgiving: a list matches if it contains the value, "true" matches true, "1" matches 1, and an unset field counts as an empty string. While hidden, the field shows as a one-line note saying it’ll appear when its conditions are met, so editors know it exists. Inside an object or a list of objects, conditions see the parent frontmatter and the object’s own values together.

String#

A single-line text input.

- name: subtitle
  type: string
  placeholder: Optional
  validation:
    max_length: 100

Fields named title, meta_title or seo_title get a counter against 60 characters without being asked, and description, meta_description and seo_description against 160, since those are the lengths search results truncate at.

Text#

A textarea, rows tall (default 3), with the same max_length counter.

- name: summary
  type: text
  rows: 4

Markdown#

This type is listed in the config types but doesn’t do anything useful yet. A top-level markdown field is filtered out of the frontmatter panel entirely (the body is edited by the main editor, not a field), and inside an object or list it renders as a plain textarea. If you want Markdown in frontmatter, use text and accept that there’s no toolbar.

Number#

A text input whose value is parsed as a number on the way out. Anything that doesn’t parse, including an empty box, removes the key from the frontmatter rather than writing an empty string.

- name: rating
  type: number

min, max, step and value_type are accepted but not read: there’s no range enforcement and no integer-only mode.

Boolean#

A toggle. Don’t declare one for draft; that key is filtered out of the panel and handled by the Draft / Publish toggle in the panel header instead.

- name: featured
  type: boolean

Datetime#

A date-and-time picker with a Now button and a note showing which timezone the browser is in. What’s written to the file is UTC in ISO 8601 form, e.g. 2026-10-10T12:00:00.000Z, whatever you typed in locally. Hugo is fine with that; if you’d rather see local time in the file, you’ll have to edit it in Markdown mode.

- name: date
  type: datetime

Half-typed values the browser produces while you edit the year are ignored rather than written to the file. The format, display_format and time_format options aren’t read.

Date#

The same picker without the time. The value is stored exactly as the picker gives it, 2026-10-10, with no timezone conversion, so it can’t shift by a day.

- name: event_date
  type: date

Select#

A dropdown, with a blank Select… option at the top for “no value”. Options are either plain strings or value/label pairs:

- name: category
  type: select
  options:
    - news
    - tutorial

- name: status
  type: select
  options:
    - value: wip
      label: In progress
    - value: done
      label: Finished

With multiple: true the dropdown becomes a group of checkboxes and the value is a list, written in the order the options are declared regardless of the order you ticked them, which keeps diffs quiet. A value that’s a comma-separated string in an old file is split into a list for you.

- name: platforms
  type: select
  multiple: true
  options: [web, ios, android]

List#

A list of items, each with a number, a remove button and an Add item button underneath.

- name: tags
  type: list

Without items, or with items.type: string, each item is a text input and there’s a dashed quick-add box below the list: type comma-separated values and press Enter (or click away) to add them all at once. A plain string value in an old file is split on commas and written back as a list the next time you save.

For anything else, items is a full field definition, so a list of objects is:

- name: authors
  type: list
  items:
    type: object
    fields:
      - name: name
        type: string
      - name: url
        type: string

Each item renders with that field’s widget, labelled “Item 1”, “Item 2” and so on. min and max aren’t enforced.

The system aliases field is a string list with one extra: each alias is checked against Hugo’s rules (no whitespace, no Windows-reserved names or characters, must not resolve to the site root), and an invalid one blocks saving until you fix it. A section field named aliases gets the same treatment.

Object#

A collapsible group of nested fields, stored as a map.

- name: author
  type: object
  fields:
    - name: name
      type: string
    - name: avatar
      type: image

Relation#

A searchable dropdown of entries from another section, storing one value.

- name: series
  type: relation
  section: series
  display_field: title
  value_field: slug

section is the key of the section to list and is required. display_field and value_field can be title, slug, path or date (those are the only things Emet knows about an entry without opening it) and default to title and slug. The widget shows the current value’s title if it can find it, or the raw value if not, with a clear button. There’s no multi-select; for several related entries use a list of strings for now.

Image#

A path input with a Browse button that opens the media library, a clear button, and a thumbnail once there’s a value. You can also just type a path.

- name: cover
  type: image

If AI image generation is set up, the library’s Edit with AI button lets you regenerate the picked image and replace the file in place.

File#

The same as image but with a filename instead of a thumbnail. It opens the same media library, which only lists files matching media.accept, so to pick a PDF with it you’ll need to add .pdf to that list.

- name: attachment
  type: file

Code#

A CodeMirror editor with syntax highlighting.

- name: custom_css
  type: code
  language: css
  rows: 10

language can be markdown, javascript, typescript, json, css or html, and defaults to json. yaml is accepted but highlighted as Markdown, since there’s no YAML grammar bundled. rows sets the height; rows: 1 also hides the line numbers for a single-line snippet.

Colour#

A native colour picker next to a text box for the hex value, with a swatch below.

- name: accent
  type: color

Only six-digit hex (#3b82f6) is recognised. Anything else is kept as typed and flagged with a warning, which is deliberate: it means a value like var(--brand) survives a round trip through the editor.

Hidden#

There’s no working hidden type; a field declared with type: hidden renders as “Unsupported field type”. What you want is the hidden: true option on whatever type the value really is:

- name: layout
  type: string
  hidden: true

That keeps layout in the file without showing it. Since default isn’t applied to entries, a hidden field only has a value if the archetype (or an earlier edit) put one there.

Where next?#

  • Sections for where fields are declared, plus field_groups and slug patterns.
  • Entries for the panel the fields live in.