Fedify: an ActivityPub server framework<p>Hey folks! We're excited to share a preview of a new API coming in <a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/Fedify" target="_blank">#<span>Fedify</span></a> 1.6 that should make structuring larger federated apps much cleaner: <a href="https://unstable.fedify.dev/manual/federation#builder-pattern-for-structuring" rel="nofollow noopener noreferrer" target="_blank"><code>FederationBuilder</code></a>.</p><p>As your Fedify applications grow, you might encounter circular dependency issues when registering dispatchers and listeners across multiple files. The new <a href="https://unstable.fedify.dev/manual/federation#builder-pattern-for-structuring" rel="nofollow noopener noreferrer" target="_blank"><code>FederationBuilder</code></a> pattern helps solve this by separating the configuration phase from instantiation.</p><p>Instead of this:</p><pre><code>// federation.ts
import { 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...
</code></pre><p>You can now do this:</p><pre><code>// builder.ts
import { createFederationBuilder } from "@fedify/fedify";
export const builder = createFederationBuilder<AppContext>();
// other files can import and configure this builder...
</code></pre><pre><code>// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";
builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
// Actor implementation
});
</code></pre><pre><code>// inbox.ts
import { builder } from "./builder.ts";
import { Follow } from "@fedify/fedify";
builder.setInboxListeners("/users/{handle}/inbox", "/inbox")
.on(Follow, async (ctx, follow) => {
// Follow handling
});
</code></pre><pre><code>// main.ts — Only create the Federation instance at startup
import { builder } from "./builder.ts";
// Build the Federation object with actual dependencies
export const federation = await builder.build({
kv: new DbKvStore(),
queue: new RedisMessageQueue(),
// Other options...
});
</code></pre><p>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 <code>Federation</code> instance.</p><p>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!</p><p>Want to try it right now? You can install the development version from <a href="https://jsr.io/@fedify/fedify@1.6.0-dev.777+1206cb01" rel="nofollow noopener noreferrer" target="_blank">JSR</a> or <a href="https://www.npmjs.com/package/@fedify/fedify/v/1.6.0-dev.777" rel="nofollow noopener noreferrer" target="_blank">npm</a>:</p><pre><code># Deno
deno add jsr:@fedify/fedify@1.6.0-dev.777+1206cb01
# Node.js
npm add @fedify/fedify@1.6.0-dev.777
# Bun
bun add @fedify/fedify@1.6.0-dev.777
</code></pre><p><a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/ActivityPub" target="_blank">#<span>ActivityPub</span></a> <a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/fedidev" target="_blank">#<span>fedidev</span></a></p>