page.cavu.progress

cavu.page

{
  "id": "page.cavu.progress",
  "defs": {
    "main": {
      "key": "tid",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "publication",
          "position",
          "updatedAt"
        ],
        "properties": {
          "percent": {
            "type": "integer",
            "maximum": 100,
            "minimum": 0,
            "description": "Denormalized whole-book completion percent at `position`, weighted over body-matter chapters, computed by the writing client (which has the book loaded). Lets list views render progress bars from this record plus the publication record alone. A serial's denominator grows with each release, so display against the live spine when possible."
          },
          "finished": {
            "type": "array",
            "items": {
              "ref": "com.atproto.repo.strongRef",
              "type": "ref"
            },
            "description": "Spine documents read to completion, each pinned at the cid it had when finished. A finished entry whose cid no longer matches the live record marks a chunk that changed after the reader read it; re-reading a changed chunk to completion replaces its entry with the new cid."
          },
          "furthest": {
            "ref": "#position",
            "type": "ref",
            "description": "Furthest position ever reached, when it differs from position (re-reading, or a device syncing an older current position). Clients max-merge by spine order: position is last-writer-wins, furthest never regresses."
          },
          "position": {
            "ref": "#position",
            "type": "ref",
            "description": "Where the reader currently is — the resume point."
          },
          "startedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the reader started the book."
          },
          "updatedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When this record was last written. Doubles as last-read-at for surfacing recently read books."
          },
          "finishedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the reader finished the book. Presence marks the book finished regardless of percent."
          },
          "publication": {
            "type": "string",
            "format": "at-uri",
            "description": "AT-URI of the book's site.standard.publication record — the backlink target."
          }
        }
      },
      "description": "Reading progress for one book, written to the reader's own repo. One record per (reader, publication) by convention: clients list their own repo and update the existing record for a publication rather than create a second (the BookHive shelf pattern). The publication AT-URI makes records discoverable by backlink index (Microcosm/Constellation), so 'who is reading this book' needs no app-side database. Positions anchor documents by strongRef: the cid pins the chunk *as read*, so a later edit to an already-read chunk is detectable by cid drift and clients can flag it. Repo records are currently public: clients must disclose at sign-in that reading positions are saved to the reader's own repo. These records are intended to move into permissioned spaces once that capability is live."
    },
    "position": {
      "type": "object",
      "required": [
        "document"
      ],
      "properties": {
        "document": {
          "ref": "com.atproto.repo.strongRef",
          "type": "ref",
          "description": "Spine document the reader is in, at the cid last seen by this client."
        },
        "thousandths": {
          "type": "integer",
          "maximum": 1000,
          "minimum": 0,
          "description": "How far through the document the reader is, in thousandths (0 = top, 1000 = end). Omit when unknown; clients treat absence as the top of the document."
        }
      },
      "description": "A place in a book: the spine document (pinned at its as-seen cid) plus how far through it the reader is. Fractional depth in thousandths keeps the grammar integer-only and is deliberately edit-tolerant — after an in-place edit it lands near the old spot and clamps, and the strongRef cid tells clients the ground shifted."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}

Validate Record

Validate a record against page.cavu.progress

Validation Options
Treat any remaining unresolved references as valid

Metadata

DID
did:plc:citulkqjdzbnf7wd5xb6lled
CID
bafyreifr6hijx7mlea7mlx4xwsugdhpw5f6wykt674m3ywdtft2ppjlxvi
Indexed At
2026-07-30 00:06 UTC
AT-URI
at://did:plc:citulkqjdzbnf7wd5xb6lled/com.atproto.lexicon.schema/page.cavu.progress

Version History (2 versions)

Lexicon Garden

@