This action will delete this post on this instance and on all federated instances, and it cannot be undone. Are you certain you want to delete this post?
This action will delete this post on this instance and on all federated instances, and it cannot be undone. Are you certain you want to delete this post?
This action will block this actor and hide all of their past and future posts. Are you certain you want to block this actor?
This action will block this object. Are you certain you want to block this object?
Are you sure you want to delete the OAuth client [Client Name]? This action cannot be undone and will revoke all access tokens for this client.
Are you sure you want to revoke the OAuth token [Token ID]? This action cannot be undone and will immediately revoke access for this token.
#ActivityPub 85 hashtags


Servers
- Betula v1.8.1
- Stegodon v1.8.6
- Ktistec v3.8.0
- Mitra v5.7.0
- Ibis v0.3.3
- Gathio v1.6.3
- NodeBB v4.14.0
- Wanderer v0.20.0
- Wafrn v2026.07.01
- Gush! v0.0.40
- PieFed v1.7.5
- Harmony v1.4.0
Clients
- Mastodon for iOS v2026.05
- tooi v0.27.0
- Voyager v2.47.4
- Aria v1.5.7
- Holos v1.14.0
- Rocinante v1.1.0
- chan-fe: Imageboard-style frontend for Mitra and Mastodon-compatible fediverse APIs
Tools and Plugins
- tag-federation.online: How Widely Do Hashtags Federate?
- Fedigraph: A dashboard for exploring the fediverse
For developers
Protocol
- FEP-4772: Representing bookmarks
- FEP-521b: Switch the default in FEP-521a to be 76171% cooler
-----
#WeekInFediverse #Fediverse #ActivityPub
Previous edition: https://mitra.social/objects/019f29a4-78da-7a53-805d-72c8e43916c2

There are two significant new additions in release v3.8.0 of ktistec.
First, the actor cards on the followed/following pages show relevant actor status. On the followed page, it tells you how long it has been since that actor published an activity (create, announce, like, etc.) that was sent to your server. It's a proxy for how active they are (or are not). On the following page, it tells you how long it has been since you have been able to send to that server. It's a proxy for whether that server is reachable or that actor is still alive.
Second, the backend for user-defined algorithmic feeds is in place, along with a keyword/hashtag/mention feeds implementation. You can't set up a feed via the user-interface, but the feeds work if you set one up directly in the database—which is how I've been previewing them. I plan to release the frontend next week.
Here's the full changelog:
Added
Announce.rel="alternate" link when searching.Fixed
has_many collections when constructing child records.MIME::Multipart::Error in local file-upload handling.Bad Request.
i'm sure inline json-ld contexts with server extensions seem like the wrong thing, but they're preferable to identical copies of the same context hosted externally and served by a dozen or more instances of a server or family of servers.
i could be persuaded to change my mind if a server allowed meaningful customization. but if a server is publishing a canonical vocabulary of extensions for that server, it should be hosted in a single, well-know location.


Servers
- TinyAP v0.1.10
- GoToSocial v0.22.0
- Mobilizon v5.2.4
- Bonfire v1.0.5
- PeerTube v8.2.2
- Ktistec v3.7.0
- PieFed v1.7.0
- Mastodon v4.6.3
- Hollo v0.9.6
- ActivityPub for WordPress v9.0.2
- NeoDB v0.16.3
- Wanderer v0.19.3
- Trunk & Tidbits, May 2026 (Mastodon)
- Lemmy Development Update June 2026 and 1.0.0-beta.1
Clients
- Fedilab v3.42.1
- Pachli v3.7.1
- Aria v1.5.5
- Rocinante v1.0.9
- Holos v1.12.0
- Mitra Mini v0.4.2
Tools and Plugins
- FediFetcher v7.1.21
- owncast-emojiwall v2.1.0
- Polls For ActivityPub (WordPress plugin)
For developers
- Why implementing ActivityPub is hard, and why it doesn't have to be (Fedify)
Protocol
- FEP-8c13: Context-Authority Routing with Object Integrity Proofs for Restricted Threads
- FEP-f228: Backfilling conversations (Final comments)
- FEP-7628: Move actor (Final comments)
-----
#WeekInFediverse #Fediverse #ActivityPub
Previous edition: https://mitra.social/objects/019f058a-b456-7c32-a9ee-f6ef93e8ee55

I started to work on algorithmic feeds but was side-tracked by interoperability work. No complaints. It turned out to be a productive detour.
Here's the full changelog for release v3.7.0 of Ktistec:
Added
Update activities for actor profile changes.Fixed
quote_policy mapping to public/nobody values.mediaType is missing.statuses_count using an approximate count.Changed
The first version of algorithmic feeds won't be very algorithmic—it will let you create a feed that filters by keywords, hashtags, and mentions. That covers a lot of ground for me personally, and lays the groundwork for future enhancements.

