πŸ“š biblio.bond

decentralized peer-to-peer reading attestation

dev guide

Login via AT Protocol
Works with any Bluesky account

Developer Guide

biblio.bond is built on the AT Protocol as an experiment in humanized connections through co-reading. This guide is meant to explain how the lexicons work and how to use them for your own free purposes. We believe bonded readership improves communication and empathy.

⚠️ Status & Transparency

Experimental Community Project

These lexicons are not officially registered with Bluesky. This is a community experiment in decentralized reading attestation. The namespace and schema may change.

πŸ“„ Lexicon Files

πŸ” View Live Records

Search for these collections on the AT Protocol Browser to see real records:

  • biblio.bond.book
  • biblio.bond.list
  • biblio.bond.stamp
Open AT Protocol Browser β†’

How Data Storage Works

All book, list, and stamp records live on YOUR personal data server (PDS). biblio.bond runs a firehose monitor that indexes these records for discovery and matching, caching titles, authors, and timestamps to calculate biblio.bonds and enable search. Your reading history is public on your PDS by AT Protocol design.

Overview

πŸ“Œ Version 2.0 (December 2025)

Lexicons updated for cross-lexicon compatibility! The authors field now supports multiple authors and matches BookHive's schema. Stamps are lexicon-agnostic and work with any book record type.

biblio.bond uses three simple record types to create a decentralized reading attestation system:

    biblio.bond.book - Personal reading records (created by readers)
    biblio.bond.list - Reading challenges (created by librarians)
    biblio.bond.stamp - Completion attestations (issued by librarians)

πŸ”„ How It Works

  1. Readers create biblio.bond.book records on their PDS for books they've read
  2. Librarians create biblio.bond.list reading challenges with specific books and deadlines
  3. Readers notify librarians when they've completed a book from a list
  4. Librarians review completions and issue biblio.bond.stamp attestations
  5. Everyone can verify stamps cryptographically via AT Protocol
  6. Bonds are calculated between readers who have stamps for the same book

πŸ”‘ Key Concept: Authority Model

Stamps live in the librarian's repository, not the reader's. This creates a trust model: you trust the librarian's attestation that the reader completed the book. The stamp URI itself proves who validated it and when.

βš™οΈ Limitations & Considerations

Experimental Lexicons

These lexicons are community-created and may evolve. Use freely for your own reading projects.

πŸ“– biblio.bond.book

Purpose: Track books you've read

Schema (v2.0)

{
  "$type": "biblio.bond.book",
  "title": string (required, max 500 chars),
  "authors": string (required, max 2048 chars, tab-separated for multiple),
  "createdAt": datetime (ISO 8601)
}

Example

{
  "$type": "biblio.bond.book",
  "title": "A Wizard of Earthsea",
  "authors": "Ursula K. Le Guin",
  "createdAt": "2024-11-15T12:00:00Z"
}

// Multiple authors example:
{
  "$type": "biblio.bond.book",
  "title": "The Difference Engine",
  "authors": "William Gibson\tBruce Sterling",
  "createdAt": "2024-11-15T12:00:00Z"
}

πŸ“ Changes in v2.0

  • authors field (replaces singular author) - supports multiple authors separated by tabs
  • Removed joins array - participation is now tracked via stamps, not embedded in books
  • Field name matches BookHive's authors for cross-lexicon compatibility

πŸ“‹ biblio.bond.list

Purpose: Create reading challenges with specific books and deadlines

Schema (v2.0)

{
  "$type": "biblio.bond.list",
  "title": string (optional, max 200 chars),
  "librarians": [did] (required, array of DIDs),
  "books": [
    {
      "title": string (required, max 500 chars),
      "authors": string (required, max 200 chars)
    }
  ] (required),
  "duedate": datetime (required, ISO 8601)
}

Example

{
  "$type": "biblio.bond.list",
  "title": "Earthsea December 2024",
  "librarians": ["did:plc:librarian123..."],
  "books": [
    {
      "title": "A Wizard of Earthsea",
      "authors": "Ursula K. Le Guin"
    },
    {
      "title": "The Tombs of Atuan",
      "authors": "Ursula K. Le Guin"
    }
  ],
  "duedate": "2024-12-31T23:59:59Z"
}

πŸ“ Notes

The librarians array can have multiple DIDs for collaborative lists. The duedate is enforced - stamps are only valid for books created before this timestamp. Books are embedded in the list (not URIs) for ease.

βœ“ biblio.bond.stamp

Purpose: Librarian-issued validation of book completion

Schema (v2.0)

{
  "$type": "biblio.bond.stamp",
  "list": at-uri (required, URI of the list),
  "book": at-uri (required, URI of the book - ANY book lexicon),
  "createdAt": datetime (ISO 8601, optional)
}

Example

// Stamp for biblio.bond.book:
{
  "$type": "biblio.bond.stamp",
  "list": "at://did:plc:lib.../biblio.bond.list/xyz789",
  "book": "at://did:plc:reader.../biblio.bond.book/abc123",
  "createdAt": "2024-12-15T18:30:00Z"
}

