# Settings for the site dashboard at /admin (Sveltia CMS).
# All of the site's content is edited here, including publications, talks, teaching and the CV records.
# Menu (same sections and order as the Overview at /admin/): Research outputs, Projects, Grants |
# Conference papers, Invited lectures, Service | Courses, Student theses | Prizes and honours, Curricula vitae |
# Research groups, People | About me, Extra pages.
# Since 2026-10-24 the scholarly records are edited here too; the Obsidian vault receives a copy.
# Previous version: _Deprecated/public-admin/config-2026-10-23.yml

backend:
  name: github
  repo: nludovice1209/nludovice-site
  branch: main
  # "Sign in with GitHub" goes through this sign-in service on Nicolo's Cloudflare account
  # (folder nludovice-cms-auth next to this project; code: sveltia/sveltia-cms-auth, pinned).
  base_url: https://nludovice-cms-auth.nludovice.workers.dev

# Photos: originals are stored in assets/. The build makes the web sizes.
# Top-level photos (headshots, portrait) also get a square crop; photos in subfolders do not.
# The saved path may start with /assets/; the site accepts it (src/lib/images.mjs).
media_folder: assets

site_url: https://nludovice.com
display_url: https://nludovice.com
logo:
  src: /favicon.svg
app_title: nludovice.com dashboard

