constellation · lexicon-agnostic

<atproto-backlinks>

Every collection + path that references the target, with record + distinct-DID counts. The 'tell me everything Constellation knows about X' view.

<atproto-backlinks src="at://did/any.lexicon.nsid/rkey"></atproto-backlinks>
NameTypeDefaultDescription
src * string Target AT-URI or DID. Works on any record from any lexicon.
constellation string Override the Constellation endpoint.

External CSS can target these via atproto-backlinks::part(<name>) { ... }.

PartWhat it is
article / header / subject / totalHeader with the queried subject and aggregate counts.
rows / rowTable of collection:path entries.
key / count / distinct / emptyPer-row pieces and empty-state.

Every other library in this space is Bluesky-first. They ship components that render Bluesky posts, Bluesky profiles, Bluesky feeds — all via the Bluesky AppView. They work great if you're building a Bluesky client.

ATProto isn't Bluesky. It's a federated protocol where anyone can define a lexicon and anyone can run a PDS. The moment you step off the Bluesky path, those libraries give you nothing. Your custom records are invisible. Your own lexicon's interactions aren't surfaceable. You'd have to build your own indexer.

Constellation indexes every link in every record from every PDS it sees — not just Bluesky's. If your custom lexicon com.example.recipe.recipe has an ingredients[].source.uri field that points at other recipes, Constellation indexes those backlinks automatically. You didn't tell it to. You didn't register anything.

<atproto-backlinks> surfaces that index for you. Point it at any record — Bluesky post, custom recipe, arbitrary object — and see every collection:path that references it, with record counts and distinct-DID counts, in one call. Instant observability for any lexicon that exists or that you invent tomorrow.

Under the hood, this component calls Constellation's /links/all endpoint. The response is a nested object: { collection: { path: { records, distinct_dids } } }. The component flattens that into a table sorted by record count. No pagination — it's a summary endpoint, and summaries fit in one response.

For drilling into a specific link type, follow up with <atproto-generic-count> or <atproto-likers>-style components using the collection:path you find here.

  • Custom lexicon builder: embed it on your admin page to monitor who's referencing your records without standing up an indexer.
  • Debugging: see at a glance what ATProto "thinks" about a post — is it being liked? Quoted? Included in lists? Referenced by a custom app?
  • Exploring the protocol: point it at a random at-uri and see the implicit graph of relationships ATProto has built around it.

If you just need a number for a specific link type, <atproto-generic-count> is lighter. If you want the list of DIDs behind a count, <atproto-likers>-style components (actor grids) hit the same API shape with a different view. For the raw record that the backlinks reference, pair with <atproto-lexicon-viewer>.