Publishing isn't posting — putting my blog on AT Protocol

I thought if I published a blog entry to the Atmosphere, the whole ecosystem using AT Protocol including Bluesky, it would show up everywhere people are reading. Publishing a site.standard.document record does go out through the firehose to relays. Indexers subscribe to site.standard.document and pick up the record. This is how apps like Standard Reader fill their feeds. However, it won’t show up in the Bluesky timeline since it only indexes app.bsky.* records. Hence, publishing is distribution without notification.

That turned into a decision about how much of the article to put in the record itself. What I sent, what I held back and why.

I like the idea of a decentralized social network, where users have control over their data and can connect with others without relying on centralized platforms and hidden algorithms. And I like the idea of owning my own content, meaning, if I left Bluesky, I wouldn’t have to start over with things I publish. This turns out to depend entirely on what you put in the record, which is the part I hadn’t thought about.

What’s the Point?

Publishing simply makes a record in the AT Protocol version of a database, a Personal Data Server (PDS). You can host your own PDS, the one hosted by Bluesky or use a custom provider.

You have the choice of how much of your blog entry you want in that record. Do you just want a lightweight pointer back to your blog entry hosted on your own site? Or do you want to include the whole thing and let the atmosphere handle the data?

So why have a PDS entry and share a link referencing it instead of just posting a URL link in the post to your own website?

Normally, when you put a URL link in a Bluesky post to your own site, you’ll see the modern-day version of a business card, an Open Graph card that you can brand.

If you have a site.standard.document entry and link to it in your blog post’s HTML <head>, when you use the same URL in your Bluesky post, Bluesky will use the link to the site.standard.document entry and render an enhanced card. It will have more features than an Open Graph card. This card can render custom publication branding (accent colors and icons), author attribution tied to an ATProto handle and estimated reading time. Andy Bell’s walkthrough has previews of the card, including one detail I’d have guessed wrong: the button on it always reads “View Publication.”

What Standard.site Actually Is

Standard.site is a community lexicon, a shared schema created by three publishing apps: Leaflet, pckt.blog and Offprint. It isn’t a Bluesky feature. Bluesky adopted a rendering for it in late May 2026.

The payoff isn’t really about posting on Bluesky. It’s that other readers in the atmosphere (pckt, Leaflet, Docs.surf, Standard Reader, Heron and others) can pick your posts up with no additional work from you, because the structure is shared. Write once, and anything that speaks the lexicon can render it. The Bluesky card is just the most visible result.

Getting there takes two claims. A text file at /.well-known/site.standard.publication holding the AT-URI of your publication proves you control the domain, and a <link rel="site.standard.document"> tag in the head of each post proves you control that page. The quick start walks through both, plus the fields each record requires, so I won’t restate them here.

One detail worth knowing if your site is anything other than static: Bluesky’s crawler doesn’t execute JavaScript. The tags have to be in the served HTML. Mine is a static Astro site, so this was free, but it does rule out injecting them client-side.

The Decision I Almost Made by Accident

The document lexicon has a textContent field. My first working version filled it in, and the dry run printed 4,922 characters, essentially the entire post.

I’d been describing these records to myself as “metadata.” They aren’t. With textContent populated, the whole article goes to your PDS, propagates to relays so other readers can render it without anyone visiting your site.

Formatting doesn’t survive. The lexicon defines textContent as a plain String (type: "string"). It flattens custom HTML elements, Markdown links and inline styles into raw text. There is a rich content field in the lexicon, an open union (content) that can use a Lexicon like at.markpub.markdown. A reader app will render only the content type it supports. Putting structured content in the union is how apps like Leaflet and Standard Reader render full long-form articles without sending readers to my site.

Off-site reads are invisible. If a reader renders the post from the record, no request reaches my site. No pageview, nothing in the logs and nothing on the protocol side reports readership back. It’s a view or impression I don’t see or count.

Bluesky will render the enhanced card even if textContent and the union are empty, but you’ll lose the reading time estimate. So it comes down to whether I want people to view my blog post on my site or in reader apps in the atmosphere.

On my game engine post I left textContent empty.

For this post I’m going to use a hybrid approach. I’ll populate textContent and the union with an opening and a link to the full article on my site. The time estimate will be just for the content I’m including in the textContent, not the entire article on my site — a one-minute read instead of a five-minute read.

Leaflet, pckt.blog and Offprint all put full content in the record, and that community treats content portability as the point. I get that point of view, but I don’t want to lose the ability to see readership, so I’m going to try the hybrid approach.

Share: Bluesky · LinkedIn