collections:

  # ================================================================ Research
  - name: publications
    label: Research outputs
    label_singular: Publication
    icon: menu_book
    description: "Every publication, including work under review or in progress. Only Published and Forthcoming ones appear on the site; the others stay private. The abstract is part of each entry."
    folder: src/site/publications
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{year}} · {{title}} · {{status}}"
    sortable_fields: [ year, title, order ]
    create: true
    delete: true
    fields:
      - name: status
        label: Status
        widget: select
        default: in-progress
        hint: "Only Published and Forthcoming appear on the site. Under review and In progress are never shown anywhere."
        options:
          - { label: Published, value: published }
          - { label: Forthcoming, value: forthcoming }
          - { label: Under review (hidden), value: under-review }
          - { label: In progress (hidden), value: in-progress }
      - { name: public, label: Show on the site, widget: boolean, default: true, hint: "Untick to hide a published work from the site (it stays in your records and the vault copy)." }
      - name: id
        label: Short name
        widget: string
        hint: "Lowercase letters, numbers and hyphens, usually author-year-keyword (for example ludovice-2025-nutribun). It links the publication to projects and featured work, so do not change it later."
        pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ]
      - name: type
        label: Type
        widget: select
        options:
          - { label: Book, value: book }
          - { label: Journal article, value: article }
          - { label: Special issue (edited), value: special-issue }
          - { label: Book chapter, value: chapter }
          - { label: Book review, value: review }
          - { label: Working paper, value: working-paper }
          - { label: Thesis, value: thesis }
          - { label: "Public writing (op-ed, commentary)", value: op-ed }
      - { name: title, label: Title, widget: text }
      - { name: authors, label: Authors, widget: list, hint: "In order, as Surname, Initials (for example Ludovice, N.P.). Your name is shown in bold automatically.", field: { name: author, label: Author, widget: string } }
      - { name: role, label: Your role, widget: select, required: false, hint: "Only for edited works.", options: [ { label: Editor, value: editor } ] }
      - { name: year, label: Year, widget: string, required: false, pattern: [ "^[0-9]{4}$", "Use four digits, for example 2026" ], hint: "Four digits, for example 2026. Leave empty for forthcoming work." }
      - { name: date, label: Date, widget: string, required: false, hint: "For public writing: YYYY-MM-DD." }
      - { name: venue, label: "Journal, press or outlet", widget: string, required: false }
      - { name: show_venue, label: Show the journal name, widget: boolean, required: false, default: true, hint: "Untick to hide the venue name on the site." }
      - { name: volume, label: Volume, widget: string, required: false }
      - { name: issue, label: Issue, widget: string, required: false }
      - { name: pages, label: Pages or article number, widget: string, required: false }
      - { name: special_issue, label: Special issue title, widget: string, required: false }
      - { name: editors, label: Editors of the volume, widget: list, required: false, hint: "For book chapters, as Surname, Initials.", field: { name: editor, label: Editor, widget: string } }
      - { name: publisher, label: Publisher, widget: string, required: false }
      - { name: doi, label: DOI, widget: string, required: false, hint: "Only the DOI itself, for example 10.1016/j.erss.2025.104235" }
      - { name: url, label: Web address, widget: string, required: false, hint: "If there is no DOI, or for public writing." }
      - { name: reprint_url, label: Reprint web address, widget: string, required: false }
      - name: themes
        label: Themes
        widget: select
        multiple: true
        required: false
        options:
          - { label: Animal history, value: animal-history }
          - { label: Medicine and health, value: medicine-and-health }
          - { label: Food and nutrition, value: food-and-nutrition }
          - { label: Environment and technology, value: environment-and-technology }
          - { label: Post-conflict health, value: post-conflict-health }
          - { label: Green buildings, value: green-buildings }
          - { label: Philippines and Southeast Asia, value: philippines-and-southeast-asia }
          - { label: History and policy, value: history-and-policy }
          - { label: AI and history, value: ai-and-history }
          - { label: Public writing, value: public-writing }
      - { name: featured, label: Featured, widget: boolean, required: false, default: false, hint: "Marks a key work (used to break ties in lists)." }
      - { name: hprg, label: HPRG output, widget: boolean, required: false, default: false, hint: "Tick to list it under Outputs on the HPRG page." }
      - { name: abstract, label: Abstract, widget: text, required: false }
      - { name: abstract_source, label: Abstract source, widget: string, required: false, hint: "For example: publisher, OpenAlex." }
      - name: metrics
        label: Journal metrics (never shown)
        widget: object
        required: false
        collapsed: true
        fields:
          - { name: quartile, label: Quartile, widget: string, required: false }
          - { name: impact_factor, label: Impact factor, widget: number, value_type: float, required: false }
      - { name: note, label: Private note, widget: text, required: false, hint: "For yourself; never shown." }
      - { name: order, label: Order, widget: number, value_type: int, required: false, default: 999, hint: "Advanced. Only breaks ties where two works have the same year. New works can keep 999." }

  - name: projects
    label: Projects
    label_singular: Project
    icon: science
    description: "Research projects. Each has a card (Research page, home page, group pages) and, if 'Has its own page' is ticked, a page at nludovice.com/research/short-name/."
    folder: src/site/projects
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{order}}. {{title}} ({{status}}) · {{visibility}}"
    sortable_fields: [ order, title ]
    create: true
    delete: true
    fields:
      - &visibility
        name: visibility
        label: Visibility
        widget: select
        default: draft
        hint: "Published and Forthcoming appear on the site. Draft stays hidden: use it for anything under review or in progress."
        options:
          - { label: Published, value: published }
          - { label: Forthcoming, value: forthcoming }
          - { label: Draft (hidden), value: draft }
      - name: id
        label: Short name
        widget: string
        hint: "Lowercase letters, numbers and hyphens. It is the page address, so do not change it later."
        pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ]
      - { name: title, label: Title, widget: string }
      - name: status
        label: Stage
        widget: select
        default: ongoing
        options: [ { label: Ongoing, value: ongoing }, { label: Completed, value: completed } ]
      - { name: groups, label: Groups, widget: relation, collection: groups, value_field: id, display_fields: [ name ], search_fields: [ name, short_name ], multiple: true, required: false, hint: "Group projects also appear on the group's page and carry its badge (for example HPRG)." }
      - { name: has_page, label: Has its own page, widget: boolean, default: false, hint: "Tick to give the project its own page built from the Page blocks below. The card then links to it." }
      - { name: order, label: Order, widget: number, value_type: int, default: 10, hint: "Position among ongoing projects: 1 first. Completed projects are listed by end year, newest first." }
      - { name: role, label: Your role, widget: string, hint: "For example Principal investigator" }
      - { name: funder, label: Funder, widget: string, required: false, hint: "Full name with the short form in brackets, for example Hong Kong Research Grants Council, General Research Fund (RGC-GRF)" }
      - { name: kind, label: Kind of project, widget: string, required: false, hint: "Optional line, for example the journal of a special issue." }
      - name: period
        label: Period
        widget: object
        fields:
          - { name: start, label: Start year, widget: string, pattern: [ "^[0-9]{4}$", "Use four digits, for example 2026" ] }
          - { name: end, label: End year, widget: string, pattern: [ "^[0-9]{4}$", "Use four digits, for example 2026" ] }
      - name: themes
        label: Themes
        widget: select
        multiple: true
        required: false
        options:
          - { label: Animal history, value: animal-history }
          - { label: Medicine and health, value: medicine-and-health }
          - { label: Food and nutrition, value: food-and-nutrition }
          - { label: Environment and technology, value: environment-and-technology }
          - { label: Post-conflict health, value: post-conflict-health }
          - { label: Green buildings, value: green-buildings }
          - { label: Philippines and Southeast Asia, value: philippines-and-southeast-asia }
          - { label: History and policy, value: history-and-policy }
          - { label: AI and history, value: ai-and-history }
      - { name: summary, label: Short summary, widget: text, required: false, hint: "One or two sentences for the card. If empty, the card uses the first sentences of the first Text block." }
      - { name: search_summary, label: Search summary, widget: text, required: false, hint: "For the project's own page: the description search engines show. If empty, the short summary is used." }
      - name: image
        label: Photograph
        widget: object
        required: false
        collapsed: true
        fields:
          - { name: file, label: Image, widget: image, media_folder: /assets/projects, public_folder: projects, accept: ".jpg,.jpeg,.png", hint: "Public-domain or openly licensed, at least 1200 pixels wide." }
          - { name: caption, label: Caption, widget: string, hint: "Also read aloud to blind visitors as the photo's description." }
          - { name: credit, label: Credit line, widget: string, hint: "For example: U.S. National Archives, public domain, via Wikimedia Commons" }
          - { name: source_page, label: Source web page, widget: string, required: false }
      - name: recognition
        label: Prizes and recognition
        widget: list
        required: false
        field: { name: line, label: Line, widget: string }
      - { name: outputs, label: Outputs, widget: relation, collection: publications, value_field: id, display_fields: [ title ], search_fields: [ title ], filters: [ { field: status, values: [ published, forthcoming ] } ], multiple: true, required: false, hint: "Shown on the card and at the end of the project page. Only published and forthcoming publications are offered." }
      - &blocks
        name: blocks
        label: Page blocks
        widget: list
        required: false
        hint: "The sections of the page, top to bottom. Add a block with the button below, then drag to reorder. A block's heading appears on the left, as on the HPRG page."
        types:
          - name: text
            label: Text
            summary: "Text: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false }
              - name: body
                label: Text
                widget: text
                hint: "Blank line = new paragraph. *italics*, **bold**, [link text](https://address), '- ' at the start of a line for a list, '### ' for a subheading."
          - name: objectives
            label: Numbered objectives
            summary: "Objectives: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "Empty = 'Objectives'." }
              - { name: items, label: Objectives, widget: list, field: { name: item, label: Objective, widget: text } }
          - name: image
            label: Photo
            summary: "Photo: {{caption}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false }
              - { name: file, label: Photo, widget: image, media_folder: /assets/pages, public_folder: pages, accept: ".jpg,.jpeg,.png", hint: "JPEG or PNG, at least 1200 pixels wide." }
              - { name: caption, label: Caption, widget: string, required: false, hint: "Also read aloud to blind visitors as the photo's description." }
              - { name: credit, label: Credit line, widget: string, required: false, hint: "Photographer or archive, licence, source." }
          - name: gallery
            label: Gallery
            summary: "Gallery: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "Empty = 'Gallery'." }
              - name: images
                label: Photos
                widget: list
                summary: "{{caption}}"
                fields:
                  - { name: file, label: Photo, widget: image, media_folder: /assets/pages, public_folder: pages, accept: ".jpg,.jpeg,.png" }
                  - { name: caption, label: Caption, widget: string, required: false }
                  - { name: credit, label: Credit line, widget: string, required: false }
          - name: team
            label: Team
            summary: "Team: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "Empty = 'Team'." }
              - { name: people, label: People, widget: relation, collection: people, value_field: id, display_fields: [ name ], search_fields: [ name ], multiple: true, hint: "Choose from People. Each appears as a profile card." }
          - name: outputs
            label: Publications
            summary: "Publications: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "Empty = 'Outputs'." }
              - { name: publications, label: Publications, widget: relation, collection: publications, value_field: id, display_fields: [ title ], search_fields: [ title ], filters: [ { field: status, values: [ published, forthcoming ] } ], multiple: true, hint: "Type part of a title. Only published and forthcoming publications from your vault are offered." }
          - name: funding
            label: Funding
            summary: "Funding: {{funder}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "Empty = 'Funding'." }
              - { name: funder, label: Funder, widget: string, required: false, hint: "On a project page, empty boxes use the project's own funder, role and period." }
              - { name: role, label: Role, widget: string, required: false }
              - { name: period, label: Period, widget: string, required: false, hint: "For example 2027 to 2029" }
              - { name: grant, label: Grant number, widget: string, required: false }
          - name: timeline
            label: Timeline
            summary: "Timeline: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "Empty = 'Timeline'." }
              - name: items
                label: Entries
                widget: list
                summary: "{{when}}: {{what}}"
                fields:
                  - { name: when, label: When, widget: string, hint: "For example March 2027" }
                  - { name: what, label: What, widget: string, hint: "*italics* and [links](https://…) work here." }
          - name: button
            label: Button
            summary: "Button: {{label}}"
            fields:
              - { name: label, label: Button text, widget: string }
              - { name: url, label: Web address, widget: string, hint: "A full address (https://…) or a page on this site (/hprg/)." }
              - { name: style, label: Style, widget: select, default: main, options: [ { label: Orange, value: main }, { label: Outline, value: quiet } ] }
          - name: quote
            label: Quotation
            summary: "Quotation: {{source}}"
            fields:
              - { name: text, label: Quotation, widget: text }
              - { name: source, label: Who said it, widget: string, required: false }
          - name: contact
            label: Contact panel
            summary: "Contact: {{heading}}"
            fields:
              - { name: heading, label: Heading, widget: string, required: false, hint: "For example: Join the workshop." }
              - { name: line, label: Line before the email address, widget: string, required: false, hint: "The email address is added by the site and hidden from spam robots." }
      - { name: description_from, label: Description from a grant, widget: relation, collection: grants, value_field: "id", display_fields: [ title ], search_fields: [ title ], required: false, hint: "Optional. The grant's description (in Grants and funding) is shown first on the project page, as 'About the project'." }
      - { name: funding_id, label: Grant, widget: relation, collection: grants, value_field: "id", display_fields: [ title ], search_fields: [ title ], required: false, hint: "Optional. The grant that funds this project." }
  - name: grants
    label: Grants and funding
    label_singular: Grant
    icon: payments
    description: Grants, fellowships and scholarships, one entry each, listed in the CV by Position. Amounts are stored but hidden unless you tick Show amount.
    folder: src/site/grants
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{title}} ({{year}}{{period.start}})"
    sortable_fields:
      fields:
        - order
        - title
      default:
        field: order
        direction: ascending
    create: true
    delete: true
    fields:
      - name: public
        label: Show on the site
        widget: boolean
        default: true
      - name: id
        label: Short name
        widget: string
        hint: For example grant-rgc-grf-16601625. Projects can use it to show this grant's description, so do not change it later.
        pattern:
          - ^[a-z0-9-]+$
          - Use lowercase letters, numbers and hyphens only
      - name: title
        label: Title
        widget: string
      - name: kind
        label: Kind
        widget: select
        required: false
        options:
          - label: Grant
            value: grant
          - label: Fellowship
            value: fellowship
          - label: Scholarship
            value: scholarship
      - name: funder
        label: Funder
        widget: string
      - name: role
        label: Your role
        widget: string
        required: false
        hint: PI shows as Principal investigator.
      - name: project_number
        label: Project number
        widget: string
        required: false
      - name: year
        label: Year or years
        widget: string
        required: false
        hint: For example 2019 or 2017-2021. Use Period instead for grants with start and end months.
      - name: period
        label: Period
        widget: object
        required: false
        fields:
          - name: start
            label: Start (YYYY-MM)
            widget: string
          - name: end
            label: End (YYYY-MM)
            widget: string
      - name: status
        label: Status
        widget: select
        required: false
        options:
          - label: Ongoing
            value: ongoing
          - label: Submitted, outcome pending
            value: submitted-pending-outcome
          - label: Completed
            value: completed
      - name: amount
        label: Amount
        widget: string
        required: false
      - name: show_amount
        label: Show amount
        widget: boolean
        required: false
        default: false
      - name: featured
        label: Featured
        widget: boolean
        required: false
        default: false
      - name: themes
        label: Themes
        widget: select
        multiple: true
        required: false
        options:
          - label: Animal history
            value: animal-history
          - label: Medicine and health
            value: medicine-and-health
          - label: Food and nutrition
            value: food-and-nutrition
          - label: Environment and technology
            value: environment-and-technology
          - label: Post-conflict health
            value: post-conflict-health
          - label: Green buildings
            value: green-buildings
          - label: Philippines and Southeast Asia
            value: philippines-and-southeast-asia
          - label: History and policy
            value: history-and-policy
          - label: AI and history
            value: ai-and-history
      - name: description
        label: Description
        widget: text
        required: false
        hint: Shown on a project page that takes its description from this grant. New line = new paragraph.
      - name: description_source
        label: Description source (private note)
        widget: string
        required: false
      - name: order
        label: Position
        widget: number
        value_type: int
        default: 5
        hint: Smaller numbers come first. Entries are numbered 10, 20, 30; a new entry (5) goes to the top. Use 15 to put it between the first and the second.
  - divider: true

  # ================================================================ Activities
  - name: presentations
    label: Conference papers
    label_singular: Conference paper or workshop
    icon: co_present
    description: "Papers, panels, discussant roles, fellowships and workshops. Those marked 'Attended' are counted on the Talks page and listed in the CV only."
    folder: src/site/presentations
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{date}} · {{title}}"
    sortable_fields: [ date, title ]
    create: true
    delete: true
    fields:
      - { name: public, label: Show on the site, widget: boolean, default: true }
      - { name: id, label: Short name, widget: string, hint: "For example pres-2026-06-leiden. Do not change it later.", pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ] }
      - { name: date, label: Date (YYYY-MM), widget: string, pattern: [ "^[0-9]{4}-[0-9]{2}$", "Use year and month, for example 2026-06" ] }
      - name: role
        label: Your role
        widget: select
        options:
          - { label: Paper, value: presenter }
          - { label: "Paper, co-presented", value: co-presenter }
          - { label: Discussant, value: discussant }
          - { label: Panel organiser and chair, value: organizer-chair }
          - { label: Fellow, value: fellow }
          - { label: Contributor, value: contributor }
          - { label: "Attended (counted, not listed on the Talks page)", value: participant }
      - { name: title, label: Title, widget: text }
      - { name: event, label: Event, widget: string }
      - { name: place, label: Place, widget: string }
      - { name: coauthors, label: Co-presenters, widget: list, required: false, field: { name: name, label: Name, widget: string } }
      - &talk_themes
        name: themes
        label: Themes
        widget: select
        multiple: true
        required: false
        options: [ { label: Animal history, value: animal-history }, { label: Medicine and health, value: medicine-and-health }, { label: Food and nutrition, value: food-and-nutrition }, { label: Environment and technology, value: environment-and-technology }, { label: Post-conflict health, value: post-conflict-health }, { label: Green buildings, value: green-buildings }, { label: Philippines and Southeast Asia, value: philippines-and-southeast-asia }, { label: History and policy, value: history-and-policy }, { label: AI and history, value: ai-and-history } ]

  - name: lectures
    label: Invited lectures
    label_singular: Invited lecture
    icon: record_voice_over
    description: "Invited lectures, guest talks and similar."
    folder: src/site/lectures
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{date}} · {{title}}"
    sortable_fields: [ date, title ]
    create: true
    delete: true
    fields:
      - { name: public, label: Show on the site, widget: boolean, default: true }
      - { name: id, label: Short name, widget: string, hint: "For example lec-2026-upd-sti. Do not change it later.", pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ] }
      - { name: date, label: Year, widget: string, pattern: [ "^[0-9]{4}$", "Use the year, for example 2026" ] }
      - name: role
        label: Your role
        widget: select
        options:
          - { label: Invited lecture, value: invited-speaker }
          - { label: Guest lecture, value: guest-lecturer }
          - { label: Guest talk, value: guest-speaker }
          - { label: Workshop facilitator, value: facilitator }
          - { label: Book response, value: book-response }
          - { label: Convener, value: convener }
      - { name: title, label: Title, widget: text }
      - { name: host, label: Host, widget: string, hint: "Institution or organisation" }
      - { name: context, label: Context, widget: string, required: false, hint: "Optional, for example the course or series." }
      - *talk_themes
  - name: service
    label: Professional service
    label_singular: Service entry
    icon: handshake
    description: "Editorial and advisory roles, fellowships and affiliations, memberships, peer review, organising and consulting: one entry each. Shown on the CV, grouped by Category, then by Position."
    folder: src/site/service
    extension: yml
    format: yaml
    identifier_field: body
    slug: "{{id}}"
    summary: "{{category}} · {{period}}{{year}} · {{role}}, {{body}}"
    sortable_fields:
      fields:
        - order
        - body
      default:
        field: order
        direction: ascending
    view_groups:
      - label: Category
        field: category
    create: true
    delete: true
    fields:
      - name: category
        label: Category
        widget: select
        options:
          - label: Editorial and advisory
            value: editorial_and_advisory
          - label: Fellowships and affiliations
            value: fellowships_and_affiliations
          - label: Memberships
            value: memberships
          - label: Peer review
            value: peer_review
          - label: Organising and consulting
            value: organizing_and_consulting
      - name: public
        label: Show on the site
        widget: boolean
        default: true
      - name: id
        label: Short name
        widget: string
        pattern:
          - ^[a-z0-9-]+$
          - Use lowercase letters, numbers and hyphens only
      - name: role
        label: Role
        widget: string
      - name: body
        label: Organisation, journal or press
        widget: string
      - name: period
        label: Period
        widget: string
        required: false
        hint: For roles held over time, for example 2024-present (editorial, fellowships).
      - name: year
        label: Year
        widget: string
        required: false
        hint: For one-off service, for example 2026 (peer review, organising).
      - name: order
        label: Position
        widget: number
        value_type: int
        default: 5
        hint: Smaller numbers come first. Entries are numbered 10, 20, 30; a new entry (5) goes to the top. Use 15 to put it between the first and the second.
  - divider: true

  # ================================================================ Teaching
  - name: teaching
    label: Courses
    label_singular: Course
    icon: school
    description: Every course you have taught, one entry each, listed under its institution by Position. Institutions and teaching certification are in Institutions and settings.
    folder: src/site/courses
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{code}} {{title}} · {{institution}}"
    sortable_fields:
      fields:
        - order
        - code
      default:
        field: order
        direction: ascending
    view_groups:
      - label: Institution
        field: institution
    create: true
    delete: true
    fields:
      - name: id
        label: Short name
        widget: string
        hint: Lowercase letters, numbers and hyphens, for example hkust-ppol-6100u.
        pattern:
          - ^[a-z0-9-]+$
          - Use lowercase letters, numbers and hyphens only
      - name: public
        label: Show on the site
        widget: boolean
        default: true
      - name: institution
        label: Institution
        widget: relation
        collection: teaching-settings
        file: teaching
        value_field: institutions.*.id
        display_fields:
          - institutions.*.name
        search_fields:
          - institutions.*.name
        hint: Add a new institution in Institutions and settings first.
      - name: code
        label: Course code
        widget: string
      - name: title
        label: Course title
        widget: string
      - name: featured
        label: Featured
        widget: boolean
        required: false
        default: false
      - name: order
        label: Position
        widget: number
        value_type: int
        default: 5
        hint: Smaller numbers come first. Entries are numbered 10, 20, 30; a new entry (5) goes to the top. Use 15 to put it between the first and the second.
  - name: supervision
    label: Student theses
    label_singular: Thesis
    icon: history_edu
    description: Students you supervised and theses you examined, one entry each, newest first by Position. Whether names are shown is set in Institutions and settings.
    folder: src/site/theses
    extension: yml
    format: yaml
    identifier_field: student
    slug: "{{id}}"
    summary: "{{kind}} · {{year}} · {{student}} · {{title}}"
    sortable_fields:
      fields:
        - order
        - year
      default:
        field: order
        direction: ascending
    view_groups:
      - label: Kind
        field: kind
    create: true
    delete: true
    fields:
      - name: kind
        label: Kind
        widget: select
        default: supervised
        options:
          - label: Supervised
            value: supervised
          - label: Examined or read (thesis reviewed)
            value: reviewed
      - name: public
        label: Show on the site
        widget: boolean
        default: true
      - name: id
        label: Short name
        widget: string
        pattern:
          - ^[a-z0-9-]+$
          - Use lowercase letters, numbers and hyphens only
      - name: year
        label: Year
        widget: string
      - name: student
        label: Student
        widget: string
      - name: title
        label: Thesis or project title
        widget: text
      - name: level
        label: Level
        widget: string
        hint: For example Master of Arts in History
      - name: institution
        label: Institution
        widget: string
      - name: honor
        label: Honour
        widget: string
        required: false
      - name: order
        label: Position
        widget: number
        value_type: int
        default: 5
        hint: Smaller numbers come first. Entries are numbered 10, 20, 30; a new entry (5) goes to the top. Use 15 to put it between the first and the second.
  - name: teaching-settings
    label: Institutions and settings
    icon: tune
    description: The institutions your courses belong to, your teaching certification, and what the Teaching page shows.
    files:
      - name: teaching
        label: Institutions and certification
        file: src/site/teaching.yml
        fields:
          - name: institutions
            label: Institutions
            widget: list
            summary: "{{name}} ({{period}})"
            fields:
              - name: id
                label: Short name
                widget: string
                pattern:
                  - ^[a-z0-9-]+$
                  - Use lowercase letters, numbers and hyphens only
              - name: name
                label: Institution and unit
                widget: string
              - name: period
                label: Period
                widget: string
                hint: For example 2024-present
              - name: appointment
                label: Appointment
                widget: string
              - name: level
                label: Level
                widget: select
                options:
                  - label: Postgraduate
                    value: postgraduate
                  - label: Undergraduate
                    value: undergraduate
                  - label: Undergraduate and graduate
                    value: undergraduate and graduate
              - name: note
                label: Note
                widget: string
                required: false
          - name: certification
            label: Teaching certification
            widget: list
            required: false
            summary: "{{title}} ({{year}})"
            fields:
              - name: title
                label: Title
                widget: string
              - name: institution
                label: Institution
                widget: string
              - name: year
                label: Year
                widget: string
          - name: public
            label: Show teaching on the site
            widget: boolean
            default: true
      - name: supervision
        label: "Student theses: what is shown"
        file: src/site/supervision.yml
        fields:
          - name: show_student_names
            label: Show students' names
            widget: boolean
            default: true
          - name: show_reviewed
            label: Show theses reviewed
            widget: boolean
            default: false
          - name: show_reviewed_names
            label: Show reviewed students' names
            widget: boolean
            default: false
  - divider: true

  # ================================================================ Recognition and CV
  - name: honours
    label: Prizes and honours
    label_singular: Honour
    icon: emoji_events
    description: Prizes, awards and honours, one entry each, listed in the CV by Position (newest first).
    folder: src/site/honours
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{year}} · {{title}}"
    sortable_fields:
      fields:
        - order
        - year
      default:
        field: order
        direction: ascending
    create: true
    delete: true
    fields:
      - name: public
        label: Show on the site
        widget: boolean
        default: true
      - name: id
        label: Short name
        widget: string
        pattern:
          - ^[a-z0-9-]+$
          - Use lowercase letters, numbers and hyphens only
      - name: year
        label: Year
        widget: string
      - name: title
        label: Honour
        widget: string
      - name: body
        label: Awarding body
        widget: string
      - name: featured
        label: Featured
        widget: boolean
        required: false
        default: false
      - name: order
        label: Position
        widget: number
        value_type: int
        default: 5
        hint: Smaller numbers come first. Entries are numbered 10, 20, 30; a new entry (5) goes to the top. Use 15 to put it between the first and the second.
  - name: cv
    label: Curricula vitae
    label_singular: Appointment or degree
    icon: badge
    description: Appointments and education, one entry each, listed in the CV by Position. The CV page and PDF are built from these and from the other categories.
    folder: src/site/cv
    extension: yml
    format: yaml
    identifier_field: degree
    slug: "{{id}}"
    summary: "{{kind}} · {{period}} · {{title}}, {{institution}}"
    sortable_fields:
      fields:
        - order
        - period
      default:
        field: order
        direction: ascending
    view_groups:
      - label: Kind
        field: kind
    create: true
    delete: true
    fields:
      - name: kind
        label: Kind
        widget: select
        default: employment
        options:
          - label: Appointment
            value: employment
          - label: Education
            value: education
      - name: public
        label: Show on the site
        widget: boolean
        default: true
      - name: id
        label: Short name
        widget: string
        pattern:
          - ^[a-z0-9-]+$
          - Use lowercase letters, numbers and hyphens only
      - name: title
        label: Job title
        widget: string
        required: false
        hint: Appointments only, for example Research Assistant Professor.
      - name: degree
        label: Degree
        widget: string
        required: false
        hint: Education only, for example Doctor of Philosophy, Major in History.
      - name: period
        label: Period
        widget: string
        hint: For example 2024-present
      - name: institution
        label: Institution
        widget: string
      - name: unit
        label: Unit or department
        widget: string
        required: false
      - name: notes
        label: Notes
        widget: list
        required: false
        field:
          name: note
          label: Note
          widget: string
        hint: Appointments only.
      - name: thesis
        label: Thesis title
        widget: text
        required: false
        hint: Education only.
      - name: thesis_date
        label: Thesis date
        widget: string
        required: false
        hint: Education only.
      - name: supervisors
        label: Supervisors
        widget: list
        required: false
        field:
          name: name
          label: Name
          widget: string
        hint: Education only.
      - name: gpa
        label: GPA
        widget: string
        required: false
        hint: Education only.
      - name: rank_note
        label: Rank note
        widget: string
        required: false
        hint: Education only.
      - name: hide_fields
        label: Fields to hide
        widget: select
        multiple: true
        required: false
        options:
          - label: GPA
            value: gpa
          - label: Rank note
            value: rank_note
        hint: Education only.
      - name: order
        label: Position
        widget: number
        value_type: int
        default: 5
        hint: Smaller numbers come first within Appointments and within Education. Entries are numbered 10, 20, 30; a new entry (5) goes to the top. Use 15 to put it between the first and the second.
  - divider: true

  # ================================================================ Groups and people
  - name: groups
    label: Research groups
    label_singular: Research group
    icon: groups
    description: "HPRG is the first entry. A future research group gets its own entry here and its own page at nludovice.com/groups/short-name/; HPRG keeps nludovice.com/hprg/."
    folder: src/site/groups
    extension: yml
    format: yaml
    identifier_field: name
    slug: "{{id}}"
    summary: "{{name}} · {{visibility}}"
    sortable_fields: [ order, name ]
    create: true
    delete: false
    fields:
      - *visibility
      - name: id
        label: Short name
        widget: string
        hint: "Lowercase letters, numbers and hyphens. It is the page address. Do not change it later (HPRG must stay 'hprg')."
        pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ]
      - { name: name, label: Full name, widget: string }
      - { name: short_name, label: Abbreviation, widget: string, required: false, hint: "For example HPRG. Shown on project badges." }
      - { name: order, label: Order, widget: number, value_type: int, default: 10 }
      - { name: logo, label: Logo, widget: image, required: false, media_folder: /assets/groups, public_folder: groups, accept: ".jpg,.jpeg,.png", hint: "Optional, for future groups. HPRG always uses its own monogram. Without a logo, the abbreviation is shown." }
      - { name: search_summary, label: Search summary, widget: text, required: false, hint: "The short description search engines and link previews show." }
      - name: hero
        label: Opening section
        widget: object
        fields:
          - { name: label, label: Small label, widget: string, required: false, hint: "For example: Division of Public Policy, HKUST" }
          - { name: statement, label: Statement, widget: text }
          - { name: paragraph, label: Paragraph, widget: text, required: false }
      - { name: description, label: About, widget: text, required: false }
      - { name: objectives, label: Objectives, widget: list, required: false, field: { name: objective, label: Objective, widget: text } }
      - { name: projects_intro, label: Line above the projects, widget: text, required: false, hint: "Projects that list this group appear on its page automatically." }
      - name: contact
        label: Contact section
        widget: object
        required: false
        hint: "The email address itself is added by the site and protected from spam robots; do not type it here."
        fields:
          - { name: heading, label: Heading, widget: string }
          - { name: line, label: Line before the email address, widget: string }
      - *blocks

  - name: people
    label: People
    label_singular: Person
    icon: person
    description: "One entry per person. A person appears on the page of each group they belong to, listed by Order (lowest first)."
    folder: src/site/people
    extension: yml
    format: yaml
    identifier_field: name
    slug: "{{id}}"
    summary: "{{order}}. {{name}} ({{role}}) · {{visibility}}"
    sortable_fields: [ order, name ]
    create: true
    delete: true
    fields:
      - *visibility
      - name: id
        label: Short name
        widget: string
        hint: "Lowercase letters, numbers and hyphens, for example bernabe. It becomes the file name and the link to this profile, so do not change it later."
        pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ]
      - { name: name, label: Name, widget: string }
      - { name: role, label: Role, widget: string, hint: "For example Research Assistant" }
      - { name: order, label: Order, widget: number, value_type: int, default: 10, hint: "1 first, 2 second, and so on." }
      - { name: groups, label: Groups, widget: relation, collection: groups, value_field: id, display_fields: [ name ], search_fields: [ name, short_name ], multiple: true, required: false, hint: "The research groups this person belongs to." }
      - { name: photo, label: Headshot, widget: image, required: false, accept: ".jpg,.jpeg,.png", hint: "Optional. A clear head-and-shoulders photo, at least 600 pixels wide; the site crops it to a square. Name the file hprg-surname.jpg. Without a photo the site shows initials." }
      - name: bio_from
        label: Biography source
        widget: select
        required: false
        hint: "Choose 'From About me' only for Nicolo. Leave empty to use the biography below."
        options: [ { label: From About me (my biography), value: about } ]
      - { name: bio, label: Biography, widget: text, required: false }
      - name: links
        label: Links
        widget: list
        required: false
        summary: "{{label}}"
        fields:
          - { name: label, label: Link text, widget: string }
          - { name: url, label: Web address, widget: string }
  - divider: true

  # ================================================================ Website
  - name: text
    label: About me
    icon: home
    description: "Your home page, your biography, and short lines on other pages."
    files:
      - name: home
        label: Home page
        file: src/site/home.yml
        fields:
          - name: hero
            label: Opening section
            widget: object
            fields:
              - { name: role_line, label: Role line, widget: string }
              - { name: statement, label: Statement, widget: text, hint: "The large headline. Keep it to about ten words. Put *asterisks* around the words to show in orange italics." }
              - { name: paragraph, label: Paragraph, widget: text }
              - name: image
                label: Photograph beside the headline
                widget: object
                required: false
                collapsed: true
                fields:
                  - { name: file, label: Image, widget: image, required: false, media_folder: /assets/projects, public_folder: projects, accept: ".jpg,.jpeg,.png", hint: "Public-domain or openly licensed, at least 1200 pixels wide. Shown in navy and orange." }
                  - { name: caption, label: Caption, widget: string, required: false, hint: "Also read aloud to blind visitors as the photo's description." }
          - name: book_image
            label: Photograph beside the featured book
            widget: object
            required: false
            collapsed: true
            fields:
              - { name: file, label: Image, widget: image, required: false, media_folder: /assets/projects, public_folder: projects, accept: ".jpg,.jpeg,.png", hint: "Shown only when a book is among the featured work. Without a photo the book panel runs full width." }
              - { name: caption, label: Caption, widget: string, required: false }
          - name: currently
            label: Currently
            widget: list
            summary: "{{label}}: {{text}} · {{visibility}}"
            fields:
              - *visibility
              - { name: label, label: Label, widget: string, hint: "One word, for example Leading" }
              - { name: text, label: Text, widget: string }
              - { name: sub, label: Small line, widget: string, required: false }
          - { name: featured, label: Featured work, widget: relation, collection: publications, value_field: id, display_fields: [ title ], search_fields: [ title ], filters: [ { field: status, values: [ published, forthcoming ] } ], multiple: true, max: 3, hint: "Choose three. Only published and forthcoming publications are offered." }
      - name: biography
        label: Biography
        file: src/site/about.yml
        fields:
          - { name: bio_short, label: Short biography, widget: text, hint: "Two sentences. Shown on your HPRG profile card." }
          - { name: bio_long, label: Long biography, widget: text, hint: "A paragraph, for a future About page." }
      - name: profile
        label: Profile
        file: src/site/profile.yml
        fields:
          - name: name
            label: Name
            widget: object
            fields:
              - { name: full, label: Full name, widget: string }
              - { name: short, label: Short name, widget: string, hint: "As shown on the site, for example Nicolo Ludovice" }
              - { name: citation, label: Citation form, widget: string, hint: "As in author lists, for example Ludovice, N.P. It is shown in bold in publication entries." }
          - { name: title, label: Title, widget: string }
          - name: affiliation
            label: Affiliation
            widget: object
            fields:
              - { name: unit, label: Unit, widget: string }
              - { name: institution, label: Institution, widget: string }
              - { name: since, label: Since, widget: number, value_type: int }
          - { name: leads, label: Leads, widget: string, required: false }
          - { name: location, label: Location, widget: string, required: false }
          - name: contact
            label: Contact
            widget: object
            hint: "The site shows the address protected from spam robots."
            fields:
              - { name: email, label: Email, widget: string }
              - { name: email_public, label: Show email on the site, widget: boolean, default: true }
          - name: identifiers
            label: Scholarly identifiers
            widget: object
            fields:
              - { name: orcid, label: ORCID, widget: string }
              - { name: scopus, label: Scopus author ID, widget: string, required: false }
              - { name: researcherid, label: Web of Science ResearcherID, widget: string, required: false }
              - { name: google_scholar, label: Google Scholar user id, widget: string, required: false }
              - { name: pure, label: HKUST Research Portal address, widget: string, required: false }
          - { name: research_interests, label: Research interests, widget: list, required: false, field: { name: interest, label: Interest, widget: string } }
          - name: languages
            label: Languages
            widget: list
            required: false
            summary: "{{language}} ({{level}})"
            fields:
              - { name: language, label: Language, widget: string }
              - { name: level, label: Level, widget: string }
          - { name: public, label: Show profile on the site, widget: boolean, default: true }
      - name: pages
        label: Other page text
        file: src/site/pages.yml
        fields:
          - { name: home, label: Home page, widget: object, fields: [ { name: hprg_band, label: HPRG band line, widget: text } ] }
          - { name: research, label: Research, widget: object, fields: [ { name: description, label: Search summary, widget: text, hint: "The short description search engines and link previews show." }, { name: intro, label: Intro, widget: text, hint: "The line under the page title." } ] }
          - { name: publications, label: Publications, widget: object, fields: [ { name: description, label: Search summary, widget: text } ] }
          - { name: talks, label: Talks, widget: object, fields: [ { name: description, label: Search summary, widget: text } ] }
          - { name: talks_archive, label: Talks archive, widget: object, fields: [ { name: description, label: Search summary, widget: text } ] }
          - { name: teaching, label: Teaching, widget: object, fields: [ { name: description, label: Search summary, widget: text }, { name: intro, label: Intro, widget: text } ] }
          - { name: writing, label: Public writing, widget: object, fields: [ { name: description, label: Search summary, widget: text } ] }
          - { name: cv, label: CV, widget: object, fields: [ { name: description, label: Search summary, widget: text }, { name: intro, label: Intro, widget: text } ] }
          - name: contact
            label: Contact
            widget: object
            fields:
              - { name: description, label: Search summary, widget: text }
              - { name: intro, label: Intro, widget: text }
              - { name: affiliation, label: Affiliation, widget: string }
              - { name: address, label: Address, widget: string }
          - { name: not_found, label: Page not found (404), widget: object, fields: [ { name: intro, label: Intro, widget: text } ] }
  - name: news
    label: News
    label_singular: News item
    icon: campaign
    description: "Short news about you: talks, publications, awards. The home page shows the latest three; all are on nludovice.com/news/."
    folder: src/site/news
    extension: yml
    format: yaml
    identifier_field: text
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
    slug_length: 60
    summary: "{{date}} · {{text}}"
    sortable_fields:
      fields:
        - date
      default:
        field: date
        direction: descending
    create: true
    delete: true
    fields:
      - name: visibility
        label: Visibility
        widget: select
        default: published
        hint: "Published and Forthcoming appear on the site. Draft stays hidden: use it for anything under review or in progress."
        options:
          - label: Published
            value: published
          - label: Forthcoming
            value: forthcoming
          - label: Draft (hidden)
            value: draft
      - name: date
        label: Date
        widget: datetime
        time_format: false
        format: YYYY-MM-DD
        hint: The site shows the month and year.
      - name: text
        label: News
        widget: text
        hint: One or two sentences. *Italics* for titles.
      - name: link
        label: Link
        widget: string
        required: false
        hint: Optional web address, for example the event page or the publication.
      - name: link_label
        label: Link text
        widget: string
        required: false
        hint: Optional. If empty, the link reads "More".

  - name: extra-pages
    label: Extra pages
    label_singular: Extra page
    icon: description
    description: "Free-standing pages built from blocks, each at nludovice.com/short-name/. Tick 'Show in the footer' to link it at the bottom of every page."
    folder: src/site/extra-pages
    extension: yml
    format: yaml
    identifier_field: title
    slug: "{{id}}"
    summary: "{{title}} · {{visibility}}"
    sortable_fields: [ order, title ]
    create: true
    delete: true
    fields:
      - *visibility
      - name: id
        label: Short name
        widget: string
        hint: "Lowercase letters, numbers and hyphens. It is the page address (nludovice.com/short-name/). Names the site already uses, such as research or cv, are refused."
        pattern: [ "^[a-z0-9-]+$", "Use lowercase letters, numbers and hyphens only" ]
      - { name: title, label: Title, widget: string }
      - { name: label, label: Small label above the title, widget: string, required: false }
      - { name: intro, label: Intro, widget: text, required: false, hint: "The line under the title. *italics* work." }
      - { name: search_summary, label: Search summary, widget: text, required: false }
      - { name: in_footer, label: Show in the footer, widget: boolean, default: false }
      - { name: order, label: Order, widget: number, value_type: int, default: 10 }
      - name: image
        label: Photo below the title
        widget: object
        required: false
        collapsed: true
        fields:
          - { name: file, label: Photo, widget: image, media_folder: /assets/pages, public_folder: pages, accept: ".jpg,.jpeg,.png" }
          - { name: caption, label: Caption, widget: string, required: false }
          - { name: credit, label: Credit line, widget: string, required: false }
      - *blocks
