Pushing Posts to the Atmosphere
A few weeks ago I wired up comments so replies on Bluesky would show up under each post here. That worked, but it only covered conversations.
What I wanted next was for the blog itself to be discoverable through ATProto-native readers, without moving off Astro. The shape of that idea is POSSE, short for "publish on your own site, syndicate elsewhere." The blog stays canonical, and other places that surface my posts read from it.
tl;dr: I write here. One command () creates a Bluesky thread, mirrors the post to my PDS as a standard.site document, and (for book reviews) writes a Bookhive record. The post stays the canonical version. Everything else points back.
Domain as identity
The foundation is making the blog's domain my ATProto handle. I'd already pointed at my DID with a DNS TXT record. To make that resolvable from the blog itself, I dropped a single file at :
Now on Bluesky is verifiable from the site, and ATProto clients that resolve handles via well-known will pick it up.
standard.site documents
standard.site is a community-maintained set of ATProto lexicons for long-form writing. Publish records that follow them and ATProto-native readers like Pckt and Leaflet can index your posts even though they live on your own site.
gives you a class that handles the auth and the lexicon shape. The setup is two scripts.
The first runs once to create a record on my PDS:
Save the returned in as . The second script walks , skips drafts, and writes each post as a record:
A small Astro endpoint at serves the publication AT URI as so readers can verify ownership.
The first sync wrote 32 documents to my PDS in a single pass. Re-running the script is safe because the publisher derives a deterministic rkey from each slug, so existing records get updated instead of duplicated.
Bookhive book reviews
Bookhive is an ATProto app for tracking books. You write reviews, rate things, log what you're reading, and it all ends up in your PDS as records. I've written a few posts about books I've read (tagged , titled ), and I wanted those to show up in Bookhive without doubling my writing workflow. The book reviews were also a good excuse to see how syndication feels when the downstream is another ATProto app instead of a feed.
The script reads my blog, picks anything tagged , parses out of the post title, looks up the book against Bookhive's XRPC to get a stable , then writes a record on my PDS pointing at the canonical review URL.
All seven of my book posts showed up on my Bookhive profile after the first run.
There's probably a better way to do this than parsing out of the post title. A dedicated block in the frontmatter would be cleaner, since it could carry the ISBN and author directly without depending on a naming convention. But the parsing approach is good enough for v1.
One command
The three scripts (Bluesky thread, standard.site document, Bookhive record) all read the same and from , so I wrapped them into one npm script:
The full publish workflow:
Two commits and one syndicate call per post. The deploy happens on the first push, the comments thread shows up after the second.
There's probably a better way to wire this up (a Netlify build hook, a git post-push, something), but the local two-step approach is good enough for now. The step writes back to the post's frontmatter, and I'd prefer not to have a remote machine making commits to my repo.
What I like about this
Nothing downstream is load-bearing. If Pckt redesigns or Bookhive disappears, the records I've already written are still in my PDS and the post itself reads exactly the same here. Syndication is additive.
The other thing I keep noticing is that my handle is the same in every one of these places. Same on Bluesky, Bookhive, and Pckt, all pointing back here. The web stopped feeling like that for a while; it's nice to have it back in a small corner.
Resources POSSE on IndieWeb standard.site lexicons Bookhive Pckt Leaflet Adding Bluesky comments to an Astro blog
Discussion in the ATmosphere