BotKit 0.1.1 is out!
This security update fixes a message visibility bug where direct/followers-only replies to bots were unintentionally forwarded to bot followers. Upgrade recommended. Download at JSR:
deno add jsr:@fedify/botkit@^0.1.1
BotKit 0.1.1 is out!
This security update fixes a message visibility bug where direct/followers-only replies to bots were unintentionally forwarded to bot followers. Upgrade recommended. Download at JSR:
deno add jsr:@fedify/botkit@^0.1.1
A milestone worth celebrating—#Fedify just hit 100+ releases! From day one, we've been committed to building a robust #ActivityPub framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the #fediverse together! #fedidev
Most #ActivityPub implementations include Mention objects in the tag attribute when someone mentions another actor within the content of a Note or Article. Should actor objects like Person or Group also include Mention objects in their tag attribute when mentioning other actors within their bio (summary)? Are there any implementations that already work this way? (I've checked Mastodon and it seems they don't include these mentions.) What are your thoughts on this?
I just discovered why some of my followers from larger #Mastodon instances (like mastodon.social) would mysteriously unfollow me after a while!
Turns out Mastodon implements the FEP-8fcf specification (Followers collection synchronization across servers), but it expected all followers to be in a single page collection. When followers were split across multiple pages, it would only see the first page and incorrectly remove all followers from subsequent pages!
This explains so much about the strange behavior I've been seeing with #Hollo and other #Fedify-based servers over the past few months. Some people would follow me from large instances, then mysteriously unfollow later without any action on their part.
Thankfully this fix has been marked for backporting, so it should appear in an upcoming patch release rather than waiting for the next major version. Great news for all of us building on #ActivityPub!
This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊
We're considering adding custom background task support to #Fedify 1.5.0.
Want to use Fedify's worker system for your own background tasks? We're exploring ways to let you register and process custom tasks alongside #ActivityPub jobs.
Check out the proposal: https://github.com/fedify-dev/fedify/issues/206.
Key considerations:
Should this be part of Fedify's scope?
Quick API extension vs complete worker architecture redesign
Integration with existing task queue systems
We'd love to hear your thoughts! Do you need this feature? How would you use it? Share your feedback in the issue thread.
Excited to share that Fedify CLI is now available on Scoop for #Windows users! You can easily install it with scoop install fedify. One more way to get started with #ActivityPub development!
A collection of silly Mastodon apps (the best kind). It includes a Fax-To-Mastodon app.
Build your own #fediverse server with #Fedify!
Fedify is a #TypeScript framework that simplifies #ActivityPub implementation. Want to build a federated server without the complexity? Fedify has got you covered!
✨ Key features
Complete protocol support including WebFinger, HTTP Signatures, and NodeInfo
Enhanced interoperability with Object Integrity Proofs and Linked Data Signatures
Type-safe Activity Vocabulary API to prevent development mistakes
Reliable delivery with automatic retries and message queues
Full observability through OpenTelemetry integration
Multiple backend support: Redis, PostgreSQL, AMQP
Seamless integration with popular web frameworks: Express, Hono, Fresh, SvelteKit
Comprehensive logging and tracing
Debug ActivityPub in real-time with ephemeral inbox server
Inspect ActivityPub objects and actors with lookup tool
Tunnel your local server for development
🚀 Runtime support
📚 Easy to learn
Extensive docs
Step-by-step tutorials
Community support via Matrix & Discord
Available under the #MIT license—free and open source!
New API filter action in Mastodon that fedi app developers will want to know about.
Filters can now include a new filter_action of “blur”. Media attachments in posts matching the criteria should then be blurred by the client app based on the FilterResult object attached.
We're excited to announce the release of Fedify 1.5.0! This version brings several significant improvements to performance, configurability, and developer experience. Let's dive into what's new:
Two-Stage Fan-out Architecture for Efficient Activity Delivery
#Fedify now implements a smart fan-out mechanism for delivering activities to large audiences. This change is particularly valuable for accounts with many followers. When sending activities to many recipients, Fedify now creates a single consolidated message containing the activity payload and recipient list, which a background worker then processes to re-enqueue individual delivery tasks.
This architectural improvement delivers several benefits: Context.sendActivity() returns almost instantly even with thousands of recipients, memory consumption is dramatically reduced by avoiding payload duplication, UI responsiveness improves since web requests complete quickly, and the system maintains reliability with independent retry logic for each delivery.
For specific requirements, we've added a new fanout option with three settings:
// Configuring fan-out behaviorawait ctx.sendActivity( { identifier: "alice" }, recipients, activity, { fanout: "auto" } // Default: automatic based on recipient count // Other options: "skip" (never use fan-out) or "force" (always use fan-out));
Canonical Origin Support for Multi-Domain Setups
You can now explicitly configure a canonical origin for your server, which is especially useful for multi-domain setups. This feature allows you to set different domains for WebFinger handles and #ActivityPub URIs, configured through the new origin option in createFederation(). This enhancement prevents unexpected URL construction when requests bypass proxies and improves security by ensuring consistent domain usage.
const federation = createFederation({ // Use example.com for handles but ap.example.com for ActivityPub URIs origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, // Other options...});
Optional Followers Collection Synchronization
Followers collection synchronization (FEP-8fcf) is now opt-in rather than automatic. This feature must now be explicitly enabled through the syncCollection option, giving developers more control over when to include followers collection digests. This change improves network efficiency by reducing unnecessary synchronization traffic.
await ctx.sendActivity( { identifier: sender }, "followers", activity, { preferSharedInbox: true, syncCollection: true, // Explicitly enable collection synchronization });
Enhanced Key Format Compatibility
Key format support has been expanded for better interoperability. Fedify now accepts PEM-PKCS#1 format in addition to PEM-SPKI for RSA public keys. We've added importPkcs1() and importPem() functions for additional flexibility, which improves compatibility with a wider range of ActivityPub implementations.
Improved Key Selection Logic
The key selection process is now more intelligent. The fetchKey() function can now select the public key of an actor if keyId has no fragment and the actor has only one public key. This enhancement simplifies key handling in common scenarios and provides better compatibility with implementations that don't specify fragment identifiers.
New Authorization Options
Authorization handling has been enhanced with new options for the RequestContext.getSignedKey() and getSignedKeyOwner() methods. This provides more flexible control over authentication and authorization flows. We've deprecated older parameter-based approaches in favor of the more flexible method-based approach.
Efficient Bulk Message Queueing
Message queue performance is improved with bulk operations. We've added an optional enqueueMany() method to the MessageQueue interface, enabling efficient queueing of multiple messages in a single operation. This reduces overhead when processing batches of activities. All our message queue implementations have been updated to support this new operation:
@fedify/redis 0.4.0
@fedify/postgres 0.3.0
@fedify/amqp 0.2.0
If you're using any of these packages, make sure to update them alongside Fedify to take advantage of the more efficient bulk message queueing.
CLI Improvements
The Fedify command-line tools have been enhanced with an improved web interface for the fedify inbox command. We've added the Fedify logo with the cute dinosaur at the top of the page and made it easier to copy the fediverse handle of the ephemeral actor. We've also fixed issues with the web interface when installed via deno install from JSR.
Additional Improvements and Bug Fixes
Updated dependencies, including @js-temporal/polyfill to 0.5.0 for Node.js and Bun
Fixed bundler errors with uri-template-router on Rollup
Improved error handling and logging for document loader when KV store operations fail
Added more log messages using the LogTape library
Internalized the multibase package for better maintenance and compatibility
For the complete list of changes, please refer to the changelog.
To update to Fedify 1.5.0, run:
# For Denodeno add jsr:@fedify/fedify@1.5.0# For npmnpm add @fedify/fedify@1.5.0# For Bunbun add @fedify/fedify@1.5.0
Thank you to all contributors who helped make this release possible!
I'm exploring a new idea called FediOTP (codename): an authentication system that uses #ActivityPub DMs to deliver one-time passwords, allowing any #fediverse account to authenticate with web services. Unlike current solutions that rely on specific APIs (#Mastodon, #Misskey), this would work with any ActivityPub-compatible server, increasing interoperability across the fediverse. Would love to hear your thoughts on potential challenges or use cases for this approach.
📣 Exciting news! Fedify CLI is now available via Homebrew!
If you're using #Homebrew on macOS or #Linuxbrew on Linux, you can now install our CLI toolchain with a simple command:
brew install fedify
This makes it even easier to get started with building your federated server app. Try it out and let us know what you think!
After reviewing FEP-5624: Per-object reply control policies and GoToSocial's interaction policy spec, I find myself leaning toward the latter for long-term considerations, though both have merit.
FEP-5624 is admirably focused and simpler to implement, which I appreciate. However, #GoToSocial's approach seems to offer some architectural advantages:
The three-tier permission model (allow/require approval/deny) feels more flexible than binary allow/deny
Separating approval objects from interactions appears more secure against forgery
The explicit handling of edge cases (mentioned users, post authors) provides clearer semantics
The extensible framework allows for handling diverse interaction types, not just replies
I wonder if creating an #FEP that extracts GoToSocial's interaction policy design into a standalone standard might be worthwhile. It could potentially serve as a more comprehensive foundation for access control in #ActivityPub.
This is merely my initial impression though. I'd be curious to hear other developers' perspectives on these approaches.
#FEP5624 #fedidev #fediverse #replycontrol #interactionpolicy
I've been wrestling with implementing #multilingual content support in Hackers' Pub, our #ActivityPub-powered platform for software engineers.
While ActivityPub theoretically supports multilingual content through the contentMap property, the reality is that most server implementations (Mastodon, Misskey, etc.) don't properly handle this content as of April 2025. This creates a significant challenge for us.
We want our users to share their knowledge in multiple languages, but we need to ensure compatibility with existing ActivityPub servers. I'm considering several approaches:
Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
Using the primary language in content while storing translations in contentMap
Adding "View in other languages" links at the bottom of each post
Implementing inline language dividers that degrade gracefully on non-supporting servers, for example:
<div lang="en"> <h3>English</h3> <p>This is the English content…</p></div><hr><div lang="ko"> <h3>한국어</h3> <p>한국어 내용입니다…</p></div>
I'm leaning toward a hybrid approach—showing content in the user's preferred language when possible while providing easy access to other language versions.
Has anyone tackled this problem effectively? I'd love to hear about your experiences or ideas for making multilingual content work well in the fediverse, especially when dealing with server implementations that don't fully support ActivityPub's multilingual features.
I've been considering what to add in the next version of BotKit (v0.2.0) and wanted to share my current plans. After reviewing feedback and examining the #ActivityPub ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:
Custom emoji support. This would allow bots to use server-defined custom emojis in their messages, making communication more expressive and allowing better integration with instance culture.
Emoji reactions. I plan to implement both sending and receiving emoji reactions to messages. This provides a lightweight interaction model that many users prefer for simple acknowledgments or responses. This would manifest as new event handlers (like Bot.onReaction) and methods (like Message.react()).
Quote posts. The ability to reference other posts with commentary is an important discourse feature in the fediverse. Supporting both sending quotes and detecting when bot posts have been quoted would enable more sophisticated conversational patterns.
These additions should make #BotKit more capable while maintaining its simple, developer-friendly API. I expect implementation to involve extending the Message class and adding new Text processing capabilities, all while keeping backward compatibility with existing bots. Having built both Hollo and Hackers' Pub, I already have deep familiarity with how various ActivityPub implementations handle these features across the fediverse. I welcome any community feedback on priorities or implementation details before I begin coding.
As someone who has developed several #ActivityPub software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the #fediverse is #custom_emoji.
The challenges are numerous:
First, there's no standardization. ActivityPub specifications don't define how custom emoji should work, leading to inconsistent implementations across different servers like Mastodon and Misskey.
Rendering is particularly problematic. Emojis must display properly across different contexts (in text, as reactions, in emoji pickers) while maintaining quality at various sizes. Animated emojis add another layer of complexity.
Perhaps most concerning is the poor #accessibility. Most implementations simply use the emoji code (like :party_blob:) as the alt text, which provides no meaningful information to screen reader users (in particular, non-English speakers) about what the emoji actually depicts or means.
What really dampens my motivation to implement this feature is knowing I'm investing significant effort into something that ultimately creates accessibility barriers. It's disheartening to work hard on a feature that excludes part of the community.
In case you weren't aware, #Fedify has both #Discord and #Matrix communities where you can get help, discuss features, or just chat about #ActivityPub and federated social networks.
Matrix space: #fedify:matrix.org
Discord server: https://discord.gg/bhtwpzURwd
Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.
Great news for the wafrn app !!
As a culmination of the big journey of the past weeks, the Wafrn App is now listed in the official @unifiedpush documentation as one of the apps that support UnifiedPush
Check it at https://unifiedpush.org/users/apps/
We're excited to introduce emoji reactions in the upcoming #BotKit 0.2.0 release!
With the new Message.react() method, your bot can now react to messages using standard Unicode #emojis:
await message.react(emoji`👍`);
#Custom_emoji support is also included, allowing your bot to react with server-specific emojis:
const emojis = bot.addCustomEmojis({ // Use a remote image URL: yesBlob: { url: "https://cdn3.emoji.gg/emojis/68238-yesblob.png", mediaType: "image/png", }, // Use a local image file: noBlob: { file: `${import.meta.dirname}/emojis/no_blob.png`, mediaType: "image/webp", },});await message.react(emojis.yesBlob);
Reactions can be removed using the AuthorizedReaction.unreact() method:
const reaction = await message.react(emoji`❤️`);await reaction.unreact();
Want to try these features now? You can install the development version from JSR today:
deno add jsr:@fedify/botkit@0.2.0-dev.84+c997c6a6
We're looking forward to seeing how your bots express themselves with this new feature!
Looking for #ActivityPub implementations with #RFC9421 support! 🔍
As mentioned in the Fedify announcement below, I've implemented RFC 9421 (HTTP Message Signatures) and need to verify its interoperability with other ActivityPub implementations.
The challenge is that most major ActivityPub projects don't seem to have full RFC 9421 implementations in production yet. If you're working on an ActivityPub project that:
has implemented RFC 9421 (even in a development branch)
is currently implementing it
has plans to implement it soon
Please reach out! I'd love to collaborate on interoperability testing to ensure our implementations work properly with each other before merging this into #Fedify's main branch.
Any leads or connections would be greatly appreciated! 🙏
PieFed adds PassKeys! As in, log in only with your passkey. Not just as a 2FA addition to your username/password.
I've been thinking about client-server interactions in the #fediverse. #ActivityPub #C2S isn't widely used, and most clients rely on Mastodon-compatible APIs instead.
What if we created a new standardized API based on GraphQL + Relay for client-server communication, while keeping ActivityPub for server-to-server federation?
The Mastodon-compatible API lacks formal schema definitions for code generation and type checking, which hurts developer productivity. And ActivityPub C2S is honestly too cumbersome to use directly from client apps.
#GraphQL would give us type safety, efficient data fetching (only get what you need), and the ability to evolve the API without breaking clients. #Relay's features for pagination, caching, and optimistic updates seem perfect for social apps.
Would this be valuable to our community? What challenges do you see? How might we handle backward compatibility? And should this be formalized as an FEP?
Curious what others think about this approach.
Hey folks! We're excited to share a preview of a new API coming in #Fedify 1.6 that should make structuring larger federated apps much cleaner: FederationBuilder.
As your Fedify applications grow, you might encounter circular dependency issues when registering dispatchers and listeners across multiple files. The new FederationBuilder pattern helps solve this by separating the configuration phase from instantiation.
Instead of this:
// federation.tsimport { createFederation } from "@fedify/fedify";export const federation = createFederation<AppContext>({ kv: new DbKvStore(), queue: new RedisMessageQueue(), // Other options...});// Now we need to import this federation instance in other files// to register dispatchers and listeners...
You can now do this:
// builder.tsimport { createFederationBuilder } from "@fedify/fedify";export const builder = createFederationBuilder<AppContext>();// other files can import and configure this builder...
// actors.tsimport { builder } from "./builder.ts";import { Person } from "@fedify/fedify";builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => { // Actor implementation});
// inbox.tsimport { builder } from "./builder.ts";import { Follow } from "@fedify/fedify";builder.setInboxListeners("/users/{handle}/inbox", "/inbox") .on(Follow, async (ctx, follow) => { // Follow handling });
// main.ts — Only create the Federation instance at startupimport { builder } from "./builder.ts";// Build the Federation object with actual dependenciesexport const federation = await builder.build({ kv: new DbKvStore(), queue: new RedisMessageQueue(), // Other options...});
This pattern helps avoid circular dependencies and makes your code more modular. Each part of your app can configure the builder without needing the actual Federation instance.
The full documentation will be available when 1.6 is released, but we wanted to share this early with our community. Looking forward to your feedback when it lands!
Want to try it right now? You can install the development version from JSR or npm:
# Denodeno add jsr:@fedify/fedify@1.6.0-dev.777+1206cb01# Node.jsnpm add @fedify/fedify@1.6.0-dev.777# Bunbun add @fedify/fedify@1.6.0-dev.777
If you're interested in building your own #ActivityPub server but don't know where to start, I recommend checking out #Fedify's #tutorial Creating your own federated microblog. It provides a comprehensive, step-by-step guide that walks you through building a fully functional federated application. Perfect for developers who want to dive into the #fediverse!
#Fedify 1.6 is approaching with three major enhancements: RFC 9421 HTTP Message Signatures support with double-knocking for seamless backward compatibility, a new builder pattern for better code organization in large applications, and native #Cloudflare #Workers support for serverless deployments. These additions strengthen Fedify's standards compliance while expanding deployment flexibility across different environments. Stay tuned for the official release! 🚀
#ActivityPub #fedidev #fediverse #RFC9421 #CloudflareWorkers