Skip to main content
This reference documents every option available in the outpost-manifest.yaml file. For a quick introduction, see Getting Started.

File Location

The manifest file must be named outpost-manifest.yaml and placed in your theme’s root directory, alongside package.json.
your-theme/
├── package.json
├── outpost-manifest.yaml  ← here
├── default.hbs
├── post.hbs
└── ...

Schema Overview

manifest_version: 1           # Required — must be 1

events:
  default_tags: []            # Optional — tags for all event types
  types:                      # Required — at least one type
    type_key:                 # Your type identifier (e.g., "webinar")
      label: "Display Name"
      post_template: "custom-template"  # Required
      tags: []
      supported_fields: []
      required_fields: []
      field_constraints: {}
      custom_fields: []
      messaging_states: []

Top-Level Fields

manifest_version

Required. Must be 1. This enables future schema evolution without breaking existing manifests.
manifest_version: 1

events

Required. Contains all event-related configuration.

Events Section

events.default_tags

Optional. Array of Ghost tag names applied to ALL event types when published.
events:
  default_tags:
    - "event"
    - "registration-open"
Tags are strings. Invalid entries (non-strings) are silently ignored.

events.types

Required. Object where each key is an event type identifier and the value is that type’s configuration.
events:
  types:
    webinar:
      # ... webinar config
    workshop:
      # ... workshop config
    meetup:
      # ... meetup config
Type keys should be lowercase with underscores (e.g., in_person, virtual_workshop). These keys are stored on event records and used for identification.

Event Type Configuration

Each event type supports the following fields:

post_template

Required. The Ghost custom template filename (without .hbs extension) used for this event type’s posts.
types:
  webinar:
    post_template: "custom-webinar"
This template must exist in your theme. Events using this type will have their Ghost posts set to use this template.

label

Optional. Human-readable name shown in the Outpost UI. Defaults to the type key with underscores replaced by spaces and title-cased.
types:
  in_person:
    label: "In-Person Event"  # Shows as "In-Person Event" in dropdown

tags

Optional. Array of Ghost tags specific to this event type. Merged with default_tags when publishing.
types:
  webinar:
    tags:
      - "webinar"
      - "online-event"

supported_fields

Optional. Array of standard field keys to show for this event type. If omitted, all standard fields are shown.
types:
  webinar:
    supported_fields:
      - name
      - description
      - event_date
      - event_time_start
      - event_time_end
      - event_time_zone
      - platform_url
      - access
See Standard Field Keys for all available fields.

required_fields

Optional. Array of field keys that must be filled before publishing. Must be a subset of supported_fields (or standard fields if supported_fields is omitted).
types:
  webinar:
    required_fields:
      - name
      - event_date
      - platform_url
If a required field is not in supported_fields, it will be ignored with a warning.

field_constraints

Optional. Object defining validation constraints for specific fields.
types:
  in_person:
    field_constraints:
      feature_image:
        aspect_ratio: "16:9"
        min_width: 1200
      description:
        max_length: 500
See Field Constraints for available constraint options.

custom_fields

Optional. Array of custom field definitions for theme-specific data.
types:
  webinar:
    custom_fields:
      - key: speaker_name
        label: "Speaker Name"
        type: text
        required: true
See Custom Field Types for complete options.

messaging_states

Optional. Array of messaging states to show in the event settings. If omitted, all seven states are shown.
types:
  webinar:
    messaging_states:
      - can_register
      - registered
      - event_passed
See Messaging States for all available states.

Standard Field Keys

These are the built-in fields available for supported_fields and required_fields:
KeyDescriptionData Type
nameEvent name/titlestring
slugURL-safe identifierstring
descriptionEvent description (used as post excerpt)string
event_dateDate of the eventdate
event_time_startStart timestring (e.g., “10:00 am”)
event_time_endEnd timestring (e.g., “11:00 am”)
event_time_zoneIANA timezonestring (e.g., “America/New_York”)
locationVenue or location textstring
platform_urlVirtual event platform linkURL string
max_attendeesCapacity limitinteger
feature_imageFeatured/hero imageURL string
accessWho can registerenum: anyone, free, paid
rsvp_labelsLabels applied to registrantsarray of strings
registration_deadlineRegistration cutoff datedate
deadline_time_endRegistration cutoff timestring

