{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://orbitmarkdown.com/schema/orbit.config.json",
  "title": "orbit.config.yaml",
  "description": "Orbit MD's settings for a site: where content and images live, what editors may do, and — for sites not built with Astro — the content map. Every key is optional. Docs: https://orbitmarkdown.com/docs/orbit-config",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "assetsDir": {
      "type": "string",
      "description": "Folder images live in, from the site's root (default src/assets). Inside public/ (or static/ on Gatsby and Hugo), images are referenced from the site root.",
      "examples": [
        "src/assets",
        "public/images",
        "static/images"
      ]
    },
    "site": {
      "type": "object",
      "additionalProperties": false,
      "description": "How the site shows in Orbit.",
      "properties": {
        "title": {
          "type": "string",
          "description": "The site's name in Orbit."
        },
        "favicon": {
          "type": "string",
          "description": "Path to the site icon, if it isn't in a usual place."
        },
        "defaultRole": {
          "type": "string",
          "enum": [
            "editor",
            "dev"
          ],
          "description": "The view a new install opens in: editor (simple) or dev (with settings)."
        },
        "liveUrl": {
          "type": "string",
          "description": "Address of the live site — adds a link in Orbit."
        },
        "previewUrl": {
          "type": "string",
          "description": "Address of the preview site — adds a Preview link in Orbit."
        }
      }
    },
    "branches": {
      "type": "object",
      "additionalProperties": false,
      "description": "Publishing. When default and live differ, saving sends changes to the preview branch and Publish takes them live.",
      "properties": {
        "default": {
          "type": "string",
          "description": "The branch editors save to (e.g. preview)."
        },
        "live": {
          "type": "string",
          "description": "The branch the live site is built from (default main)."
        },
        "allowed": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Branches the dev view may switch between (empty = all)."
        },
        "goLive": {
          "type": "string",
          "enum": [
            "merge",
            "pullRequest"
          ],
          "description": "merge (default): approvers publish in Orbit. pullRequest: publishing opens a pull request on the git host."
        }
      }
    },
    "snippets": {
      "type": "object",
      "additionalProperties": false,
      "description": "Reusable [[name]] blocks.",
      "properties": {
        "compileOnSave": {
          "type": "boolean",
          "description": "true: Orbit writes each snippet's text into the page on save. Use only when the site's build does NOT expand [[name]] itself."
        },
        "dir": {
          "type": "string",
          "description": "Snippets folder, from the site's root (default: snippets inside the content folder — src/content/snippets on Astro, snippets/ elsewhere)."
        }
      }
    },
    "collections": {
      "type": "object",
      "description": "Rules per section (an Astro collection or a content-map section), by name.",
      "additionalProperties": {
        "$ref": "#/definitions/collectionRule"
      }
    },
    "sections": {
      "type": "object",
      "description": "The content map — for sites not built with Astro (Gatsby, Next.js, Nuxt, Hugo, …): where each kind of content lives, what renders it and its fields. Ignored on an Astro site. Docs: https://orbitmarkdown.com/docs/content-map",
      "additionalProperties": {
        "$ref": "#/definitions/section"
      }
    },
    "data": {
      "type": "array",
      "description": "JSON or YAML files editors may edit through a form (navigation, site details, team lists…).",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "path"
        ],
        "properties": {
          "path": {
            "type": "string",
            "description": "The file, from the site's root (.json, .yaml or .yml)."
          },
          "label": {
            "type": "string",
            "description": "Its name in Orbit."
          }
        }
      }
    },
    "components": {
      "type": "array",
      "description": "MDX components editors may insert from a form, in .mdx pages.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The component's tag name, e.g. Callout."
          },
          "description": {
            "type": "string",
            "description": "One line shown in the picker."
          },
          "children": {
            "type": "boolean",
            "description": "true: wraps text (<Callout>…</Callout>); false: self-closing (<Figure />)."
          },
          "props": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "string",
                    "enum",
                    "boolean",
                    "number"
                  ]
                },
                "options": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Choices, for type: enum."
                },
                "default": {
                  "type": "string"
                },
                "required": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      }
    }
  },
  "definitions": {
    "collectionRule": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "canAdd": {
          "type": "boolean",
          "description": "Whether editors may add pages (a content-map section also needs its template)."
        },
        "readOnly": {
          "type": "boolean",
          "description": "Editors can read but not change these pages."
        },
        "bodyless": {
          "type": "boolean",
          "description": "Pages are fields only — no text editor."
        },
        "addTo": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Folders that take new pages (and the folders inside them)."
        },
        "noAddTo": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Folders that never take new pages (wins over addTo)."
        },
        "newFolders": {
          "type": "boolean",
          "description": "Editors may start new sub-folders. Check your routes handle a / in the address first."
        },
        "url": {
          "type": "string",
          "pattern": "^/",
          "description": "Where these pages are on the built site, from its root: {slug} = the page's file name (or its folder's name for a page in its own folder), {path} = its sub-folder and slug. Lets editors open the page they're editing on the preview or live site.",
          "examples": [
            "/blog/{slug}",
            "/journal/{path}",
            "/about"
          ]
        }
      }
    },
    "section": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "files"
      ],
      "properties": {
        "files": {
          "type": "string",
          "description": "The pages, from the site's root: a pattern starting in a folder (content/blog/*.md, posts/**/*.mdx) or one file for a fixed page.",
          "examples": [
            "content/blog/*.md",
            "content/blog/**/index.md",
            "_posts/*.md",
            "content/pages/home.md"
          ]
        },
        "template": {
          "type": "string",
          "description": "The file that renders these pages (a Gatsby template, a Next.js route, nuxt.config.ts for Docus). Editors may add pages only when it's set and exists.",
          "examples": [
            "src/templates/blog-post.js",
            "app/blog/[slug]/page.tsx"
          ]
        },
        "newPage": {
          "type": "string",
          "description": "Where a new page goes, from the folder files starts in, with {slug} for its name. Default {slug} + the pages' extension.",
          "examples": [
            "{slug}.md",
            "{slug}/index.md"
          ]
        },
        "fields": {
          "description": "The form's fields: a list, or the path of a JSON Schema file. Leave out to have Orbit work them out from the pages.",
          "oneOf": [
            {
              "type": "string",
              "description": "A JSON Schema file (.json) describing the frontmatter."
            },
            {
              "type": "array",
              "items": {
                "$ref": "#/definitions/field"
              }
            }
          ]
        }
      }
    },
    "field": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "description": "The frontmatter key. Not needed for a list's items."
        },
        "type": {
          "type": "string",
          "enum": [
            "string",
            "number",
            "boolean",
            "date",
            "enum",
            "image",
            "array",
            "object"
          ],
          "description": "Default string."
        },
        "required": {
          "type": "boolean",
          "description": "Default false."
        },
        "options": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Choices, for type: enum."
        },
        "fields": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/field"
          },
          "description": "For type: object."
        },
        "items": {
          "$ref": "#/definitions/field",
          "description": "The shape of each item, for type: array."
        }
      }
    }
  }
}
