This repository has no description
readme.md

constellation 🌌 #

A global atproto backlink index ✨

  • Self hostable: handles the full write throughput of the global atproto firehose on a raspberry pi 4b + single SSD
  • Storage efficient: less than 2GB/day disk consumption indexing all references in all lexicons and all non-atproto URLs
  • Handles record deletion, account de/re-activation, and account deletion, ensuring accurate link counts and respecting users data choices
  • Simple JSON API

All social interactions in atproto tend to be represented by links (or references) between PDS records. This index can answer questions like "how many likes does a bsky post have", "who follows an account", "what are all the comments on a frontpage post", and more.

note: the public instance currently runs on a little raspberry pi in my house, feel free to use it! it comes with only with best-effort uptime, no commitment to not breaking the api for now, and possible rate-limiting. if you want to be nice you can put your project name and bsky username (or email) in your user-agent header for api requests.

API endpoints #

currently this is a bit out of date -- refer to the api docs hosted by the app itself for now. they also let you try out live requests.

terms as used here:

  • "URI": a URI, AT-URI, or DID.
  • "JSON path": a dot-separated (and dot-prefixed, for now) path to a field in an atproto record. Arrays are noted by [] and cannot contain a specific index.

GET /links/count #

The number of backlinks to a URI from a specified collection + json path.

Required URL parameters #

  • target (required): the URI. must be URL-encoded.
    • example: at%3A%2F%2Fdid%3Aplc%3A57vlzz2egy6eqr4nksacmbht%2Fapp.bsky.feed.post%2F3lg2pgq3gq22b
  • collection (required): the source NSID of referring documents to consider.
    • example: app.bsky.feed.post
  • path (required): the JSON path in referring documents to consider.
    • example: .subject.uri

Response #

A number (u64) in plain text format

cURL example: Get a count of all bluesky likes for a post #

curl '<HOST>/links/count?target=at%3A%2F%2Fdid%3Aplc%3A57vlzz2egy6eqr4nksacmbht%2Fapp.bsky.feed.post%2F3lg2pgq3gq22b&collection=app.bsky.feed.like&path=.subject.uri'

40

GET /links/all/count #

The number of backlinks to a URI from any source collection or json path

Required URL parameters #

  • target (required): the URI. must be URL-encoded.
    • example: did:plc:vc7f4oafdgxsihk4cry2xpze

Response #

A JSON object {[NSID]: {[JSON path]: [N]}}

cURL example: Get reference counts to a DID from any collection at any path #

curl '<HOST>/links/all/count?target=did:plc:vc7f4oafdgxsihk4cry2xpze'

curl '<HOST>/links/all/count?target=did:plc:vc7f4oafdgxsihk4cry2xpze'
{
    "app.bsky.graph.block": { ".subject": 13 },
    "app.bsky.graph.follow": { ".subject": 159 },
    "app.bsky.feed.post": { ".facets[].features[].did": 16 },
    "app.bsky.graph.listitem": { ".subject": 6 },
    "app.bsky.graph.starterpack":
    {
        ".feeds[].creator.did": 1,
        ".feeds[].creator.labels[].src": 1
    }
}

some todos

    • instead of looking this up, should be able to listen for it to be published on the firehose.
      • this should work, but without backfill it won't be accurate. targeted backfill might be an option.
  • [~] other useful endpoints for the api server
  • [~] write this readme
  • [?] fix it sometimes getting stuck
    • seems to unstick in my possibly-different repro (letting laptop fall asleep) after a bit.
  • [~] handle all the unwraps
    • very close to 1GB with data model before adding rkeys to linkers + fixing paths
  • [~] clean up the main readme
  • [~] rocksdb metrics

cache

data fixes

    • [~] pull $type/type from object children of arrays (distinguish replies, quotes, etc)
      • just $type to start
        • and it could be looked up from the linker's doc
        • ^^ for now, look up from source doc to get cid. might revisit this later.