Becoming a better atproto citizen
12 July 26
Back in February I
gave every post on this blog a persistent AT-URI
via the standard.site lexicons. In June I
fixed the verification file that had been 404ing in production the entire time.
Since then the records have been syncing on every push, and the spec has grown
up around them. Standard.site started as an agreement between three publishing
platforms; now even the AT Protocol team’s own blog publishes these records. And
as of May,
Bluesky is rolling out enhanced link cards
built from them. The publication’s avatar, reading time and theme colours are
pulled from records in your repo rather than scraped from your og: meta tags.
This week I brought the blog’s records up to spec. The publication record now
carries an icon (the favicon, rasterised at 512px), a basicTheme with the
site’s colours, and the showInDiscover preference. Those are the fields
readers like Leaflet’s draw on for
rendering and discovery. Every document record now includes a coverImage blob
(the post’s hero image) plus an updatedAt stamp whenever I edit a published
post. When a new post gets announced on Bluesky, the announcement’s link embed
now holds associatedRefs, strongRefs to the document and publication records.
That’s the signal for Bluesky to build an enhanced card rather than recrawl the
page.1
There are two smaller additions. Post pages now emit a
<link rel="site.standard.publication"> tag alongside the existing document
one, because Bluesky verifies articles against both records before rendering a
card. There’s also a new hand-curated
atproto-recommendations.json,
which the publish pipeline syncs to site.standard.graph.recommend records.
It’s an atproto-native way of vouching for individual posts, mine or anyone
else’s.2
With all that in place I re-published the back catalogue, so all 162 documents
now carry cover images. If you want the details, the whole pipeline is
scripts/atproto-publish.ts
and
scripts/lib/atproto.ts:
plain putRecord calls via @atproto/api, nothing clever. The records live in
a repo I control; the sync is a few hundred lines of TypeScript. Publish once,
and the blog shows up properly in Leaflet, pckt and Bluesky with no per-platform
integration required.
Footnotes#
-
This required a small ordering dance in the publish pipeline. The document record has to exist before the Bluesky post so the post can reference it, but the document also wants a
bskyPostRefpointing back at the post. So: write the document, create the post withassociatedRefs, then re-put the document with the back-link. Two writes to close one reference cycle. ↩ -
It’s currently empty, which makes it the protocol equivalent of a blogroll page that says “coming soon”. Recommendations to follow. ↩
Cite this post
@online{swift2026becomingABetterAtprotoCitizen,
author = {Ben Swift},
title = {Becoming a better atproto citizen},
url = {https://benswift.me/blog/2026/07/12/becoming-a-better-atproto-citizen/},
year = {2026},
month = {07},
note = {AT-URI: at://did:plc:tevykrhi4kibtsipzci76d76/site.standard.document/2026-07-12-becoming-a-better-atproto-citizen},
}