1693 words
8 minutes
Welcome to the ATmosphere!

In a previous post, I touched on Bluesky and the AT Protocol (or, ATProto for short). Since that post, I've looked further into the AT Protocol, and have come to be enticed by the concept. It's not necessarily a novel system, but it is a system that's becoming more widely used by the day.

Definition: The AT Protocol#

"The AT Protocol stands for "Authenticated Transfer Protocol," and is frequently shortened to "atproto." The name is in reference to the fact that all user-data is signed by the authoring users, which makes it possible to broadcast the data through many services and prove it's real without having to speak directly to the originating server." - atproto.com[1]

This was a fun project to work on and I'm glad to have everything in a working state! I'll talk about my thought process behind this and some of the inner workings of the blog and the AT Protocol. At the end, I'll also include a few caveats; this isn't a perfect system after all!

View the Blog Source

If you would like to host this yourself, or would like to learn how this all works, the source code is available on my Forgejo instance and Github!

The What#

Before I get into any details, I should explain the title of this blog post. My personal blog, blog.shad.moe, is now an ATProto AppView! What this means specifically is that my posts are no longer markdown files stored in a git repository. Instead, each post is an entry on my Personal Data Server (or PDS)!

It's similar to a post on BlueSky. If you go to my Bluesky profile right now, you will see a few posts. Clicking on one directs you to a URL resembling https://bsky.app/profile/{Handle or DID}/post/{rKey}. The first blank is one of two identifiers for a Bluesky account; either a "handle", a domain name like username, or a unique DID (Decentralized Identifier)[2] for an account. If a handle changes, the DID stays the same unless a new account is made.

The second part is the key. Or quite literally, the Record Key (rKey for short). The rKey looks like a random string of characters at first, but it's often actually something more. The most common rKey is the TID format, but there are other formats that may be used. The important part is that the rKey is a unique key that when passed to a PDS server alongside a "repository" AKA your handle or DID, will return a specific piece of content. In the case of Bluesky, that would look like a post.

Circling back to my blog, a familiar format is used! As the blog is intended for one person, the profile is hardcoded in for ease. With that being the case, the url scheme this blog follows drops the profile part to become https://shad.moe/posts/3lgbnigwdzk2r/! The rKey 3lgbnigwdzk2r is the key to this specific post on my PDS, and thus is all the information needed to render the post.

The Why#

While I already was in control of my blog posts and the platform they were on, moving to the Atmosphere opens up federation of the posts, potentially increasing their view. In addition, I've been looking for a project I could use the AT Protocol on for some time now, cause I simply think it's cool.

The AT Protocol is, as described by the developers, a social protocol. Despite being a relatively new system, many awesome projects all ready exist, testing the limits of the protocol! A short list of my favorites include BlueSky, WhiteWind, GrayHaze, and ATFile.

The How#

The way I made this work is rather interesting, and pulled from a lot of existing community knowledge to cobble together. Perhaps the greatest help and inspiration was WhiteWind. Whitewind is a pre-existing ATProto based blogging service, and their lexicon is what I'm using for my posts. Specifically, each blog post has a type of com.whtwnd.blog.entry. Since these posts are inherently public, they can be viewed from my blog, WhiteWind's website, or a PDS viewer such as PDSls.


Similar projects that helped#

I referred to haileyok/blug and rwietter/atproto-blog both multiple times during work on the transition. haileyok's blug project specifically pushed me to implement Redis caching for posts on the backend. If you attempt to do something similar to this, please use a caching system of some sort. One downside of ATProto is that you generally have to make a web request for each view; a proper cache will immensly cut down traffic to your PDS and speed up loading times on your blog.

The Blog's Design Itself#

If you've visited my blog before, you'll notice it looks the same as it did before! I put a strong effort into retrofitting ATProto into saicaca/fuwari, the Astro-based blog view I used up till now. I really like the design of Fuwari, and didn't want to sacrifice it for this.

Loss of Metadata#

One of the biggest challenges of retro-fitting was the loss of metadata. Fuwari uses Frontmatter to store important data about a post, like it's title, description, category, and tags (among a few other things). However, the WhiteWind Lexicon for com.whtwnd.blog.entry defines different data! The only matching field is the title field. To work around this, I did something I still consider a bit cursed. Markdown allows the use of HTML; I took advantage of this to use an HTML comment to act as a Frontmatter field of sorts.