It is said that there are only two hard things in computer science: cache invalidation and naming things. The story goes: you have something that is expensive to compute, so you compute it once and then you cache it and use the cached value in the future. But the inputs to that computation change, and so the cached value grows stale. You have to decide when and how to recompute that value.
In Ktistec, presenting accurate tag counts is expensive because not every tagged post counts. Posts are deleted, actors are blocked. My own drafts don't count, but when they're published they do. A post tagged with the same hashtag more than once, must count as one. And tag cardinality is not uniform: #3dprinting has hundreds of thousands of posts, others have one or two. Even with indexes, there is no single query that counts all cases in an acceptable amount of time.
So I reached for a cache, counted once and then cached the count. Because I didn't want to maintain adjustments from every place in the code that changed something that touched the count, I settled for eventual consistency and recomputed counts after every server restart.
As it turns out, that's not good enough. On a server with reasonable traffic, an event that affects some tag's count happens every few hours. Days or weeks later there is significant drift. Worse, the implementation didn't recompute on first read, it recomputed on first write (a new tagged object arrives).
This release fixes all that. Counts are still eventually consistent, but all counts are recomputed in a regular background task, so they really are eventually consistent, and care was taken in constructing the query to minimize database (read) locking to ~100-200msec.
Is it better? Yes! Is it perfect? Probably not. Cache invalidation is hard.
Here's the full changelog for this release:
Added
Fixed
Changed
Removed
idx_relationships_type database index.In the next release, I'm going to fix a few bugs in the Mastodon-compatible API. These require an internal redesign, so I've held off until a few other things were out of the way. And I'm turning my attention to reading and better tools for surfacing and finding interesting content.


Servers
- Gush! v0.0.39
- Hollo v0.9.5
- FitPub v1.1.0
- Mbin v1.10.0
- PeerTube v8.2.1
- Mastodon v4.6.0
- Wafrn v2026.06.02
- Ktistec v3.5.0
- ActivityPub for WordPress v9.0.1
- NeoDB v0.16.2
- NodeBB v4.13.2
Clients
- Nicolium v1.0.0
- Mastodon Bird UI v4.0.0
- Loops for Android v1.0.2.4
- Voyager v2.47.1
- Aria v1.5.4
- Loops is now on Google Play
Tools and Plugins
- PeerTube livechat plugin v14.0.3
- Canvas: A collaborative pixel canvas built for the Fediverse
Articles
-----
#WeekInFediverse #Fediverse #ActivityPub
Previous edition: https://mitra.social/objects/019ebd9e-110f-7960-b3cc-e837a3b2f810

I really enjoy optimization. Release v3.5.0 of Ktistec doesn't drop significant new features, but it does deliver a ~15% smaller executable and significantly faster queries on anonymous endpoints. The two are intertwined.
The size reduction comes from replacing a poorly designed, custom rules engine with a materialized view layer that uses SQL to define membership in a collection. The rules engine worked well enough but required a lot of supporting code to present rules as a DSL (Domain Specific Language) over the domain objects in ktistec. The driving realization was that SQL is a DSL and membership in a collection is just a query and domain objects are just rows. Voilà!
Query performance improvements came from using this new view layer to materialize two very popular but expensive-to-query views: the instance's public timeline and public hashtag pages. Because both are public pages they receive more traffic than internal pages.
The problem with the original queries was that performance was not uniform. Querying for posts with popular tags was okay. Querying for posts with sparse tags was very slow. I could have added more indexes, but that's its own cost. After the change, endpoints all respond in a consistent ~10msec timeframe and the CPU barely registers when a crawler hits. (I don't want to make things easier for bots, but I don't want to pay a tax for their activity either—ask me about my new nginx configuration.)
Here is the full changelog:
Added
max-id and min-id pagination links on web pages.Fixed
Changed
Removed
school dependency; replaced by activity processors and materialized views.openssl_ext dependency; vendored in.There are still a few slow queries. In the next release I'm going to see if I can get everything under 10msec, and maybe release a new feature, too. 🚀

This release fixes a small number of bugs found in recent releases.
The full changelog:
Fixed
header and header_static images are always present.replies collection for local objects.Changed
Removed
This release fixes a hard-to-exploit but potentially server-crashing bug. If you're running v3.3.9 or v3.4.0, you should upgrade.

The biggest change in release v3.4.0 of Ktistec is cursor-based pagination for all web-navigable collections (timeline, notifications, etc.). Offset-based pagination will be removed completely in the next release.
Offset-based (e.g. page/size) pagination works well on collections that don't change. But, what does "the second page" contain in a dynamic timeline? Support for cursor-based pagination is required by the Mastodon-compatible API, but has been a desirable feature for quite a while.
While updating queries to paginate by cursor, I also made performance improvements to the queries themselves, as mentioned elsewhere. Scrapers and bots have already adapted—sort of. I now see odd hybrid requests in the log like /tags/xyz?page=7&min_id=123. Overall CPU usage under normal load is now sitting at 0-1%.
Here is the full changelog for the release:
Added
/api/v1/timelines/tag/:hashtag endpoint.Fixed
published rather than id.Changed
Ktistec::Network.get.Removed
Enjoy!