{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://bobku.net/edm-artist/data/catalog-schema.json",
  "title": "Bobku Public Music Catalog Dataset",
  "description": "Schema documentation for the public Bobku music catalog export. The export includes song, album, identifier, genre, narrative, dedication, and link metadata. Full lyrics are intentionally excluded from the main JSON export.",
  "version": "2026-05-15",
  "generatedAtUtc": "2026-05-15T03:12:25+00:00",
  "type": "object",
  "required": [
    "dataset",
    "artist",
    "recordCounts",
    "albums",
    "songs"
  ],
  "properties": {
    "dataset": {
      "type": "object",
      "description": "Dataset-level metadata.",
      "properties": {
        "name": {
          "type": "string"
        },
        "version": {
          "type": "string",
          "description": "Export version date."
        },
        "generatedAtUtc": {
          "type": "string",
          "format": "date-time"
        },
        "description": {
          "type": "string"
        },
        "license": {
          "type": "string",
          "format": "uri"
        },
        "canonicalUrl": {
          "type": "string",
          "format": "uri"
        },
        "lyricsPolicy": {
          "type": "string",
          "format": "uri"
        }
      }
    },
    "artist": {
      "type": "object",
      "description": "Artist/entity metadata for Bobku.",
      "properties": {
        "name": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "musicBrainzArtistId": {
          "type": "string"
        },
        "wikidataQid": {
          "type": "string"
        },
        "googleKnowledgeGraphMid": {
          "type": "string"
        }
      }
    },
    "recordCounts": {
      "type": "object",
      "description": "Row counts from the source SQLite tables at export time.",
      "additionalProperties": {
        "type": "integer"
      }
    },
    "albums": {
      "type": "array",
      "description": "Album and EP records referenced by the catalog.",
      "items": {
        "$ref": "#/$defs/album"
      }
    },
    "songs": {
      "type": "array",
      "description": "Denormalized song records.",
      "items": {
        "$ref": "#/$defs/song"
      }
    }
  },
  "$defs": {
    "album": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "tagline": {
          "type": "string"
        },
        "releaseDate": {
          "type": "string",
          "description": "ISO-style release date when available."
        },
        "upc": {
          "type": "string"
        },
        "coverImageUrl": {
          "type": "string"
        },
        "canonicalUrl": {
          "type": "string",
          "format": "uri"
        },
        "musicbrainzUrl": {
          "type": "string",
          "format": "uri"
        }
      }
    },
    "song": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "urlSlug": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "subtitle": {
          "type": "string"
        },
        "canonicalUrl": {
          "type": "string",
          "format": "uri"
        },
        "album": {
          "$ref": "#/$defs/album"
        },
        "trackNumber": {
          "type": "integer"
        },
        "releaseDate": {
          "type": "string"
        },
        "durationSeconds": {
          "type": "integer"
        },
        "durationDisplay": {
          "type": "string"
        },
        "durationIso8601": {
          "type": "string"
        },
        "bpm": {
          "type": "string",
          "description": "Human-facing BPM value. May include dual-tempo notation."
        },
        "bpmSpotify": {
          "type": "integer"
        },
        "camelotKey": {
          "type": "string"
        },
        "leadProducer": {
          "type": "string"
        },
        "genres": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "identifiers": {
          "$ref": "#/$defs/identifiers"
        },
        "festival": {
          "$ref": "#/$defs/festival"
        },
        "dedication": {
          "type": "string"
        },
        "dedicationSourceDoc": {
          "type": "string"
        },
        "links": {
          "$ref": "#/$defs/links"
        },
        "lyrics": {
          "$ref": "#/$defs/lyrics"
        }
      }
    },
    "identifiers": {
      "type": "object",
      "description": "Public music registration and catalog identifiers.",
      "properties": {
        "isrc": {
          "type": "string"
        },
        "iswc": {
          "type": "string"
        },
        "upc": {
          "type": "string"
        },
        "bmiWorkNumber": {
          "type": "string",
          "description": "BMI work registration number."
        },
        "mlcSongCode": {
          "type": "string",
          "description": "Mechanical Licensing Collective song code."
        },
        "musicbrainzRecordingUrl": {
          "type": "string",
          "format": "uri"
        }
      }
    },
    "festival": {
      "type": "object",
      "description": "Feltware Festival narrative placement and in-universe context.",
      "properties": {
        "cueIn": {
          "type": "string"
        },
        "primaryType": {
          "type": "string"
        },
        "primaryDetail": {
          "type": "string"
        },
        "secondaryType": {
          "type": "string"
        },
        "secondaryDetail": {
          "type": "string"
        },
        "narrativeShort": {
          "type": "string"
        },
        "narrativeFull": {
          "type": "string"
        },
        "narrativeNote": {
          "type": "string"
        },
        "producerNote": {
          "type": "string"
        }
      }
    },
    "links": {
      "type": "object",
      "description": "Canonical Bobku page URL and external platform/reference links.",
      "properties": {
        "canonicalUrl": {
          "type": "string",
          "format": "uri"
        },
        "spotify": {
          "type": "string",
          "format": "uri"
        },
        "youtubeSong": {
          "type": "string",
          "format": "uri"
        },
        "youtubeVideo": {
          "type": "string",
          "format": "uri"
        },
        "youtubeMusic": {
          "type": "string",
          "format": "uri"
        },
        "amazon": {
          "type": "string",
          "format": "uri"
        },
        "apple": {
          "type": "string",
          "format": "uri"
        },
        "soundcloud": {
          "type": "string",
          "format": "uri"
        },
        "bandcamp": {
          "type": "string",
          "format": "uri"
        },
        "genius": {
          "type": "string",
          "format": "uri"
        },
        "musixmatch": {
          "type": "string",
          "format": "uri"
        },
        "musicbrainz": {
          "type": "string",
          "format": "uri"
        }
      }
    },
    "lyrics": {
      "type": "object",
      "description": "Lyric availability metadata. Full lyric text is intentionally excluded from the main public JSON export.",
      "properties": {
        "available": {
          "type": "boolean"
        },
        "format": {
          "type": "string"
        },
        "source": {
          "type": "string"
        },
        "updatedUtc": {
          "type": "string"
        },
        "includedInBulkExport": {
          "type": "boolean",
          "const": false
        },
        "pageUrl": {
          "type": "string",
          "format": "uri"
        },
        "reusePolicy": {
          "type": "string",
          "format": "uri"
        }
      }
    }
  }
}