It's a strange solution, but it allows passing values Fuwari would have previously seen as what I've deemed "Extended Data". When the blog view pulls a post, it will be parsed for a string like the following: <!-- ### ADDITIONAL DATA FIELD ### { 'description': 'Now blogging in the Clouds', 'published': '2024-01-21', 'tags': ['ATProto', 'Meta'], 'category': 'ATProto' } ### solutions.konpeki.post.extendedData ### --->

This string can be broken down into a header, a footer, and a JSON object. This JSON object is extracted when the header and footer are found, and serialized to be passed along as metadata. Notably, no AppView should display this data in the post! Both Fuwari and WhiteWind's AppViews parse markdown, hiding the comment from the reader.

Verceln't#

Something else of note is that Vercel no longer hosts this blog. I spent way too long on trying to get post fetching to work, but Vercel refused to build the project to have dynamic paths or serverless functions no matter what I tried. This gave me the excuse I needed to move from Vercel to my own infrastructure! This blog is currently hosted on an Optiplex that serves as the outer edge of my Homelab network, but will eventually be moved onto the Dell Poweredge R640 servers I mentioned in a previous blog post.


The Caveats#

As I mentioned before, the Atmosphere is not all sunshine and rainbows. There are a few notable issues with this system that are important to understand before undertaking this adventure.

Network Requests#

Every time someone loads the blog, a web request is made. And often, more than one. This is something that is unavoidable; the entire point is that the blog AppView needs to call out to my (or the authors) PDS. This can result in longer load times as the web requests are made, and can be delayed if something is wrong with the network.

However, this is acceptable in many cases. In the case of network issues, it's highly likely that your blog would be inaccessible in the first place since users can't connect to it. In the case of sending many requests that can potentially take some time to resolve, this is relieved through the use of caching. Specifically, a KV database, Redis, is used in the backend to cache posts locally.

Different AppViews#

The first caveat is the potential for a post to differ slightly depending on where it's viewed. As mentioned before, each post can be viewed directly on my blog or on Whitewind. It may also be viewed by any other AppView that chooses to implement the Whitewind lexicon. While these posts are written in Markdown, which should be universal, there can be differences in how Markdown is rendered. A great example is Admonition cards: on my blog, they create a nice block to grab a readers attention! On other AppViews, these aren't rendered and instead appear as text.

Image: An Admonition card as it would appear on my blog

Image: An Admonition card as it would appear on my blog#

Image: An Admonition card as it would appear on WhiteWind

Image: An Admonition card as it would appear on WhiteWind#

Posts are Inherently Public#

Finally, it's important to note that posts are always public (unless you've configured your PDS to require authentication to view certain things. YMMV.), so if you're drafting a post that you don't want to be viewable, you should hold off on posting it to your PDS.

This is something I am fine with. My flow is to use the WhiteWind editor (eventually an editor on my own blog) in "Anyone with the link" privacy mode. This hides the post on Whitewind unless the reader has the exact rKey, and my blog is configured to not show these posts but to still allow direct URL access without caching. This enables quick reviews everytime I save the post, and allows me to share the unlisted link with friends for review. Once a post is ready, simply changing the privacy mode to public "publishes" the post, making it appear on the blog's front page and enabling my RSS.xml to pick up on the post and distribute it.

(Potential) Future Plans:#

  • Finish the editor at blog.shad.moe/editor
  • Add comments and reactions sections
  • Change URL Schema to allow multiple users? b.s.moe/author/{acc}/post/{rKey}?
    • Currently possible but probably won't be implemented for my blog
      • Changing URL schema could/would break SEO again
      • Maybe have Single / Multi-User toggle in code?

Conclusion#

I don't have much of a conclusion for this post. This is a project I started near the end of Commit Overflow (Post soon on this event!). I began on January 8th, 2024 and finished January 21st, 2025, which is less time than I thought until I typed it out. This project was honestly quite motivating, and I'm glad that I went through with it instead of scrapping it like I almost did on two seperate occasions. All in all, I'm excited for this new system! If anyone wants to try this for themselves, you can find the repository on my Forgejo instance and Github as mentioned above. If you have any questions, feel free to shoot me a message on BlueSky or through email!

References#

[1] Quick start guide to building applications on AT Protocol - atproto.com
[2] ATProto DIDs - atproto.com

Welcome to the ATmosphere!
https://shad.moe/posts/3lgbnigwdzk2r
Author
TheShadowEevee
Published at
2025-02-02
License
CC BY 4.0