{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.seatlayer.io/schemas/venue-spec-v1.json",
  "title": "SeatLayer Venue Spec",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "seatlayerVenueSpec",
    "name",
    "categories"
  ],
  "properties": {
    "$schema": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "Optional: https://docs.seatlayer.io/schemas/venue-spec-v1.json"
    },
    "seatlayerVenueSpec": {
      "const": 1,
      "description": "Always 1. Tells SeatLayer this file is a Venue Spec"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 160,
      "description": "Venue or chart name"
    },
    "categories": {
      "type": "array",
      "minItems": 1,
      "maxItems": 7,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "For example \"Premium\", \"Standard\" or \"Standing\""
          },
          "price": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000,
            "description": "Ticket price in the event currency. Leave out to set it later"
          },
          "color": {
            "type": "string",
            "minLength": 7,
            "maxLength": 7,
            "pattern": "^#[0-9a-fA-F]{6}$",
            "description": "Six-digit hex colour. Leave out for a readable default"
          }
        },
        "description": "One ticket type"
      },
      "description": "Ticket types, most expensive first. Every seat, table, booth and standing area sells under one of these"
    },
    "base": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "layout"
      ],
      "properties": {
        "layout": {
          "type": "string",
          "enum": [
            "rows",
            "bowl",
            "tables",
            "ushape",
            "booths",
            "nightclub",
            "runway",
            "restaurant",
            "hybrid"
          ],
          "description": "rows = theatre; bowl = arena ring of stands; tables = banquet; ushape; booths = expo; nightclub = standing + VIP; runway; restaurant; hybrid = seats + standing"
        },
        "rowCount": {
          "type": "integer",
          "minimum": 1,
          "maximum": 40,
          "description": "Rows per block or stand (rows, bowl, runway, hybrid)"
        },
        "seatsPerRow": {
          "type": "integer",
          "minimum": 1,
          "maximum": 800,
          "description": "Seats in each row: the whole row across all blocks (rows, hybrid), or one stand's row (bowl, runway)"
        },
        "blocks": {
          "type": "integer",
          "minimum": 1,
          "maximum": 8,
          "description": "Side-by-side blocks (rows, hybrid)"
        },
        "sectionCount": {
          "type": "integer",
          "minimum": 2,
          "maximum": 16,
          "description": "Stands around the ring (bowl). Default 4"
        },
        "tableRows": {
          "type": "integer",
          "minimum": 1,
          "maximum": 20,
          "description": "Rows of tables (tables, ushape)"
        },
        "tableColumns": {
          "type": "integer",
          "minimum": 1,
          "maximum": 20,
          "description": "Tables per row (tables, ushape)"
        },
        "boothRows": {
          "type": "integer",
          "minimum": 1,
          "maximum": 30,
          "description": "Rows of booths (booths)"
        },
        "boothColumns": {
          "type": "integer",
          "minimum": 1,
          "maximum": 30,
          "description": "Booths per row (booths)"
        },
        "standingCapacity": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100000,
          "description": "Standing capacity (bowl floor pit, nightclub, hybrid)"
        },
        "floors": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "default": 1,
          "description": "Physical floors (rows, bowl). Default 1"
        },
        "stageKind": {
          "type": "string",
          "enum": [
            "rect",
            "rounded",
            "arc",
            "thrust",
            "runway",
            "round"
          ],
          "default": "rect",
          "description": "Stage shape. Default rect"
        },
        "sectionNames": {
          "type": "array",
          "minItems": 1,
          "maxItems": 100,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "A section name"
          },
          "description": "Names for the generated sections, clockwise from the top of the map (the stage end): for a four-stand bowl, North, East, South, West"
        }
      },
      "description": "Optional: start from a whole ready-made venue, then add items. Best for arenas and multi-floor venues. Categories are shared across its blocks in order"
    },
    "stage": {
      "anyOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": [],
          "properties": {
            "kind": {
              "type": "string",
              "enum": [
                "rect",
                "rounded",
                "arc",
                "thrust",
                "runway",
                "round",
                "pitch-football",
                "rink-hockey",
                "track-athletics",
                "oval-cricket",
                "pitch-rugby",
                "diamond-baseball",
                "court-basketball",
                "court-tennis",
                "ring-boxing"
              ],
              "default": "rect",
              "description": "Stage shape, or a sports surface such as court-basketball or ring-boxing. Default rect"
            },
            "label": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80,
              "description": "Its name, for example \"Main Stage\". Default depends on kind"
            },
            "widthM": {
              "type": "number",
              "minimum": 1,
              "maximum": 400,
              "description": "Width in metres"
            },
            "depthM": {
              "type": "number",
              "minimum": 1,
              "maximum": 400,
              "description": "Depth in metres"
            }
          },
          "description": "The stage"
        },
        {
          "const": false,
          "description": "No stage"
        }
      ],
      "description": "The stage or playing surface every seat faces, placed at the front. Leave out for a plain stage; false for none (an expo hall). Not used with base"
    },
    "items": {
      "type": "array",
      "minItems": 0,
      "maxItems": 80,
      "items": {
        "oneOf": [
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "rowCount",
              "seatsPerRow"
            ],
            "properties": {
              "type": {
                "const": "rows",
                "description": "rows"
              },
              "rowCount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100,
                "description": "How many rows"
              },
              "seatsPerRow": {
                "type": "integer",
                "minimum": 1,
                "maximum": 300,
                "description": "Seats in each whole row, counted across all blocks: 24 with blocks 2 is two blocks of 12"
              },
              "blocks": {
                "type": "integer",
                "minimum": 1,
                "maximum": 8,
                "default": 1,
                "description": "Side-by-side blocks with an aisle between each; 2 = one centre aisle. Default 1"
              },
              "category": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Name of one entry in categories. May be left out when there is only one category"
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Where it goes against everything placed so far: front (toward the stage), rear (behind it all), left or right. Default rear"
              },
              "section": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Put it in a section with this name, as buyers will see it (for example \"Stalls\" or \"Balcony\")"
              }
            },
            "description": "Straight rows of seats, optionally split into side-by-side blocks with aisles between them"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "rowCount"
            ],
            "properties": {
              "type": {
                "const": "curvedRows",
                "description": "curvedRows"
              },
              "rowCount": {
                "type": "integer",
                "minimum": 1,
                "maximum": 60,
                "description": "How many curved rows"
              },
              "spreadDegrees": {
                "type": "number",
                "minimum": 20,
                "maximum": 360,
                "description": "How wide the fan is: 100 = theatre, 180 = semicircle, 360 = all the way round. Default: just wide enough for seatsPerRow, or 100 without it. With both set, the rows sit far enough out for the seats to fit"
              },
              "seatsPerRow": {
                "type": "integer",
                "minimum": 2,
                "maximum": 300,
                "description": "Seats in every row. Leave out to fit seats at the standard spacing (outer rows get more)"
              },
              "aisles": {
                "type": "string",
                "enum": [
                  "none",
                  "center",
                  "two"
                ],
                "default": "none",
                "description": "Aisles through the fan. Default none"
              },
              "firstRowDistanceM": {
                "type": "number",
                "minimum": 1,
                "maximum": 200,
                "default": 4,
                "description": "Metres from the stage to the first row when nothing is there yet. Default 4"
              },
              "category": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Name of one entry in categories. May be left out when there is only one category"
              },
              "section": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Put it in a section with this name, as buyers will see it (for example \"Stalls\" or \"Balcony\")"
              }
            },
            "description": "Rows that curve around the stage, as in a theatre or amphitheatre, placed behind any seats already there"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "tableRows",
              "tableColumns"
            ],
            "properties": {
              "type": {
                "const": "tables",
                "description": "tables"
              },
              "tableRows": {
                "type": "integer",
                "minimum": 1,
                "maximum": 20,
                "description": "Rows of tables"
              },
              "tableColumns": {
                "type": "integer",
                "minimum": 1,
                "maximum": 20,
                "description": "Tables in each row"
              },
              "seatsPerTable": {
                "type": "integer",
                "minimum": 1,
                "maximum": 20,
                "default": 8,
                "description": "Chairs at each table. Default 8"
              },
              "shape": {
                "type": "string",
                "enum": [
                  "round",
                  "rect"
                ],
                "default": "round",
                "description": "round or rect. Default round"
              },
              "category": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Name of one entry in categories. May be left out when there is only one category"
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Where it goes against everything placed so far: front (toward the stage), rear (behind it all), left or right. Default rear"
              },
              "section": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Put them in a section with this name. When the venue has other sections and this is left out, they get one named after their category, so phones show them"
              }
            },
            "description": "A grid of round or rectangular tables with chairs, as at a wedding, gala or cabaret"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "capacity"
            ],
            "properties": {
              "type": {
                "const": "standing",
                "description": "standing"
              },
              "capacity": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100000,
                "description": "How many people it holds"
              },
              "label": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Its name, for example \"Pit\" or \"Dance floor standing\". Default \"General Admission\""
              },
              "category": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Name of one entry in categories. May be left out when there is only one category"
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Where it goes against everything placed so far: front (toward the stage), rear (behind it all), left or right. Default rear"
              }
            },
            "description": "A standing (general admission) area sold by capacity, not by seat"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "boothRows",
              "boothColumns"
            ],
            "properties": {
              "type": {
                "const": "booths",
                "description": "booths"
              },
              "boothRows": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "description": "Rows of booths"
              },
              "boothColumns": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "description": "Booths in each row"
              },
              "category": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Name of one entry in categories. May be left out when there is only one category"
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Where it goes against everything placed so far: front (toward the stage), rear (behind it all), left or right. Default rear"
              },
              "section": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Put them in a section with this name. When the venue has other sections and this is left out, they get one named after their category, so phones show them"
              }
            },
            "description": "A grid of expo or market booths, each sold whole"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "landmark",
                "description": "landmark"
              },
              "role": {
                "type": "string",
                "enum": [
                  "bar",
                  "entrance",
                  "exit",
                  "restroom",
                  "screen",
                  "sound",
                  "concession",
                  "coat",
                  "wall",
                  "rail",
                  "suite",
                  "obstruction"
                ],
                "description": "A drawn landmark. Give role or icon, not both"
              },
              "icon": {
                "type": "string",
                "enum": [
                  "restroom-men",
                  "restroom-women",
                  "restroom-accessible",
                  "first-aid",
                  "coat-check",
                  "atm",
                  "info",
                  "lost-found",
                  "restrooms",
                  "charging",
                  "smoking",
                  "no-smoking",
                  "food",
                  "bar",
                  "coffee",
                  "water",
                  "merch",
                  "screen",
                  "sound-booth",
                  "entrance",
                  "exit",
                  "emergency-exit",
                  "stairs",
                  "elevator",
                  "parking",
                  "wheelchair",
                  "hearing",
                  "box-office",
                  "escalator",
                  "ramp",
                  "taxi",
                  "transit",
                  "bike-parking",
                  "meeting-point",
                  "security",
                  "lockers",
                  "baby-change",
                  "prayer-room",
                  "quiet-room",
                  "wifi",
                  "vip-lounge",
                  "accessible-entrance",
                  "assistance-dog"
                ],
                "description": "A small wayfinding icon. Give role or icon, not both"
              },
              "label": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Its name on the map, for example \"Main bar\" or \"Entrance A\""
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right",
                  "center"
                ],
                "default": "rear",
                "description": "Where it goes: front (between the stage and the seats), rear, left, right or center. Default rear. Two items both at rear go one behind the other; to put one next to another, use near and side"
              },
              "near": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Place it next to something named earlier: a section, landmark, area or standing area (for example \"Bar\" or \"Stalls\"), instead of against the whole layout"
              },
              "nearSection": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Older name for near, for a section"
              },
              "side": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Which side of near: front, rear, left or right. Default rear"
              }
            },
            "oneOf": [
              {
                "required": [
                  "role"
                ]
              },
              {
                "required": [
                  "icon"
                ]
              }
            ],
            "description": "Something buyers find their way by: a bar, entrance, exit, restrooms, or a small icon such as first aid"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "text"
            ],
            "properties": {
              "type": {
                "const": "text",
                "description": "text"
              },
              "text": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120,
                "description": "The words"
              },
              "size": {
                "type": "string",
                "enum": [
                  "small",
                  "medium",
                  "large"
                ],
                "default": "medium",
                "description": "Default medium"
              },
              "showAt": {
                "type": "string",
                "enum": [
                  "always",
                  "when-it-fits",
                  "close-up"
                ],
                "default": "when-it-fits",
                "description": "When buyers see it: always, when-it-fits, or only close-up. Default when-it-fits"
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right",
                  "center"
                ],
                "default": "rear",
                "description": "Where it goes: front (between the stage and the seats), rear, left, right or center. Default rear. Two items both at rear go one behind the other; to put one next to another, use near and side"
              },
              "near": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Place it next to something named earlier: a section, landmark, area or standing area (for example \"Bar\" or \"Stalls\"), instead of against the whole layout"
              },
              "nearSection": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Older name for near, for a section"
              },
              "side": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Which side of near: front, rear, left or right. Default rear"
              }
            },
            "description": "A sign on the map, for example \"Gate C\" or \"Balcony via stairs B\""
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "label",
              "widthM",
              "depthM"
            ],
            "properties": {
              "type": {
                "const": "area",
                "description": "area"
              },
              "label": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Its name on the map"
              },
              "widthM": {
                "type": "number",
                "minimum": 0.5,
                "maximum": 400,
                "description": "Width in metres"
              },
              "depthM": {
                "type": "number",
                "minimum": 0.5,
                "maximum": 400,
                "description": "Depth in metres"
              },
              "shape": {
                "type": "string",
                "enum": [
                  "rect",
                  "ellipse"
                ],
                "default": "rect",
                "description": "Default rect"
              },
              "placement": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right",
                  "center"
                ],
                "default": "rear",
                "description": "Where it goes: front (between the stage and the seats), rear, left, right or center. Default rear. Two items both at rear go one behind the other; to put one next to another, use near and side"
              },
              "near": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Place it next to something named earlier: a section, landmark, area or standing area (for example \"Bar\" or \"Stalls\"), instead of against the whole layout"
              },
              "nearSection": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Older name for near, for a section"
              },
              "side": {
                "type": "string",
                "enum": [
                  "front",
                  "rear",
                  "left",
                  "right"
                ],
                "default": "rear",
                "description": "Which side of near: front, rear, left or right. Default rear"
              }
            },
            "description": "A named space nobody books, sized in metres: a dance floor, registration desk, mixing desk or VIP lounge"
          }
        ]
      },
      "description": "What to add, in order, from the stage outward. Each item is placed against everything before it"
    }
  },
  "description": "A SeatLayer Venue Spec: what a venue has, in words and counts. SeatLayer places everything; never give coordinates."
}
