It’s been a week and a bit since part one of this story, since then a few things happened. Threads’s user base has more than halved (from it’s 49 million peak to under 12 million), I got a new keyboard but more importantly part two of this project is finished.
Part one (here) was a lot more involved as I had to dive head first into the activitypub protocol as a whole, struggle with Mastodon’s decision to produce silence fails and figure out how to write a blog post for the first time in a year.
This time around my goal is to get the blog post to show up on mastodon on the post history and in the feeds of the followers of my blog. And if things go alright (which they did if you’re reading this) then you should’ve seen this article as a post on your Mastodon feed, if you follow my blog that is. (or me as I’ll probably boost it)
The plan for part 2
There’s a few steps to be done this step:
- Figure out how to get posts show up on mastodon if you search for the blog
- Figure out if/how to update your followers that a post has been made
- Try and improve the link sharing experience for the blog
Creating the outbox
The first thing I wanted to get going was to get the post history to show up on Mastodon. This seemed to be reasonable straightforward. As you might’ve seen in part one the actor object has a link defined called “outbox”. Where the inbox is for receiving messages, the outbox is for sending messages out, makes sense. The activity pub documentation is also quite simple. The outbox contains a list of messages for the called to see. If you call it unauthenticated you should see whatever is publicly available, if you call it with authorization you show the public and private activities, for whomever authorized.
The outbox returns an object known as “OrderedCollection” (on the right) most collections in ActivityPub can be either a normal collection or an ordered collection, but the outbox specifically requires an ordered collection, where the order is publication date.
I already made the code for this in part 1, as I tried this as one of the debug steps to make it possible to follow the blog on Mastodon thinking that it was a required property for the social network. Which would make sense to some degree but turned out to not be the issue.
Though even though following worked after figuring out what the issue was, the posts never showed up. I did notice that there was some sort of caching going on at the Mastodon server when I tried to change the icon of the blog.
I changed the actor document, published the code and it took about a day for it to reflect on Mastodon when searching for the blog. Which was going to make this part a lot more annoying, as you can’t be sure that the change you make is not fixing the issue, or if the cache just needs to invalidate.
{
"@context": "https://www.w3.org/ns/activitystreams",
"summary": "Sally's notes",
"type": "OrderedCollection",
"totalItems": 2,
"orderedItems": [
{
"type": "Note",
"name": "A Simple Note"
},
{
"type": "Note",
"name": "Another Simple Note"
}
]
}
Diving further into Mastodon
Still trying to get the posts to show up on Mastodon I wanted to do a control test, in a controlled environment. And since Mastodon is decentralized it would be possible to create this controlled environment. I got both a hosted environment as well as spun up an environment from the source code.
The hosted instance was simple enough to get going, swipe the credit card enter some data and your mastodon instance is up and running. Getting an instance up and running from code is a lot more involved, though if you follow the steps one by one on the Mastodon site in the end it does boot and work (don’t forget to compile the CSS and JS… things might look really odd otherwise).
This gave me a fully federated controlled environment where I could test and get crazy with accounts without spamming people’s timelines. And on top of that on the source build one I can see all the debug logging.
After some trial and error, I figured out that posts that are made before you follow someone on the other server never show up. Instead, they automatically appear once you post something while someone on the other server is following you.
Meaning that step one of my three step plan automatically gets completed when I create the second step.
Hitting that bell
During this project I’ve gathered quite a few resources on ActivityPub and Mastodon, this time things went smoothly for once, I already had the right Activity objects as it’s the same as in the outbox. Already had the signing code ready and tested from part 1.
Quick abstraction layer later and I can send an post to an inbox of an actor. On top of that Umbraco has a few easy hooks into the CMS, in this case I used the “ContentPublishedNotification” which you can register as an event handler and gets called whenever a user publishes a piece of content in the CMS.
Things are very simple from here, loop over your followers (that I saved from step 1) send them an activity on their inbox nicely singed by your private key and like magic it shows up on their feed and in the post history if you search for the blog on that server.
The only thing (that I found out the hard way on my test Mastodon instance) that I had to add after that is keeping track of which posts I already send the update to the inbox. Since the notification from Umbraco gets send for every time you publish, also if it’s just fixing a typo.
Styling it up
Now that the blog is going to be shared (at least once by the blog itself) the share link should at least look somewhat decent. I never really looked into this, but it’s pretty straightforward add some meta tags (that I may or may not have stolen from an random post I saw) and fill them with the content from the article and all is set.
Next steps?
So now that I’ve implemented ActivityPub, or at least the basics of it what’s next?
My first things would be to clean up the code, write some proper tests. Then I think this would be a great bit of code to make it into an real Umbraco plug in which also is something I’d want to give a shot. But if I am going to publish this I need to add some more features to, like configuration settings, being able to defederate from specific actors and make it possible to put it in “single user mode” instead of an actor per Umbraco User. On top of that I would like to maybe add a commenting system on the site that works through activity pub, comments on the post in the Fediverse then would show up on the site as well.
For now, this is good enough, so no promises on when the next installment arrives.