atproto and bluesky

A real-world survey of cross-record references in atproto

2025-03-04 by phil (they/them)

post status: draft, in progress, please don't share yet

Every social interaction in Bluesky (and atproto generally) is represented as a link from a record to some target.

On the HTTP web, links look like this: <a href="[SOME URL]">. A link exists on some web page and usually points to another web page by URL. Your browser understands what a link is and allows you to follow it to that other web page. Search engines discover new pages by crawling the web and following links, and also index them in reverse: tracking how many web pages point to a page is a signal for popularity and credibility.

(todo: i actually think i want to avoid the http link comparison maybe? :/ )

In HTTP you have HTML which defines the meanings of tags like the <a> anchor tag, so identifying links is easy.

In contrast, atproto records are organized into collections which define their own meaning for arbitrary record data via lexicons. This flexibility allows lexicon authors to define what a link is for themselves, which is powerful and leaves room for everyone do define links a little bit differently.

I'm collecting as much information here as I can about how everyone is doing this today. I'm hoping that some conventions will emerge that can become guidance for future lexicon authors, and help lexicon-agnostic tools like constellation more effective and intuitive to use.

StrongRef

Wait, atproto does have a link type! A URI with a content-hash fingerprint. A StrongRef is an object with an at-uri and cid, both required. It's widely used:

collection key notes lexicon
app.bsky.feed.like subject
cid binds likes to post content

If a bluesky post is modified, any likes would become invalidated due to the content changing.

Bluesky's appview currently ignores updates to post records anyway, and they may chose a different mechanism to support editable posts when they implement that.

like.json
app.bsky.feed.post reply.parent direct parent in reply thread post.json
reply.root root of reply thread post.json
embed.record quote-posts or other record embed record.json
embed.record.record quote posts or other embed and also some post media recordWithMedia.json
app.bsky.feed.repost subject repost.json
app.bsky.actor.profile joinedViaStarterPack profile.json
pinnedPost profile.json

note: there are two kinds of quote-posts in bluesky's lexicon, and the link appears at different positions in each one.

🌌 note: constellation indexes the at-uri for all StrongRefs, but currently ignores the cid.

Bare at-uri