Field Constraints

Available constraints vary by field type:

Text/Textarea Fields

field_constraints:
  description:
    max_length: 500        # Maximum character count
    pattern: "^[A-Z]"      # Regex pattern (optional)

Image Fields

field_constraints:
  feature_image:
    aspect_ratio: "16:9"   # Width:height ratio
    min_width: 1200        # Minimum width in pixels

Number Fields

field_constraints:
  max_attendees:
    min: 1
    max: 1000

Custom Field Types

Custom fields support these types:

text

Single-line text input.
- key: speaker_name
  label: "Speaker Name"
  type: text
  required: true
  help_text: "Full name of the presenter"
  max_length: 100
  pattern: "^[A-Za-z\\s]+$"

textarea

Multi-line text input.
- key: speaker_bio
  label: "Speaker Bio"
  type: textarea
  required: false
  max_length: 500

number

Numeric input with optional range constraints.
- key: session_duration
  label: "Duration (minutes)"
  type: number
  required: true
  min: 15
  max: 480

select

Dropdown with predefined options.
- key: session_type
  label: "Session Type"
  type: select
  required: true
  options:
    - Keynote
    - Breakout
    - Workshop
    - Panel
Select fields must include an options array. Fields without options are skipped with an error.

url

URL input with validation.
- key: slides_url
  label: "Slides URL"
  type: url
  required: false
  help_text: "Link to presentation slides"

date

Date picker input.
- key: early_bird_deadline
  label: "Early Bird Deadline"
  type: date
  required: false

toggle

Boolean switch input.
- key: is_recorded
  label: "Will Be Recorded"
  type: toggle
  required: false

image

Image upload with optional constraints.
- key: speaker_photo
  label: "Speaker Photo"
  type: image
  required: false
  aspect_ratio: "1:1"
  min_width: 400
  max_file_size_kb: 2048

Custom Field Properties

All custom field types support these properties:
PropertyTypeRequiredDescription
keystringYesUnique identifier (no spaces, lowercase recommended)
labelstringNoDisplay label (defaults to formatted key)
typestringYesOne of the field types above
requiredbooleanNoWhether field must be filled (default: false)
help_textstringNoHelper text shown below the field
Custom field keys must not collide with standard field keys. Keys like name, event_date, access, etc. will be rejected with an error.

Messaging States

Control which messaging states appear in the event settings editor:
StateWhen Shown to Members
can_registerEligible member who hasn’t registered
login_required_freeGuest on a free event
login_required_paidGuest on a paid event
upgrade_requiredFree member on a paid event
registeredMember who has RSVP’d
registration_closedAfter registration deadline
event_passedAfter the event ends
types:
  webinar:
    messaging_states:
      - can_register
      - registered
      - event_passed
If omitted, all seven states are configurable.

Homepage Curation Section

Optional. Declares curated homepage regions that a publisher can fill from the Outpost UI. When a theme’s manifest includes a top-level homepage_curation key, Outpost shows a Homepage Curation screen (under Posts) where editors pick which post occupies each slot — without hand-editing tags in Ghost. homepage_curation and events are independent top-level keys in the same outpost-manifest.yaml; a theme can declare either, both, or neither.
homepage_curation:
  sections:                              # Required — one or more sections
    - key: featured-us                   # Section identifier (unique)
      name: "Featured (US)"              # Display name in the curation UI
      description: "Top-of-homepage hero carousel."   # Optional helper text
      picker:                            # Optional — controls the post picker
        default_view: recent             # Default tab when picking a post
        recent_limit: 30                 # How many recent posts to offer
        recent_filter:                   # Optional — pre-scope picker to a tag
          tag: local-news
      slots:                             # Required — one or more slots
        - { key: slot-1, label: "Slot 1", tag: hash-home-hero-slot-1 }
        - { key: slot-2, label: "Slot 2", tag: hash-home-hero-slot-2 }

