Skip to content
Quilium Docs
Back to site
Reference

Content-type schema

The YAML keys that define a content-type, the block dropped into a page section and rendered by one element template.

A content-type defines a reusable content block: a typed set of fields plus the element template that renders one instance. Blocks are dropped into a page-type section and rendered by _contents. Field definitions live exclusively inside tabsets, never at the type root.

Top-level keys

Key Type Notes
name string Backoffice display label. Live: name: En-tête de section.
template string Full element template path. Live: 'elements/entete.liquid'. .liquid is the only loadable extension; you may also drop it ('elements/entete') and the engine appends it. Any other extension is a 500, not a fallback.
icon string Font Awesome Pro id (heading, star, newspaper, envelope, quote-left).
group string Backoffice grouping label for the block selector. Live: 'Accueil', 'La revue', 'Bibliothèque de blocs'.
tabsets object tabsets.<key>.{name, fields}. All fields live here.

Fields and tabsets

Every field belongs to a tabset. A tabset is an editing tab in the backoffice; tabsets.<key>.name is its label, tabsets.<key>.fields its field map. A content-type may declare several tabsets, for example one per pipeline stage in a form-handler block (main, validation, actions).

Each field key is a camelCase identifier and maps to a {type, label, …} descriptor. See Custom fields for the field-type catalogue and per-type config.

mediaText:
  name: Media + text
  template: 'elements/mediaText.liquid'
  icon: file
  group: 'Block library'
  tabsets:
    main:
      name: Content
      fields:
        kicker:
          type: text
          label: Kicker
        title:
          type: text
          label: Title
        text:
          type: wysiwyg
          label: Body
        ctaLabel:
          type: text
          label: Link label
        ctaPage:
          type: page
          label: Internal link
        ctaUrl:
          type: text
          label: External URL
          translatable: false
        image:
          type: image
          label: Image
          config:
            versions:
              wide:
                label: Wide
                width: 1200
                height: 900
              full:
                label: Full width
                width: 1920
                height: 1080
    config:
      name: Configuration
      fields:
        layout:
          type: select
          label: Layout
          translatable: false
          default: imageRight
          config:
            options:
              imageRight: Image right
              imageLeft: Image left
              imageFull: Image full width
              textOnly: Text only
Field identifiers stay verbatim. Keys like title, text and category are real content identifiers from the live site and read back as content.custom.title in templates. They are data, not UI labels, and do not get translated — renaming one is a schema change and a data migration, since the stored values are keyed by it.

Backoffice grouping

Two independent mechanisms organise the block selector:

Mechanism Where Effect
# Section: <Name> a level-0 YAML comment above a run of content-types groups every following content-type under that heading
group: '<Name>' a property on the content-type tags the single content-type with a selector group

Convention reuses the same label for both: a group: value matches the # Section: comment that precedes it.

The <<: *custom-fields anchor

Reference skills prescribe a config tabset carrying <<: *custom-fields, a YAML anchor that injects shared display options (removeSpaceBottom, showDivider) into every content-type.

Recommended, not enforced. The <<: *custom-fields anchor is a best-practice convention, not an engine requirement. The live fil-rouge site does not use it: its config tabsets hold ordinary fields (a display-option select) instead of the anchor. Only reference a YAML anchor you have actually defined, an absent anchor (*custom-fields, *_robots) breaks the push.

Form-handler shape

A content-type can carry the full form pipeline as separate tabsets: input fields in main, a validate field in a validation tabset, a save field in an actions tabset. The save field's config.key names the target collection.

newsletterForm:
  template: 'elements/newsletterForm.liquid'
  tabsets:
    main:
      fields:
        title:
          type: text
          label: Title
        intro:
          type: wysiwyg
          label: Intro
    validation:
      name: Validation
      fields:
        validation:
          type: validate
          config:
            rules:
              email: [email, required]
              consent: [required]
    actions:
      name: Actions
      fields:
        saveToCollection:
          type: save
          config:
            key: abonnes        # target collection

See Custom fields for the validate and save field config, and Template variables for content.custom and content.form.<field>.errors.

Related


Last updated September 6, 2026.