// Stamp for BookHive book (cross-lexicon):
{
  "$type": "biblio.bond.stamp",
  "list": "at://did:plc:lib.../biblio.bond.list/xyz789",
  "book": "at://did:plc:reader.../buzz.bookhive.book/def456",
  "createdAt": "2024-12-15T18:30:00Z"
}

πŸ“ Key Features

  • Lexicon-agnostic: The book field accepts ANY at-uri. Works with biblio.bond.book, buzz.bookhive.book, or future book lexicons.
  • Authority model: Stamps live in the librarian's repository, proving WHO validated the completion.
  • Reader extraction: The reader's DID is extracted from the book URI automatically.
  • Trust-based: You trust the librarian who issued the stamp, not self-reported completions.

🌐 Cross-Lexicon Compatibility

How Stamps Work Across Different Book Lexicons

Stamps don't care what type of book record they reference. This means a librarian can stamp completions from users of any book tracking system that uses AT Protocol, including BookHive, custom lexicons, or future systems.

Example: Stamping a BookHive User

Scenario: Alice uses BookHive to track her books. Bob runs a biblio.bond reading list. Can Alice participate?

  1. Alice adds "The Dispossessed" to BookHive:
    at://did:plc:alice/buzz.bookhive.book/xyz123
  2. Alice notifies librarian Bob: "I finished The Dispossessed"
  3. Bob verifies Alice's completion and issues a stamp:
    {
      "$type": "biblio.bond.stamp",
      "list": "at://did:plc:bob/biblio.bond.list/winterchallenge",
      "book": "at://did:plc:alice/buzz.bookhive.book/xyz123",
      "createdAt": "2024-12-15T10:00:00Z"
    }
  4. The stamp lives in Bob's repository, proving he validated Alice's completion
  5. Alice's DID is extracted from the book URI: did:plc:alice

What This Enables

βœ… Works Today
  • Librarian can stamp any book URI
  • Stamp is valid at protocol level
  • Proves completion cryptographically
⏳ Application Support Needed
  • biblio.bond needs to index BookHive records
  • Bond calculation across lexicons
  • UI showing mixed participants

Key Distinction

Protocol (lexicons): The stamp lexicon intentionally accepts any book URI. We're leaving this open so books can be tracked in different systems (biblio.bond, BookHive, custom implementations) while still participating in the same reading communities.

Application (biblio.bond): This is a separate concern. The biblio.bond application currently only indexes biblio.bond.book records from the firehose. To display BookHive users in lists or calculate bonds across lexicons, the application would need to index additional lexicon types. The protocol doesn't enforce what you indexβ€”that's an implementation choice.

πŸ’‘ For Developers

To support cross-lexicon bonds in your app, you'd need to:

  1. Index multiple book lexicons from the firehose
  2. Normalize book identities (match "The Dispossessed" by "Ursula K. Le Guin" across different lexicons)
  3. Calculate bonds by grouping stamps with matching normalized books

See biblio.bond/docs for implementation details.

πŸ”§ API Examples

Create a Book Record

from atproto import Client

client = Client()
client.login('your-handle.bsky.social', 'app-password')

book = {
    "$type": "biblio.bond.book",
    "title": "A Wizard of Earthsea",
    "authors": "Ursula K. Le Guin",
    "createdAt": "2024-11-15T12:00:00Z"
}

result = client.com.atproto.repo.create_record({
    'repo': client.me.did,
    'collection': 'biblio.bond.book',
    'record': book
})

print(f"Created book: {result.uri}")

Create a Reading List

reading_list = {
    "$type": "biblio.bond.list",
    "title": "Earthsea Challenge",
    "librarians": [client.me.did],
    "books": [
    "books": [
        {
            "title": "A Wizard of Earthsea",
            "authors": "Ursula K. Le Guin"
        }
    ],uedate": "2024-12-31T23:59:59Z",
    "createdAt": "2024-11-01T00:00:00Z"
}

result = client.com.atproto.repo.create_record({
    'repo': client.me.did,
    'collection': 'biblio.bond.list',
    'record': reading_list
})

print(f"Created list: {result.uri}")

Issue a Stamp

stamp = {
    "$type": "biblio.bond.stamp",
    "list": "at://did:plc:lib.../biblio.bond.list/xyz",
    "book": "at://did:plc:reader.../biblio.bond.book/abc",
    "createdAt": "2024-12-15T18:30:00Z"
}

result = client.com.atproto.repo.create_record({
    'repo': client.me.did,
    'collection': 'biblio.bond.stamp',
    'record': stamp
})

print(f"Issued stamp: {result.uri}")

πŸ”— Integration

Firehose Monitoring

Monitor the AT Protocol firehose for new biblio.bond records:

from atproto import FirehoseSubscribeReposClient

def on_message(message):
    if message.path.startswith('biblio.bond.'):
        print(f"New record: {message.path}")

client = FirehoseSubscribeReposClient()
client.start(on_message)

Query Records

List all records for a user:

records = client.com.atproto.repo.list_records({
    'repo': 'did:plc:user...',
    'collection': 'biblio.bond.book'
})

for record in records.records:
for record in records.records:
    print(f"{record.value.title} by {record.value.authors}")
    

πŸ“š Resources

Questions or feedback? Contact @libre.reverie.house