How slots work

Each slot binds one Ghost tag to one post. The theme renders whichever single post currently carries that tag; the curation UI simply swaps which post wears it. Slot tags are ordinary Ghost internal tags — a hash- prefix maps to a # internal tag.
FieldRequiredDescription
sections[].keyYesUnique identifier for the section
sections[].nameYesDisplay name shown in the curation UI
sections[].descriptionNoHelper text shown under the section
sections[].picker.default_viewNoDefault picker tab (e.g. recent)
sections[].picker.recent_limitNoNumber of recent posts to list
sections[].picker.recent_filter.tagNoRestrict the picker to posts carrying this tag
slots[].keyYesUnique identifier for the slot within its section
slots[].labelYesLabel shown above the slot in the UI
slots[].tagYesGhost tag that binds a post to this slot
Homepage Curation is an early Labs feature and currently ships in the single-file manifest format. A complete worked example is bundled with the docs as cascade-homepage-curation.yaml.

Error Handling

Outpost validates manifests during theme upload and stores errors in the manifest data. Invalid parts are stripped while valid parts are kept.

Error Categories

CategorySeverityBehavior
YAML syntax errorErrorManifest ignored entirely
Unknown manifest_versionWarningManifest ignored
Missing post_templateErrorEvent type skipped
Unknown standard fieldWarningField key ignored
Required field not in supportedWarningRequirement ignored
Custom field key collisionErrorCustom field skipped
Unknown custom field typeErrorCustom field skipped
Missing options on selectErrorCustom field skipped

Viewing Errors

Errors are visible in:
  • Theme settings table (warning count with info button)
  • Event editor (banner at top of form)
  • Theme upload/refresh API response

Example Error Response

{
  "_errors": [
    {
      "field": "types.webinar.post_template",
      "message": "Missing required 'post_template'",
      "severity": "error"
    },
    {
      "field": "types.in_person.supported_fields",
      "message": "Unknown standard field 'title'",
      "severity": "warning"
    }
  ]
}

Complete Example

manifest_version: 1

events:
  default_tags:
    - "event"

  types:
    webinar:
      label: "Webinar"
      post_template: "custom-webinar"
      tags:
        - "webinar"
        - "online"

      supported_fields:
        - name
        - description
        - event_date
        - event_time_start
        - event_time_end
        - event_time_zone
        - platform_url
        - feature_image
        - access
        - registration_deadline
        - deadline_time_end

      required_fields:
        - name
        - event_date
        - platform_url

      field_constraints:
        feature_image:
          aspect_ratio: "16:9"
          min_width: 1200
        description:
          max_length: 300

      custom_fields:
        - key: speaker_name
          label: "Speaker Name"
          type: text
          required: true
          help_text: "Full name of the presenter"

        - key: speaker_bio
          label: "Speaker Bio"
          type: textarea
          required: false
          max_length: 500

        - key: session_type
          label: "Session Type"
          type: select
          required: true
          options:
            - Live Presentation
            - Q&A Session
            - Workshop

        - key: is_recorded
          label: "Will Be Recorded"
          type: toggle

      messaging_states:
        - can_register
        - login_required_free
        - registered
        - event_passed

    in_person:
      label: "In-Person Event"
      post_template: "custom-in-person"
      tags:
        - "in-person"
        - "conference"

      supported_fields:
        - name
        - description
        - event_date
        - event_time_start
        - event_time_end
        - event_time_zone
        - location
        - max_attendees
        - feature_image
        - access

      required_fields:
        - name
        - event_date
        - location
        - feature_image

      custom_fields:
        - key: venue_address
          label: "Venue Address"
          type: textarea
          required: true

        - key: track
          label: "Track"
          type: select
          required: true
          options:
            - Main Stage
            - Workshop Room A
            - Workshop Room B
            - Networking Hall