{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://filamentfacts.com/schema/deal.schema.json",
  "title": "FilamentFacts deal of the day",
  "description": "One file per day at data/deals/YYYY-MM-DD.json. Prices are editorial retailer checks, not Open Filament Database specs. Public HTML, public JSON, and Markdown teasers omit price and retailer URLs. Set sample to true for an example record; the unlocked payload then still omits schema.org Offer markup.",
  "type": "object",
  "additionalProperties": false,
  "required": ["product", "brand", "filamentSlug", "price", "retailer", "url", "verifiedAt"],
  "properties": {
    "date": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "description": "Calendar date. Must match the file name when present."
    },
    "product": { "type": "string", "minLength": 1 },
    "brand": { "type": "string", "minLength": 1 },
    "brandSlug": {
      "type": "string",
      "description": "Brand page slug, such as polymaker. Resolved from the brand name when omitted."
    },
    "filamentSlug": {
      "type": "string",
      "minLength": 1,
      "description": "Filament page slug, such as polylite-pla."
    },
    "price": { "type": "number", "exclusiveMinimum": 0 },
    "regularPrice": { "type": ["number", "null"] },
    "pricePerKg": { "type": ["number", "null"] },
    "currency": { "type": "string", "pattern": "^[A-Za-z]{3}$", "default": "USD" },
    "retailer": { "type": "string", "minLength": 1, "description": "Name of the first retailer. Kept so a single-store file still validates. Prefer retailers." },
    "url": { "type": "string", "pattern": "^https://", "description": "https URL of the first retailer. Not printed on public pages." },
    "retailers": {
      "type": "array",
      "description": "One or more stores. An Amazon shop URL receives tag=filamentfacts-20 when the deal is loaded, and that retailer is treated as an affiliate link. Other store URLs stay as written. Public pages do not emit these URLs.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "url"],
        "properties": {
          "name": { "type": "string", "minLength": 1 },
          "url": { "type": "string", "pattern": "^https://" },
          "affiliate": { "type": "boolean" }
        }
      }
    },
    "verifiedAt": { "type": "string", "format": "date-time" },
    "expires": {
      "type": "string",
      "format": "date-time",
      "description": "Optional instant after which the deal is removed. Compared with the viewer's clock and again at the next build."
    },
    "sample": {
      "type": "boolean",
      "description": "True means the price is an example. The page shows that label and does not emit an Offer."
    },
    "note": { "type": "string" },
    "runners": {
      "type": "array",
      "description": "Same-day alternatives. Manufacturer URLs stay plain. An Amazon shop URL receives tag=filamentfacts-20 when the deal is loaded. An expires timestamp hides that row automatically.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["product", "brand", "filamentSlug", "price", "retailer", "url", "verifiedAt"],
        "properties": {
          "product": { "type": "string", "minLength": 1 },
          "brand": { "type": "string", "minLength": 1 },
          "brandSlug": { "type": "string" },
          "filamentSlug": { "type": "string", "minLength": 1 },
          "price": { "type": "number", "exclusiveMinimum": 0 },
          "regularPrice": { "type": ["number", "null"] },
          "pricePerKg": { "type": ["number", "null"] },
          "currency": { "type": "string", "pattern": "^[A-Za-z]{3}$" },
          "retailer": { "type": "string", "minLength": 1 },
          "url": { "type": "string", "pattern": "^https://" },
          "retailers": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["name", "url"],
              "properties": {
                "name": { "type": "string", "minLength": 1 },
                "url": { "type": "string", "pattern": "^https://" },
                "affiliate": { "type": "boolean", "description": "False for a manufacturer store. An Amazon shop URL is tagged on load and treated as an affiliate link." }
              }
            }
          },
          "verifiedAt": { "type": "string", "format": "date-time" },
          "expires": { "type": "string", "format": "date-time" },
          "sample": { "type": "boolean" },
          "note": { "type": "string" }
        }
      }
    }
  }
}
