at.rolld.play

rolld.at

Documentation

A single logged session of playing a board game. The high-volume event record. Reads ('times played', 'who played this game') are served by querying Constellation for backlinks to the 'target' URL — derived live, never stored.

main record

A single logged session of playing a board game. The high-volume event record. Reads ('times played', 'who played this game') are served by querying Constellation for backlinks to the 'target' URL — derived live, never stored.

Record Key tid Timestamp-based ID

Properties

bskyPostRef ref com.atproto.repo.strongRef Optional

Strong ref (uri + cid) to a companion app.bsky.feed.post, if the user chose to share this play on Bluesky. The post links back to the per-entry permalink (/@<handle>/play/<rkey>). Storing the ref also enables showing Bluesky replies as discussion on the entry later (the Leaflet POSSE pattern).

content union Optional

Optional rich note about how the play went. Open union (bring-your-own-content, like standard.site's content field) so the format can grow without a breaking change. v1 accepts markpub Markdown. Render via the $type; consumers that don't understand it fall back to textContent.

Known types:
createdAt string datetime Required

When this record was created.

durationMinutes integer Optional

How long the session actually took.

minimum: 0
images array of ref at.rolld.defs#image Optional

Optional photos of the play (board, table, scores). Up to 4, matching Bluesky's per-post image limit so the same blobs can be embedded in a companion app.bsky.feed.post. Each blob lives in the user's PDS and is referenced here; the photo is part of the play (not a standalone record). Powers the per-game photo gallery via the existing plays-of-this-game Constellation query (filter plays that have images). See DECISIONS D-33.

maxLength: 4 items
location string Optional

Free text: whose house, which convention, which cafe.

maxLength: 500 bytes
playedAt string datetime Required

When the play session occurred (may differ from createdAt if logged later).

players array of ref at.rolld.defs#player Optional

Who played. Each entry may carry an atproto DID (for real handles) and/or a plain display name.

target string uri Required

Canonical per-game web URL (https://rolld.at/g/<bggId>) that Constellation indexes as a backlink target. FROZEN format, emitted from one shared helper shared by write and read paths. This is the linchpin of the serverless read model — backlinks to this URL ARE the play aggregation. No catalog segment: game identity is permanently BGG-keyed.

textContent string Optional

Plain-text rendering of `content`, always populated when `content` is present. The universal fallback for any consumer that can't render the content union's $type, and the field to index for search/previews. Same role as standard.site's textContent. No grapheme limit.

maxLength: 100000 bytes
winnerDids array of string did Optional

DIDs of winning players, if any were recorded as identities.

winnerNames array of string Optional

Names of winners not represented by a DID.

View raw schema
{
  "key": "tid",
  "type": "record",
  "record": {
    "type": "object",
    "required": [
      "game",
      "target",
      "playedAt",
      "createdAt"
    ],
    "properties": {
      "game": {
        "ref": "at.rolld.defs#gameRef",
        "type": "ref",
        "description": "The game played, referenced by BGG id."
      },
      "images": {
        "type": "array",
        "items": {
          "ref": "at.rolld.defs#image",
          "type": "ref"
        },
        "maxLength": 4,
        "description": "Optional photos of the play (board, table, scores). Up to 4, matching Bluesky's per-post image limit so the same blobs can be embedded in a companion app.bsky.feed.post. Each blob lives in the user's PDS and is referenced here; the photo is part of the play (not a standalone record). Powers the per-game photo gallery via the existing plays-of-this-game Constellation query (filter plays that have images). See DECISIONS D-33."
      },
      "target": {
        "type": "string",
        "format": "uri",
        "description": "Canonical per-game web URL (https://rolld.at/g/<bggId>) that Constellation indexes as a backlink target. FROZEN format, emitted from one shared helper shared by write and read paths. This is the linchpin of the serverless read model — backlinks to this URL ARE the play aggregation. No catalog segment: game identity is permanently BGG-keyed."
      },
      "content": {
        "refs": [
          "at.markpub.markdown"
        ],
        "type": "union",
        "description": "Optional rich note about how the play went. Open union (bring-your-own-content, like standard.site's content field) so the format can grow without a breaking change. v1 accepts markpub Markdown. Render via the $type; consumers that don't understand it fall back to textContent."
      },
      "players": {
        "type": "array",
        "items": {
          "ref": "at.rolld.defs#player",
          "type": "ref"
        },
        "description": "Who played. Each entry may carry an atproto DID (for real handles) and/or a plain display name."
      },
      "location": {
        "type": "string",
        "maxLength": 500,
        "description": "Free text: whose house, which convention, which cafe."
      },
      "playedAt": {
        "type": "string",
        "format": "datetime",
        "description": "When the play session occurred (may differ from createdAt if logged later)."
      },
      "createdAt": {
        "type": "string",
        "format": "datetime",
        "description": "When this record was created."
      },
      "expansions": {
        "type": "array",
        "items": {
          "ref": "at.rolld.defs#gameRef",
          "type": "ref"
        },
        "description": "Expansions in play, by BGG id."
      },
      "winnerDids": {
        "type": "array",
        "items": {
          "type": "string",
          "format": "did"
        },
        "description": "DIDs of winning players, if any were recorded as identities."
      },
      "bskyPostRef": {
        "ref": "com.atproto.repo.strongRef",
        "type": "ref",
        "description": "Strong ref (uri + cid) to a companion app.bsky.feed.post, if the user chose to share this play on Bluesky. The post links back to the per-entry permalink (/@<handle>/play/<rkey>). Storing the ref also enables showing Bluesky replies as discussion on the entry later (the Leaflet POSSE pattern)."
      },
      "textContent": {
        "type": "string",
        "maxLength": 100000,
        "description": "Plain-text rendering of `content`, always populated when `content` is present. The universal fallback for any consumer that can't render the content union's $type, and the field to index for search/previews. Same role as standard.site's textContent. No grapheme limit."
      },
      "winnerNames": {
        "type": "array",
        "items": {
          "type": "string",
          "maxLength": 320
        },
        "description": "Names of winners not represented by a DID."
      },
      "durationMinutes": {
        "type": "integer",
        "minimum": 0,
        "description": "How long the session actually took."
      }
    }
  },
  "description": "A single logged session of playing a board game. The high-volume event record. Reads ('times played', 'who played this game') are served by querying Constellation for backlinks to the 'target' URL — derived live, never stored."
}

Lexicon Garden

@