{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.zeropress.dev/theme-runtime/v0.7/schema.json",
  "title": "ZeroPress Theme Manifest (Runtime v0.7)",
  "description": "Metadata manifest for a ZeroPress theme package.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "name",
    "namespace",
    "slug",
    "version",
    "license",
    "runtime"
  ],
  "$defs": {
    "httpUrl": {
      "description": "Credential-free absolute HTTP(S) URL. Runtime validation rejects whitespace, control characters, backslashes, and malformed percent encoding.",
      "type": "string",
      "format": "uri",
      "pattern": "^(?!.*%(?![0-9A-Fa-f]{2}))https?:\\/\\/(?![^\\/?#]*@)[^\\s\\\\]+$",
      "x-zeropress-runtime-validation": true
    },
    "supportUrl": {
      "description": "Credential-free absolute HTTP(S) URL or a non-empty mailto URL.",
      "anyOf": [
        {
          "$ref": "#/$defs/httpUrl"
        },
        {
          "type": "string",
          "format": "uri",
          "pattern": "^(?!.*%(?![0-9A-Fa-f]{2}))mailto:(?!\\/\\/)[^/?#\\s\\\\][^\\s\\\\]*$",
          "x-zeropress-runtime-validation": true
        }
      ]
    },
    "themeAssetPath": {
      "description": "Theme-package-relative regular-file path. Runtime validation also rejects empty, dot, traversal, encoded separator, and encoded dot segments and verifies that the file exists.",
      "type": "string",
      "minLength": 1,
      "pattern": "^(?!.*%(?![0-9A-Fa-f]{2}))(?![A-Za-z][A-Za-z0-9+.-]*:)(?!\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\/\\/)(?!.*[?#\\s\\\\])[^\\s\\\\]+$",
      "x-zeropress-runtime-validation": true
    },
    "menuSlotDefinition": {
      "type": "object",
      "description": "Admin-facing helper metadata for a recommended menu id. It documents an expected id but does not assign a menu.",
      "markdownDescription": "Admin-facing helper metadata for a recommended menu id. It documents an expected `menu_id` but does not assign a menu.",
      "additionalProperties": false,
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "description": "Non-blank human-readable label shown in helper UIs.",
          "type": "string",
          "minLength": 1,
          "maxLength": 80,
          "pattern": "\\S"
        },
        "description": {
          "description": "Optional non-blank help text explaining where the menu is typically rendered.",
          "type": "string",
          "minLength": 1,
          "maxLength": 160,
          "pattern": "\\S"
        }
      }
    },
    "widgetAreaDefinition": {
      "type": "object",
      "description": "Admin-facing helper metadata for a recommended widget area id. It documents an expected id but does not assign widgets.",
      "markdownDescription": "Admin-facing helper metadata for a recommended `widget_area_id`. It documents an expected id but does not assign widgets.",
      "additionalProperties": false,
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "description": "Non-blank human-readable label shown in helper UIs.",
          "type": "string",
          "minLength": 1,
          "maxLength": 80,
          "pattern": "\\S"
        },
        "description": {
          "description": "Optional non-blank help text explaining where the widget area is typically rendered.",
          "type": "string",
          "minLength": 1,
          "maxLength": 160,
          "pattern": "\\S"
        }
      }
    },
    "collectionSlotDefinition": {
      "type": "object",
      "description": "Admin-facing helper metadata for a recommended named collection id. It documents an expected id but does not assign collection items.",
      "markdownDescription": "Admin-facing helper metadata for a recommended named collection id. It documents an expected collection id but does not assign collection items.",
      "additionalProperties": false,
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "description": "Non-blank human-readable label shown in helper UIs.",
          "type": "string",
          "minLength": 1,
          "maxLength": 80,
          "pattern": "\\S"
        },
        "description": {
          "description": "Optional non-blank help text explaining how the collection is rendered.",
          "type": "string",
          "minLength": 1,
          "maxLength": 160,
          "pattern": "\\S"
        }
      }
    },
    "siteMetaDefinition": {
      "type": "object",
      "description": "Admin-facing helper metadata for a site.meta key understood by the theme. It is a hint; core does not assign the value.",
      "markdownDescription": "Admin-facing helper metadata for a `site.meta` key understood by the theme. It is a hint; ZeroPress core does not assign the value.",
      "additionalProperties": false,
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "description": "Non-blank human-readable label shown in helper UIs.",
          "type": "string",
          "minLength": 1,
          "maxLength": 80,
          "pattern": "\\S"
        },
        "description": {
          "description": "Optional non-blank help text explaining how the theme uses this key.",
          "type": "string",
          "minLength": 1,
          "maxLength": 160,
          "pattern": "\\S"
        },
        "type": {
          "description": "Optional recommended scalar type for authoring tools.",
          "type": "string",
          "enum": ["string", "number", "boolean"]
        }
      }
    }
  },
  "properties": {
    "$schema": {
      "description": "Optional JSON Schema URI or path used by editors and tooling. ZeroPress core does not interpret this value.",
      "markdownDescription": "Optional JSON Schema URI or path used by editors and tooling. ZeroPress core does not interpret this value.",
      "type": "string"
    },
    "name": {
      "description": "Non-blank human-readable theme name shown in admin UIs and listings. Runtime validation trims the value.",
      "markdownDescription": "Non-blank human-readable theme name shown in admin UIs and listings. Runtime validation trims the value.",
      "type": "string",
      "minLength": 1,
      "maxLength": 80,
      "pattern": "\\S"
    },
    "namespace": {
      "description": "Publisher or organization slug that owns the theme.",
      "markdownDescription": "Publisher or organization slug that owns the theme. Use lowercase letters, numbers, and hyphens only.",
      "type": "string",
      "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
      "minLength": 3,
      "maxLength": 24
    },
    "slug": {
      "description": "Unique theme identifier used in package and registry contexts.",
      "markdownDescription": "Unique theme identifier used in package and registry contexts. Use lowercase letters, numbers, and hyphens only.",
      "type": "string",
      "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
      "minLength": 3,
      "maxLength": 32
    },
    "version": {
      "description": "Theme version in SemVer 2.0.0 format.",
      "markdownDescription": "Theme version in SemVer 2.0.0 format, for example `1.0.0` or `1.2.3-beta.1+build.5`.",
      "type": "string",
      "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$"
    },
    "license": {
      "description": "License identifier for the theme. Use an SPDX id from the allowlist or a LicenseRef-* identifier for commercial, marketplace, proprietary, or otherwise non-SPDX terms.",
      "markdownDescription": "License identifier for the theme. Use an SPDX id from the allowlist or a `LicenseRef-*` identifier for commercial, marketplace, proprietary, or otherwise non-SPDX terms.",
      "type": "string",
      "anyOf": [
        {
          "enum": [
            "MIT",
            "Apache-2.0",
            "BSD-3-Clause",
            "GPL-3.0-only",
            "GPL-3.0-or-later"
          ]
        },
        {
          "pattern": "^LicenseRef-[A-Za-z0-9][A-Za-z0-9.-]*$"
        }
      ]
    },
    "runtime": {
      "description": "Target ZeroPress theme runtime version.",
      "markdownDescription": "Target ZeroPress theme runtime version.",
      "type": "string",
      "const": "0.7"
    },
    "author": {
      "description": "Optional non-blank display name for the theme author or maintainer. Runtime validation trims the value.",
      "markdownDescription": "Optional non-blank display name for the theme author or maintainer. Runtime validation trims the value.",
      "type": "string",
      "minLength": 1,
      "maxLength": 80,
      "pattern": "\\S"
    },
    "description": {
      "description": "Optional non-blank short summary used in theme listings. Runtime validation trims the value.",
      "markdownDescription": "Optional non-blank short summary used in theme listings. Runtime validation trims the value.",
      "type": "string",
      "minLength": 1,
      "maxLength": 280,
      "pattern": "\\S"
    },
    "thumbnail": {
      "description": "Optional credential-free HTTP(S) URL or safe theme-package-relative regular-file path used for previews.",
      "markdownDescription": "Optional credential-free HTTP(S) URL or safe theme-package-relative regular-file path used for previews. Relative paths must name a file included in the theme package.",
      "anyOf": [
        {
          "$ref": "#/$defs/httpUrl"
        },
        {
          "$ref": "#/$defs/themeAssetPath"
        }
      ]
    },
    "links": {
      "description": "Optional public links for theme information, support, marketplace listings, and license terms.",
      "markdownDescription": "Optional public links for theme information, support, marketplace listings, and license terms. All values must be credential-free absolute HTTP(S) URLs; only `support` may instead use `mailto:`.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "homepage": {
          "$ref": "#/$defs/httpUrl"
        },
        "repository": {
          "$ref": "#/$defs/httpUrl"
        },
        "documentation": {
          "$ref": "#/$defs/httpUrl"
        },
        "support": {
          "$ref": "#/$defs/supportUrl"
        },
        "marketplace": {
          "$ref": "#/$defs/httpUrl"
        },
        "license": {
          "$ref": "#/$defs/httpUrl"
        }
      }
    },
    "features": {
      "description": "Optional theme capability flags exposed to the runtime and tooling.",
      "markdownDescription": "Optional theme capability flags exposed to the runtime and tooling. These flags declare whether the theme is designed to support comments, post index routes, or static search UI.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "comments": {
          "description": "Whether the theme supports the comments island capability. Omission behaves like false.",
          "markdownDescription": "Whether the theme supports the comments island capability. Omission behaves like `false`.",
          "type": "boolean"
        },
        "post_index": {
          "description": "Whether the theme supports post index routes. Omission behaves like true; explicit false disables the route even when preview data requests it.",
          "markdownDescription": "Whether the theme supports post index routes. Omission behaves like `true`; explicit `false` disables the route even when preview data requests it.",
          "type": "boolean"
        },
        "search": {
          "description": "Whether the theme supports static search UI backed by ZeroPress search artifacts. Omission behaves like false.",
          "markdownDescription": "Whether the theme supports static search UI backed by ZeroPress search artifacts. Omission behaves like `false`.",
          "type": "boolean"
        }
      }
    },
    "menu_slots": {
      "description": "Optional map of menu slots declared by the theme.",
      "markdownDescription": "Optional map of recommended `menu_id` values declared by the theme. Keys are stable identifiers such as `primary`, `footer`, or `docs-sidebar`. This field is informational helper metadata for admin UIs and documentation; it does not assign menus or affect build behavior.",
      "type": "object",
      "minProperties": 1,
      "maxProperties": 12,
      "propertyNames": {
        "description": "Menu slot identifier.",
        "markdownDescription": "Recommended `menu_id` identifier. Start with a lowercase letter; then use lowercase letters, numbers, underscores, or hyphens.",
        "type": "string",
        "pattern": "^[a-z][a-z0-9_-]{0,63}$",
        "minLength": 1,
        "maxLength": 64
      },
      "additionalProperties": {
        "$ref": "#/$defs/menuSlotDefinition"
      }
    },
    "widget_areas": {
      "description": "Optional map of widget areas declared by the theme.",
      "markdownDescription": "Optional map of recommended `widget_area_id` values declared by the theme. Keys are stable identifiers such as `sidebar`, `header`, or `docs-sidebar`. This field is informational helper metadata for admin UIs and documentation; it does not assign widgets or affect build behavior.",
      "type": "object",
      "minProperties": 1,
      "maxProperties": 12,
      "propertyNames": {
        "description": "Widget area identifier.",
        "markdownDescription": "Recommended `widget_area_id` identifier. Start with a lowercase letter; then use lowercase letters, numbers, underscores, or hyphens.",
        "type": "string",
        "pattern": "^[a-z][a-z0-9_-]{0,63}$",
        "minLength": 1,
        "maxLength": 64
      },
      "additionalProperties": {
        "$ref": "#/$defs/widgetAreaDefinition"
      }
    },
    "site_meta": {
      "description": "Optional map of site.meta keys understood by the theme.",
      "markdownDescription": "Optional map of `site.meta` keys understood by the theme. This field is informational helper metadata for admin UIs and documentation; it does not assign values or affect build behavior.",
      "type": "object",
      "minProperties": 1,
      "maxProperties": 32,
      "propertyNames": {
        "description": "site.meta key identifier.",
        "markdownDescription": "`site.meta` key identifier. Use lowercase letters, digits, underscores, and internal hyphens only.",
        "type": "string",
        "pattern": "^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$",
        "minLength": 1,
        "maxLength": 64
      },
      "additionalProperties": {
        "$ref": "#/$defs/siteMetaDefinition"
      }
    },
    "collection_slots": {
      "description": "Optional map of collection slots declared by the theme.",
      "markdownDescription": "Optional map of recommended collection ids declared by the theme. This field is informational helper metadata for admin UIs and documentation; it does not assign collections or affect build behavior.",
      "type": "object",
      "minProperties": 1,
      "maxProperties": 12,
      "propertyNames": {
        "description": "Collection slot identifier.",
        "markdownDescription": "Recommended collection identifier. Start with a lowercase letter; then use lowercase letters, numbers, underscores, or hyphens.",
        "type": "string",
        "pattern": "^[a-z][a-z0-9_-]{0,63}$",
        "minLength": 1,
        "maxLength": 64
      },
      "additionalProperties": {
        "$ref": "#/$defs/collectionSlotDefinition"
      }
    }
  },
  "examples": [
    {
      "name": "Minimal Theme",
      "namespace": "example",
      "slug": "minimal-theme",
      "version": "1.0.0",
      "license": "MIT",
      "runtime": "0.7"
    },
    {
      "name": "ZeroPress Starter Theme",
      "namespace": "official",
      "slug": "starter-theme",
      "version": "1.0.0",
      "license": "MIT",
      "runtime": "0.7",
      "description": "Starter theme",
      "links": {
        "homepage": "https://zeropress.app",
        "documentation": "https://zeropress.dev/theme-authoring/",
        "repository": "https://github.com/zeropress-app",
        "support": "mailto:support@example.com",
        "license": "https://opensource.org/license/mit"
      },
      "features": {
        "comments": true,
        "post_index": true,
        "search": false
      },
      "menu_slots": {
        "primary": {
          "title": "Primary Menu",
          "description": "Main header navigation"
        },
        "docs-sidebar": {
          "title": "Docs Sidebar",
          "description": "Documentation side navigation"
        }
      },
      "widget_areas": {
        "sidebar": {
          "title": "Sidebar Widgets",
          "description": "Widgets shown next to article and page content"
        },
        "header": {
          "title": "Header Widgets",
          "description": "Optional widgets shown in the header area"
        }
      },
      "site_meta": {
        "show_sponsor_banner": {
          "title": "Show Sponsor Banner",
          "description": "Whether to display the sponsor banner.",
          "type": "boolean"
        }
      },
      "collection_slots": {
        "cover-story": {
          "title": "Cover Story",
          "description": "Primary featured content area"
        }
      }
    }
  ]
}
