So, ActivityPub. You probably love its existence, considering that you probably found this article (or me or the creator of Wave) over one of the services implementing it, be it Mastodon, Misskey (or one of its many soft and hard forks), Plemora/Akoma or other. And they all do a great job of providing a nice UI for all the things you can do with ActivityPub (except for Akoma, I will stand with my take of its UI being badly made). What you don't see is the protocol layer though. And this is where it gets ugly.
ActivityPub has a few parts. Endpoints and what you transmit to and from those endpoints. The endpoints are fine. One inbox and one outbox endpoint per user and the same for the entire server too. Easy to solve with path parameters. The public page (the one you see when visiting the user) could be on that path too or a different one. Don't matter. Easy to do.
Webfinger? Also easy to do. Not funky yet. All nice and consistent.
The problem is what you have to transmit. Because ActivityPub is based on Json-LD. A dynamic extension of Json. Json alone would be fine. But the -LD part makes it really hard to manage in strongly typed languages. You either have to define every single element a message could have or go with whatever generic thing your language of choice has, in Go's case any. Or you could do what Mastodon and all those tutorials and guides on activitypub.rocks do and just treat everything as plain old json, no fancy extensions. And even with that, you still have fields that can be either an url to an object or the object directly. Welcome back any. Still a lot better to have most fields defined than to just throw everything into a map[string]any.
And speaking of Mastodon and activitypub.rocks, there are very few resources that show how to work with ActivityPub in a good way. For Mastodon, you have to know Ruby and download the entire source so that an IDE can decrypt all the includes happening for you. For Misskey, you have to know Japanese and also first figure out the project structure (hint: I still haven't found where they define their ActivityPub data). Akoma? Haven't looked at that yet. GoToSocial? Implemented in Go, but in a horrible way. No clear starting points that you could follow and also uses a fork of the ActivityPub vocabulary module, which went the route of everything that could be included will be included, even fields that I haven't seen on any traffic. And the guides and tutorials were all either the official specification of ActivityPub but reworded or the same webfinger to one minimal account to one minimal message. Not useful either.
So, the only option left was to reverse-engineer it in a live environment. Aka booting up a test server yourself and just monitoring all traffic and poke at it with curl or another rest explorer. Slow and annoying. Until I found https://activitypub.academy. A Mastodon server where you can get an anonymous account for a day, use it like you would use normal Mastodon, except that you now have a tab logging (almost) all ActivityPub actions, including the source json. Incredibly useful for figuring things out.
And that's about where I am right now with Linstrom. I got the ActivityPub types and events figured out (I hope) and now have to get working on the endpoints and linking it all together. And since I wanted to make Linstrom a good example of how you could work with ActivityPub, I tried my best to explain what different values are, what they are intended for as well as a decent project structure, seperating web endpoints into different categories (like ActivityPub, WebUI, Mastodon API, etc), but all under the umbrella of endpoints.
Additionally, I also plan to maybe integrate a more consistent gRPC based API as parallel to ActivityPub, focused on having one source of truth for the endpoints and data formats (a protobuf file) and maybe being extensible too via more gRPC and protobuf. But that'll only have a chance of happening once I have the main server running.
