Custom rosters

Repositories

A roster repository is a folder of packs, with two small index files that tell the game what's in it.

A pack holds one league on one day. A repository wraps your packs up so the game can list them, install them and see when a newer one comes out. It's the same folder whether it's zipped, on GitHub or on your own server.

roster-repository.json          the front page: who made it, and its sets
pond/                           a folder for each set, named for its id
  roster-set.json               the set's updates, by date
  2026-10-01/
    roster-pack.json            the pack as it was on October 1
  2026-10-05/
    roster-pack.json            and on October 5
    changes.md                  what changed since the update before

A repository can hold any number of sets. Each is a league that installs on its own, like your league, or the same teams with house rules. Each set has any number of updates, one per date.

roster-repository.json

The front page. It names the repository and lists its sets.

{
  "format": "bladeybiscuit.roster-repository",
  "formatVersion": 1,
  "name": "Example rosters",
  "description": "The example from the Blades & Biscuits custom rosters guide",
  "maintainer": "Blades & Biscuits",
  "homepage": "https://bladesandbiscuits.hockey/rosters/",
  "sets": [
    {
      "id": "pond",
      "name": "The Pond League",
      "league": "POND",
      "description": "Two made-up teams, for trying custom rosters out",
      "index": "pond/roster-set.json",
      "latest": "2026-10-05"
    }
  ]
}
Field What it does
format Required Always "bladeybiscuit.roster-repository".
formatVersion 1.
name The repository's name in the Rosters menu (default “Rosters”).
maintainer Who keeps it. Shown as “Kept by”.
description, homepage About it.
sets The sets in it.

Each set in sets:

Field What it does
id Required A short name for the set, unique in the repository, like "pond". Name its folder the same.
index Required Where its roster-set.json is, relative to this file: "pond/roster-set.json".
name Its name in the menus (default: its id).
league The league's letters, as in its packs.
description A line about it, shown while it's highlighted.
latest The date of its newest update. It's a hint: the game reads the set's own file for the real list.

roster-set.json

One set's updates. Each update is one pack.

{
  "format": "bladeybiscuit.roster-set",
  "formatVersion": 1,
  "id": "pond",
  "name": "The Pond League",
  "league": "POND",
  "description": "Two made-up teams, for trying custom rosters out",
  "updates": [
    {
      "date": "2026-10-05",
      "season": "2026-27",
      "file": "2026-10-05/roster-pack.json",
      "sha256": "ecfdbfe1f9b447036dc8d354c969dfa3505cf2aea43384db3562b48a62f9aa84",
      "size": 25482,
      "teams": 2,
      "players": 40,
      "notes": "Trades (1) · Lines · Ratings",
      "changes": "2026-10-05/changes.md"
    },
    {
      "date": "2026-10-01",
      "season": "2026-27",
      "file": "2026-10-01/roster-pack.json",
      "sha256": "c4c1ae45a6952ccd005afc178c788ae1afe6d4be5e380132933bd5218d03053a",
      "size": 25482,
      "teams": 2,
      "players": 40,
      "notes": "The first rosters of the season"
    }
  ]
}
Field What it does
format Required Always "bladeybiscuit.roster-set".
formatVersion 1.
id, name, league, description As in the repository's list.
updates Every update, in any order. The game sorts them newest first.

Each update:

Field What it does
date Required The day its rosters are as of, as yyyy-MM-dd. The game shows it as “Oct 5, 2026”. One update per date.
file Required The pack, relative to this file.
sha256 Recommended The pack's checksum. If the download doesn't match it, the game doesn't install it.
season Shown next to the date.
size The pack's size in bytes.
teams, players How many of each. The game shows these when you pick an update, so fill them in.
notes A line about what's new, shown when you pick an update.
changes A longer write-up, as a Markdown file beside the pack, for anyone browsing the repository. The game doesn't show it yet.

The checker works out sha256, size, teams and players for a pack and writes the whole update for you.

Updates and history

  • Add a new update for each change. Make a new dated folder with the new pack, and add it to updates. Keep the old ones: people can go back to any date, like the rosters from the start of the season.
  • Keep latest in step. Change the set's latest in roster-repository.json to the new date too.
  • People see it as an update. When they check the repository, the game reads each set's roster-set.json, and if there's a newer date than the one they installed, it says “Update available”.
  • One date per set is installed at a time. Installing another date replaces it. A game in progress keeps the rosters it started with.
  • Fixing a mistake? You can replace a pack and update its sha256 and size, but anyone who already installed that date won't be told. A new date is better.

Checksums

A SHA-256 checksum is a 64-character fingerprint of a file. Change one letter in the pack and it's completely different. The game works out the fingerprint of every pack it downloads and compares it with sha256, so a half-uploaded or out-of-date file never gets installed.

The checker gives you a pack's checksum. Or, from a terminal:

On Run
Mac shasum -a 256 roster-pack.json
Windows (PowerShell) (Get-FileHash roster-pack.json).Hash
Linux sha256sum roster-pack.json

Capitals or not, either works. Leave sha256 out and the game skips the check. That's handy while you're trying things out, but put it back before you share.

Paths

index, file and changes are paths relative to the file they're in. So the repository works the same zipped, on a web server or on your computer. The game is strict about them, so a repository can never point outside itself:

  • Forward slashes between folders: pond/2026-10-05/roster-pack.json.
  • Letters, digits, ., _ and - only, with each name starting with a letter or digit. No spaces, no .., and no names starting with a dot.
  • At most 8 names long (the folders and the file) and 200 characters.
  • No names Windows reserves, like con or aux.

A set index with a bad path is refused as a whole, so the checker is worth running after any change.

Zipped repositories

A repository zips up as it is. Settings ▸ Rosters ▸ Import a zip unpacks it and installs the newest update of every set in it.

  • roster-repository.json goes at the top of the zip, or inside one folder, which is what you get when you zip a folder. GitHub's “Download ZIP” works too.
  • Only .json, .md, .txt and .csv files, and .png and .jpg pictures, are taken. Anything else in the zip is skipped, and so is the junk Macs and Windows leave behind (__MACOSX, .DS_Store, Thumbs.db).
  • The game refuses a zip with an unsafe path in it, two files whose names differ only in capitals, more than 20,000 files, a file over 32 MB, or more than 1 GB in all.

A pack the game downloads can be up to 64 MB. A whole league is usually under 1 MB. Its pictures are downloaded and checked with it.