#fedidev

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

My stance on 's adoption of JSON-LD: Since we've already decided to use JSON-LD, I hope we do it properly. However, if we hadn't used JSON-LD from the beginning, things would have been much less complicated.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

My stance on 's adoption of JSON-LD: Since we've already decided to use JSON-LD, I hope we do it properly. However, if we hadn't used JSON-LD from the beginning, things would have been much less complicated.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

My stance on 's adoption of JSON-LD: Since we've already decided to use JSON-LD, I hope we do it properly. However, if we hadn't used JSON-LD from the beginning, things would have been much less complicated.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

My stance on 's adoption of JSON-LD: Since we've already decided to use JSON-LD, I hope we do it properly. However, if we hadn't used JSON-LD from the beginning, things would have been much less complicated.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

My stance on 's adoption of JSON-LD: Since we've already decided to use JSON-LD, I hope we do it properly. However, if we hadn't used JSON-LD from the beginning, things would have been much less complicated.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I've been reflecting lately on projects like @fedify, @hollo, and @botkit. Sometimes I wonder if I'm solving problems that very few people actually need solved. How many developers truly want to build their own server from scratch?

It feels a bit like inventing shoes that let people walk on their hands all day. Would there be a viable market? How many would actually buy them?

That's the sense I get with these projects. They do have users who find them tremendously valuable, but the total user base is inherently limited. The tools serve an important function for a small audience of specialized developers.

There are moments when my motivation wavers. When the user community consists of just a handful of enthusiastic supporters, it's sometimes difficult to maintain momentum and justify the ongoing investment of time and energy.

And yet, there's something meaningful about creating specialized tools that solve complex problems well, even if they're only used by a few. Perhaps that's enough.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hey folks! We're excited to share a preview of a new API coming in 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.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...

You can now do this:

// builder.ts
import { createFederationBuilder } from "@fedify/fedify";

export const builder = createFederationBuilder<AppContext>();

// other files can import and configure this builder...
// actors.ts
import { builder } from "./builder.ts";
import { Person } from "@fedify/fedify";

builder.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
  // Actor implementation
});
// 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
  });
// 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...
});

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:

# 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

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I've been reflecting lately on projects like @fedify, @hollo, and @botkit. Sometimes I wonder if I'm solving problems that very few people actually need solved. How many developers truly want to build their own server from scratch?

It feels a bit like inventing shoes that let people walk on their hands all day. Would there be a viable market? How many would actually buy them?

That's the sense I get with these projects. They do have users who find them tremendously valuable, but the total user base is inherently limited. The tools serve an important function for a small audience of specialized developers.

There are moments when my motivation wavers. When the user community consists of just a handful of enthusiastic supporters, it's sometimes difficult to maintain momentum and justify the ongoing investment of time and energy.

And yet, there's something meaningful about creating specialized tools that solve complex problems well, even if they're only used by a few. Perhaps that's enough.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I've been reflecting lately on projects like @fedify, @hollo, and @botkit. Sometimes I wonder if I'm solving problems that very few people actually need solved. How many developers truly want to build their own server from scratch?

It feels a bit like inventing shoes that let people walk on their hands all day. Would there be a viable market? How many would actually buy them?

That's the sense I get with these projects. They do have users who find them tremendously valuable, but the total user base is inherently limited. The tools serve an important function for a small audience of specialized developers.

There are moments when my motivation wavers. When the user community consists of just a handful of enthusiastic supporters, it's sometimes difficult to maintain momentum and justify the ongoing investment of time and energy.

And yet, there's something meaningful about creating specialized tools that solve complex problems well, even if they're only used by a few. Perhaps that's enough.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I've been reflecting lately on projects like @fedify, @hollo, and @botkit. Sometimes I wonder if I'm solving problems that very few people actually need solved. How many developers truly want to build their own server from scratch?

It feels a bit like inventing shoes that let people walk on their hands all day. Would there be a viable market? How many would actually buy them?

That's the sense I get with these projects. They do have users who find them tremendously valuable, but the total user base is inherently limited. The tools serve an important function for a small audience of specialized developers.

There are moments when my motivation wavers. When the user community consists of just a handful of enthusiastic supporters, it's sometimes difficult to maintain momentum and justify the ongoing investment of time and energy.

And yet, there's something meaningful about creating specialized tools that solve complex problems well, even if they're only used by a few. Perhaps that's enough.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I've been reflecting lately on projects like @fedify, @hollo, and @botkit. Sometimes I wonder if I'm solving problems that very few people actually need solved. How many developers truly want to build their own server from scratch?

It feels a bit like inventing shoes that let people walk on their hands all day. Would there be a viable market? How many would actually buy them?

That's the sense I get with these projects. They do have users who find them tremendously valuable, but the total user base is inherently limited. The tools serve an important function for a small audience of specialized developers.

There are moments when my motivation wavers. When the user community consists of just a handful of enthusiastic supporters, it's sometimes difficult to maintain momentum and justify the ongoing investment of time and energy.

And yet, there's something meaningful about creating specialized tools that solve complex problems well, even if they're only used by a few. Perhaps that's enough.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

A HEALTH-CHECK URL would, for example, make sure:

• the web-server is up,
• the database connection is fine,
• maybe query one or more important tables to make sure that still works,
• make sure any 3rd party APIs are working,
• etc.

If any of those things has a problem, then it would return "500 Internal Server Error".

Else (if everything was fine then) it would return "200 OK".

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A lot of Fediverse software has a HEALTH-CHECK URL.

But not all Fediverse does.

It would be better if ALL Fediverse software had a HEALTH-CHECK URL.

...

A HEALTH-CHECK URL is a special URL that tell others if the system is running properly.

It would return "200 OK" if everything is fine. And return "500 Internal Server Error" if there is a problem

...

A HEALTH-CHECK URL is important to those who actual run and administrate Fediverse servers

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

A HEALTH-CHECK URL would, for example, make sure:

• the web-server is up,
• the database connection is fine,
• maybe query one or more important tables to make sure that still works,
• make sure any 3rd party APIs are working,
• etc.

If any of those things has a problem, then it would return "500 Internal Server Error".

Else (if everything was fine then) it would return "200 OK".

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A lot of Fediverse software has a HEALTH-CHECK URL.

But not all Fediverse does.

It would be better if ALL Fediverse software had a HEALTH-CHECK URL.

...

A HEALTH-CHECK URL is a special URL that tell others if the system is running properly.

It would return "200 OK" if everything is fine. And return "500 Internal Server Error" if there is a problem

...

A HEALTH-CHECK URL is important to those who actual run and administrate Fediverse servers

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0 릴리스

BotKit 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 () 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.

이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.

더 나은 봇 상호작용을 위한 여정

BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.

커스텀 에모지로 봇의 개성 표현하기

가장 많이 요청받았던 기능 중 하나가 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.

// 봇의 커스텀 에모지 정의하기
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// 메시지에 커스텀 에모지 사용하기
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}은 Fedify ${customEmoji(emojis.fedify)}의 지원을 받습니다`
);

이 새로운 API를 통해 다음과 같은 기능을 사용할 수 있습니다.

반응을 통한 소통

소통은 단순히 메시지를 게시하는 것만이 아닙니다. 다른 사람의 메시지에 반응하는 것도 중요합니다. 새로운 반응 시스템은 봇과 팔로워 사이에 자연스러운 상호작용 지점을 만들어 줍니다.

// 표준 유니코드 에모지로 메시지에 반응하기
await message.react(emoji`👍`);

// 또는 정의한 커스텀 에모지로 반응하기
await message.react(emojis.botkit);

// 반응을 인식하고 응답하는 봇 만들기
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}님, 제 메시지에 ${reaction.emoji} 반응을 남겨주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

이 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

  • Message.react()를 사용하여 유니코드 에모지로 메시지에 반응하기
  • 정의한 커스텀 에모지로 반응하기
  • Bot.onReactBot.onUnreact 핸들러로 반응 이벤트 처리하기

인용을 통한 대화

토론에서는 종종 다른 사람이 말한 내용을 참조해야 할 때가 있습니다. 새로운 기능은 더 응집력 있는 대화 스레드를 만들어 줍니다.

// 봇의 게시물에서 다른 메시지 인용하기
await session.publish(
  text`이 흥미로운 관점에 대한 답변입니다...`,
  { quoteTarget: originalMessage }
);

// 사용자가 봇의 메시지를 인용할 때 처리하기
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}님, 제 생각을 공유해 주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

인용 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

시각적 개선

소통은 시각적인 요소도 중요하기 때문에 봇의 표현 방식을 개선했습니다.

  • 웹 인터페이스에서 이미지 첨부파일이 제대로 표시됩니다
  • 봇의 콘텐츠가 더 보기 좋아지고 풍부한 경험을 제공합니다

내부 개선: 향상된 액티비티 전파

연합우주에서 액티비티가 전파되는 방식도 개선했습니다.

  • 답글, 공유, 업데이트, 삭제의 더 정확한 전파
  • 원본 메시지 작성자에게 액티비티가 제대로 전송됩니다

이러한 개선 사항은 다양한 연합우주 플랫폼에서 봇의 상호작용이 일관되고 안정적으로 이루어지도록 보장합니다.

BotKit 0.2.0으로 첫 걸음 떼기

이러한 새로운 기능을 경험해 보고 싶으신가요? BotKit 0.2.0은 JSR에서 받을 수 있으며 간단한 명령어로 설치할 수 있습니다.

deno add jsr:@fedify/botkit@0.2.0

BotKit은 Temporal API(JavaScript에서 아직 시범적인 기능)를 사용하므로 deno.json에서 이를 활성화해야 합니다.

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

이 간단한 단계를 통해 최신 기능으로 연합우주 봇을 만들거나 업그레이드할 준비가 완료되었습니다.

앞으로의 전망

BotKit 0.2.0은 연합우주 봇 개발을 접근하기 쉽고, 강력하며, 즐겁게 만들기 위한 우리의 지속적인 노력을 보여줍니다. 이러한 새로운 기능들이 여러분의 봇이 연합우주 커뮤니티에서 더 매력적이고 상호작용이 풍부한 구성원이 되는 데 도움이 될 것이라고 믿습니다.

전체 문서와 더 많은 예제는 저희 문서 사이트에서 확인하실 수 있습니다.

피드백, 기능 요청, 코드 기여를 통해 이번 릴리스에 도움을 주신 모든 분들께 감사드립니다. BotKit 커뮤니티는 계속 성장하고 있으며, 여러분이 만들어낼 작품들을 기대합니다!


BotKit은 ActivityPub 서버 애플리케이션을 만들기 위한 하위 레벨 프레임워크인 Fedify의 지원을 받습니다.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Coming soon in 0.2.0: Native post support!

We're excited to share a preview of the upcoming quoting features in BotKit 0.2.0. This update will make it easier for your bots to engage with quoted content across the fediverse.

The quoting feature set includes:

Here's a quick example of how you can use the quote detection:

bot.onQuote = async (session, quote) => {
  // The quote parameter is a Message object representing the post that quoted your bot
  await quote.reply(text`Thanks for quoting my post, ${quote.actor}!`);
  
  // You can access the original quoted message
  const originalPost = quote.quoteTarget;
  console.log(`Original message: ${originalPost?.text}`);
};

And creating quote posts is just as simple:

// Quote in a new post
await session.publish(
  text`I'm quoting this interesting message!`,
  { quoteTarget: someMessage }
);

// Or quote in a reply
await message.reply(
  text`Interesting point! I'm quoting another relevant post here.`,
  { quoteTarget: anotherMessage }
);

Remember that quoting behavior may vary across different implementations—some platforms like Misskey display quotes prominently, while others like Mastodon might implement them differently.

Want to try these features right now? You can install the development version from JSR:

deno add jsr:@fedify/botkit@0.2.0-dev.90+d6ab4bdc

We're looking forward to seeing how you use these quoting capabilities in your bots!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0 릴리스

BotKit 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 () 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.

이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.

더 나은 봇 상호작용을 위한 여정

BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.

커스텀 에모지로 봇의 개성 표현하기

가장 많이 요청받았던 기능 중 하나가 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.

// 봇의 커스텀 에모지 정의하기
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// 메시지에 커스텀 에모지 사용하기
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}은 Fedify ${customEmoji(emojis.fedify)}의 지원을 받습니다`
);

이 새로운 API를 통해 다음과 같은 기능을 사용할 수 있습니다.

반응을 통한 소통

소통은 단순히 메시지를 게시하는 것만이 아닙니다. 다른 사람의 메시지에 반응하는 것도 중요합니다. 새로운 반응 시스템은 봇과 팔로워 사이에 자연스러운 상호작용 지점을 만들어 줍니다.

// 표준 유니코드 에모지로 메시지에 반응하기
await message.react(emoji`👍`);

// 또는 정의한 커스텀 에모지로 반응하기
await message.react(emojis.botkit);

// 반응을 인식하고 응답하는 봇 만들기
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}님, 제 메시지에 ${reaction.emoji} 반응을 남겨주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

이 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

  • Message.react()를 사용하여 유니코드 에모지로 메시지에 반응하기
  • 정의한 커스텀 에모지로 반응하기
  • Bot.onReactBot.onUnreact 핸들러로 반응 이벤트 처리하기

인용을 통한 대화

토론에서는 종종 다른 사람이 말한 내용을 참조해야 할 때가 있습니다. 새로운 기능은 더 응집력 있는 대화 스레드를 만들어 줍니다.

// 봇의 게시물에서 다른 메시지 인용하기
await session.publish(
  text`이 흥미로운 관점에 대한 답변입니다...`,
  { quoteTarget: originalMessage }
);

// 사용자가 봇의 메시지를 인용할 때 처리하기
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}님, 제 생각을 공유해 주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

인용 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

시각적 개선

소통은 시각적인 요소도 중요하기 때문에 봇의 표현 방식을 개선했습니다.

  • 웹 인터페이스에서 이미지 첨부파일이 제대로 표시됩니다
  • 봇의 콘텐츠가 더 보기 좋아지고 풍부한 경험을 제공합니다

내부 개선: 향상된 액티비티 전파

연합우주에서 액티비티가 전파되는 방식도 개선했습니다.

  • 답글, 공유, 업데이트, 삭제의 더 정확한 전파
  • 원본 메시지 작성자에게 액티비티가 제대로 전송됩니다

이러한 개선 사항은 다양한 연합우주 플랫폼에서 봇의 상호작용이 일관되고 안정적으로 이루어지도록 보장합니다.

BotKit 0.2.0으로 첫 걸음 떼기

이러한 새로운 기능을 경험해 보고 싶으신가요? BotKit 0.2.0은 JSR에서 받을 수 있으며 간단한 명령어로 설치할 수 있습니다.

deno add jsr:@fedify/botkit@0.2.0

BotKit은 Temporal API(JavaScript에서 아직 시범적인 기능)를 사용하므로 deno.json에서 이를 활성화해야 합니다.

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

이 간단한 단계를 통해 최신 기능으로 연합우주 봇을 만들거나 업그레이드할 준비가 완료되었습니다.

앞으로의 전망

BotKit 0.2.0은 연합우주 봇 개발을 접근하기 쉽고, 강력하며, 즐겁게 만들기 위한 우리의 지속적인 노력을 보여줍니다. 이러한 새로운 기능들이 여러분의 봇이 연합우주 커뮤니티에서 더 매력적이고 상호작용이 풍부한 구성원이 되는 데 도움이 될 것이라고 믿습니다.

전체 문서와 더 많은 예제는 저희 문서 사이트에서 확인하실 수 있습니다.

피드백, 기능 요청, 코드 기여를 통해 이번 릴리스에 도움을 주신 모든 분들께 감사드립니다. BotKit 커뮤니티는 계속 성장하고 있으며, 여러분이 만들어낼 작품들을 기대합니다!


BotKit은 ActivityPub 서버 애플리케이션을 만들기 위한 하위 레벨 프레임워크인 Fedify의 지원을 받습니다.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0 릴리스

BotKit 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 () 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.

이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.

더 나은 봇 상호작용을 위한 여정

BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.

커스텀 에모지로 봇의 개성 표현하기

가장 많이 요청받았던 기능 중 하나가 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.

// 봇의 커스텀 에모지 정의하기
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// 메시지에 커스텀 에모지 사용하기
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}은 Fedify ${customEmoji(emojis.fedify)}의 지원을 받습니다`
);

이 새로운 API를 통해 다음과 같은 기능을 사용할 수 있습니다.

반응을 통한 소통

소통은 단순히 메시지를 게시하는 것만이 아닙니다. 다른 사람의 메시지에 반응하는 것도 중요합니다. 새로운 반응 시스템은 봇과 팔로워 사이에 자연스러운 상호작용 지점을 만들어 줍니다.

// 표준 유니코드 에모지로 메시지에 반응하기
await message.react(emoji`👍`);

// 또는 정의한 커스텀 에모지로 반응하기
await message.react(emojis.botkit);

// 반응을 인식하고 응답하는 봇 만들기
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}님, 제 메시지에 ${reaction.emoji} 반응을 남겨주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

이 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

  • Message.react()를 사용하여 유니코드 에모지로 메시지에 반응하기
  • 정의한 커스텀 에모지로 반응하기
  • Bot.onReactBot.onUnreact 핸들러로 반응 이벤트 처리하기

인용을 통한 대화

토론에서는 종종 다른 사람이 말한 내용을 참조해야 할 때가 있습니다. 새로운 기능은 더 응집력 있는 대화 스레드를 만들어 줍니다.

// 봇의 게시물에서 다른 메시지 인용하기
await session.publish(
  text`이 흥미로운 관점에 대한 답변입니다...`,
  { quoteTarget: originalMessage }
);

// 사용자가 봇의 메시지를 인용할 때 처리하기
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}님, 제 생각을 공유해 주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

인용 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

시각적 개선

소통은 시각적인 요소도 중요하기 때문에 봇의 표현 방식을 개선했습니다.

  • 웹 인터페이스에서 이미지 첨부파일이 제대로 표시됩니다
  • 봇의 콘텐츠가 더 보기 좋아지고 풍부한 경험을 제공합니다

내부 개선: 향상된 액티비티 전파

연합우주에서 액티비티가 전파되는 방식도 개선했습니다.

  • 답글, 공유, 업데이트, 삭제의 더 정확한 전파
  • 원본 메시지 작성자에게 액티비티가 제대로 전송됩니다

이러한 개선 사항은 다양한 연합우주 플랫폼에서 봇의 상호작용이 일관되고 안정적으로 이루어지도록 보장합니다.

BotKit 0.2.0으로 첫 걸음 떼기

이러한 새로운 기능을 경험해 보고 싶으신가요? BotKit 0.2.0은 JSR에서 받을 수 있으며 간단한 명령어로 설치할 수 있습니다.

deno add jsr:@fedify/botkit@0.2.0

BotKit은 Temporal API(JavaScript에서 아직 시범적인 기능)를 사용하므로 deno.json에서 이를 활성화해야 합니다.

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

이 간단한 단계를 통해 최신 기능으로 연합우주 봇을 만들거나 업그레이드할 준비가 완료되었습니다.

앞으로의 전망

BotKit 0.2.0은 연합우주 봇 개발을 접근하기 쉽고, 강력하며, 즐겁게 만들기 위한 우리의 지속적인 노력을 보여줍니다. 이러한 새로운 기능들이 여러분의 봇이 연합우주 커뮤니티에서 더 매력적이고 상호작용이 풍부한 구성원이 되는 데 도움이 될 것이라고 믿습니다.

전체 문서와 더 많은 예제는 저희 문서 사이트에서 확인하실 수 있습니다.

피드백, 기능 요청, 코드 기여를 통해 이번 릴리스에 도움을 주신 모든 분들께 감사드립니다. BotKit 커뮤니티는 계속 성장하고 있으며, 여러분이 만들어낼 작품들을 기대합니다!


BotKit은 ActivityPub 서버 애플리케이션을 만들기 위한 하위 레벨 프레임워크인 Fedify의 지원을 받습니다.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:'s post

BotKit 0.2.0 릴리스

BotKit 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 () 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.

이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.

더 나은 봇 상호작용을 위한 여정

BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.

커스텀 에모지로 봇의 개성 표현하기

가장 많이 요청받았던 기능 중 하나가 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.

// 봇의 커스텀 에모지 정의하기
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// 메시지에 커스텀 에모지 사용하기
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}은 Fedify ${customEmoji(emojis.fedify)}의 지원을 받습니다`
);

이 새로운 API를 통해 다음과 같은 기능을 사용할 수 있습니다.

반응을 통한 소통

소통은 단순히 메시지를 게시하는 것만이 아닙니다. 다른 사람의 메시지에 반응하는 것도 중요합니다. 새로운 반응 시스템은 봇과 팔로워 사이에 자연스러운 상호작용 지점을 만들어 줍니다.

// 표준 유니코드 에모지로 메시지에 반응하기
await message.react(emoji`👍`);

// 또는 정의한 커스텀 에모지로 반응하기
await message.react(emojis.botkit);

// 반응을 인식하고 응답하는 봇 만들기
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}님, 제 메시지에 ${reaction.emoji} 반응을 남겨주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

이 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

  • Message.react()를 사용하여 유니코드 에모지로 메시지에 반응하기
  • 정의한 커스텀 에모지로 반응하기
  • Bot.onReactBot.onUnreact 핸들러로 반응 이벤트 처리하기

인용을 통한 대화

토론에서는 종종 다른 사람이 말한 내용을 참조해야 할 때가 있습니다. 새로운 기능은 더 응집력 있는 대화 스레드를 만들어 줍니다.

// 봇의 게시물에서 다른 메시지 인용하기
await session.publish(
  text`이 흥미로운 관점에 대한 답변입니다...`,
  { quoteTarget: originalMessage }
);

// 사용자가 봇의 메시지를 인용할 때 처리하기
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}님, 제 생각을 공유해 주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

인용 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

시각적 개선

소통은 시각적인 요소도 중요하기 때문에 봇의 표현 방식을 개선했습니다.

  • 웹 인터페이스에서 이미지 첨부파일이 제대로 표시됩니다
  • 봇의 콘텐츠가 더 보기 좋아지고 풍부한 경험을 제공합니다

내부 개선: 향상된 액티비티 전파

연합우주에서 액티비티가 전파되는 방식도 개선했습니다.

  • 답글, 공유, 업데이트, 삭제의 더 정확한 전파
  • 원본 메시지 작성자에게 액티비티가 제대로 전송됩니다

이러한 개선 사항은 다양한 연합우주 플랫폼에서 봇의 상호작용이 일관되고 안정적으로 이루어지도록 보장합니다.

BotKit 0.2.0으로 첫 걸음 떼기

이러한 새로운 기능을 경험해 보고 싶으신가요? BotKit 0.2.0은 JSR에서 받을 수 있으며 간단한 명령어로 설치할 수 있습니다.

deno add jsr:@fedify/botkit@0.2.0

BotKit은 Temporal API(JavaScript에서 아직 시범적인 기능)를 사용하므로 deno.json에서 이를 활성화해야 합니다.

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

이 간단한 단계를 통해 최신 기능으로 연합우주 봇을 만들거나 업그레이드할 준비가 완료되었습니다.

앞으로의 전망

BotKit 0.2.0은 연합우주 봇 개발을 접근하기 쉽고, 강력하며, 즐겁게 만들기 위한 우리의 지속적인 노력을 보여줍니다. 이러한 새로운 기능들이 여러분의 봇이 연합우주 커뮤니티에서 더 매력적이고 상호작용이 풍부한 구성원이 되는 데 도움이 될 것이라고 믿습니다.

전체 문서와 더 많은 예제는 저희 문서 사이트에서 확인하실 수 있습니다.

피드백, 기능 요청, 코드 기여를 통해 이번 릴리스에 도움을 주신 모든 분들께 감사드립니다. BotKit 커뮤니티는 계속 성장하고 있으며, 여러분이 만들어낼 작품들을 기대합니다!


BotKit은 ActivityPub 서버 애플리케이션을 만들기 위한 하위 레벨 프레임워크인 Fedify의 지원을 받습니다.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Coming soon in 0.2.0: Native post support!

We're excited to share a preview of the upcoming quoting features in BotKit 0.2.0. This update will make it easier for your bots to engage with quoted content across the fediverse.

The quoting feature set includes:

Here's a quick example of how you can use the quote detection:

bot.onQuote = async (session, quote) => {
  // The quote parameter is a Message object representing the post that quoted your bot
  await quote.reply(text`Thanks for quoting my post, ${quote.actor}!`);
  
  // You can access the original quoted message
  const originalPost = quote.quoteTarget;
  console.log(`Original message: ${originalPost?.text}`);
};

And creating quote posts is just as simple:

// Quote in a new post
await session.publish(
  text`I'm quoting this interesting message!`,
  { quoteTarget: someMessage }
);

// Or quote in a reply
await message.reply(
  text`Interesting point! I'm quoting another relevant post here.`,
  { quoteTarget: anotherMessage }
);

Remember that quoting behavior may vary across different implementations—some platforms like Misskey display quotes prominently, while others like Mastodon might implement them differently.

Want to try these features right now? You can install the development version from JSR:

deno add jsr:@fedify/botkit@0.2.0-dev.90+d6ab4bdc

We're looking forward to seeing how you use these quoting capabilities in your bots!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Coming soon in 0.2.0: Native post support!

We're excited to share a preview of the upcoming quoting features in BotKit 0.2.0. This update will make it easier for your bots to engage with quoted content across the fediverse.

The quoting feature set includes:

Here's a quick example of how you can use the quote detection:

bot.onQuote = async (session, quote) => {
  // The quote parameter is a Message object representing the post that quoted your bot
  await quote.reply(text`Thanks for quoting my post, ${quote.actor}!`);
  
  // You can access the original quoted message
  const originalPost = quote.quoteTarget;
  console.log(`Original message: ${originalPost?.text}`);
};

And creating quote posts is just as simple:

// Quote in a new post
await session.publish(
  text`I'm quoting this interesting message!`,
  { quoteTarget: someMessage }
);

// Or quote in a reply
await message.reply(
  text`Interesting point! I'm quoting another relevant post here.`,
  { quoteTarget: anotherMessage }
);

Remember that quoting behavior may vary across different implementations—some platforms like Misskey display quotes prominently, while others like Mastodon might implement them differently.

Want to try these features right now? You can install the development version from JSR:

deno add jsr:@fedify/botkit@0.2.0-dev.90+d6ab4bdc

We're looking forward to seeing how you use these quoting capabilities in your bots!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Coming soon in 0.2.0: Native post support!

We're excited to share a preview of the upcoming quoting features in BotKit 0.2.0. This update will make it easier for your bots to engage with quoted content across the fediverse.

The quoting feature set includes:

Here's a quick example of how you can use the quote detection:

bot.onQuote = async (session, quote) => {
  // The quote parameter is a Message object representing the post that quoted your bot
  await quote.reply(text`Thanks for quoting my post, ${quote.actor}!`);
  
  // You can access the original quoted message
  const originalPost = quote.quoteTarget;
  console.log(`Original message: ${originalPost?.text}`);
};

And creating quote posts is just as simple:

// Quote in a new post
await session.publish(
  text`I'm quoting this interesting message!`,
  { quoteTarget: someMessage }
);

// Or quote in a reply
await message.reply(
  text`Interesting point! I'm quoting another relevant post here.`,
  { quoteTarget: anotherMessage }
);

Remember that quoting behavior may vary across different implementations—some platforms like Misskey display quotes prominently, while others like Mastodon might implement them differently.

Want to try these features right now? You can install the development version from JSR:

deno add jsr:@fedify/botkit@0.2.0-dev.90+d6ab4bdc

We're looking forward to seeing how you use these quoting capabilities in your bots!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Coming soon in 0.2.0: Native post support!

We're excited to share a preview of the upcoming quoting features in BotKit 0.2.0. This update will make it easier for your bots to engage with quoted content across the fediverse.

The quoting feature set includes:

Here's a quick example of how you can use the quote detection:

bot.onQuote = async (session, quote) => {
  // The quote parameter is a Message object representing the post that quoted your bot
  await quote.reply(text`Thanks for quoting my post, ${quote.actor}!`);
  
  // You can access the original quoted message
  const originalPost = quote.quoteTarget;
  console.log(`Original message: ${originalPost?.text}`);
};

And creating quote posts is just as simple:

// Quote in a new post
await session.publish(
  text`I'm quoting this interesting message!`,
  { quoteTarget: someMessage }
);

// Or quote in a reply
await message.reply(
  text`Interesting point! I'm quoting another relevant post here.`,
  { quoteTarget: anotherMessage }
);

Remember that quoting behavior may vary across different implementations—some platforms like Misskey display quotes prominently, while others like Mastodon might implement them differently.

Want to try these features right now? You can install the development version from JSR:

deno add jsr:@fedify/botkit@0.2.0-dev.90+d6ab4bdc

We're looking forward to seeing how you use these quoting capabilities in your bots!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Coming soon in 0.2.0: Native post support!

We're excited to share a preview of the upcoming quoting features in BotKit 0.2.0. This update will make it easier for your bots to engage with quoted content across the fediverse.

The quoting feature set includes:

Here's a quick example of how you can use the quote detection:

bot.onQuote = async (session, quote) => {
  // The quote parameter is a Message object representing the post that quoted your bot
  await quote.reply(text`Thanks for quoting my post, ${quote.actor}!`);
  
  // You can access the original quoted message
  const originalPost = quote.quoteTarget;
  console.log(`Original message: ${originalPost?.text}`);
};

And creating quote posts is just as simple:

// Quote in a new post
await session.publish(
  text`I'm quoting this interesting message!`,
  { quoteTarget: someMessage }
);

// Or quote in a reply
await message.reply(
  text`Interesting point! I'm quoting another relevant post here.`,
  { quoteTarget: anotherMessage }
);

Remember that quoting behavior may vary across different implementations—some platforms like Misskey display quotes prominently, while others like Mastodon might implement them differently.

Want to try these features right now? You can install the development version from JSR:

deno add jsr:@fedify/botkit@0.2.0-dev.90+d6ab4bdc

We're looking forward to seeing how you use these quoting capabilities in your bots!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to introduce emoji reactions in the upcoming 0.2.0 release!

With the new Message.react() method, your bot can now react to messages using standard Unicode :

await message.react(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!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to introduce emoji reactions in the upcoming 0.2.0 release!

With the new Message.react() method, your bot can now react to messages using standard Unicode :

await message.react(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!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to introduce emoji reactions in the upcoming 0.2.0 release!

With the new Message.react() method, your bot can now react to messages using standard Unicode :

await message.react(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!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to introduce emoji reactions in the upcoming 0.2.0 release!

With the new Message.react() method, your bot can now react to messages using standard Unicode :

await message.react(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!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to introduce emoji reactions in the upcoming 0.2.0 release!

With the new Message.react() method, your bot can now react to messages using standard Unicode :

await message.react(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!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to announce that 0.2.0 will introduce custom emoji support! This feature allows your bots to express themselves with more personality and engagement.

What's included:

  • Add custom emojis to your bot with Bot.addCustomEmojis()
  • Use emoji in messages with the customEmoji() function
  • Support for both local image files and remote URLs as emoji sources
  • Full integration with BotKit's text formatting system

Simple example:

// Define custom emojis
const emojis = bot.addCustomEmojis({
  botkit: { file: "./botkit.png", type: "image/png" },
  fedify: { url: "https://fedify.dev/logo.png", type: "image/png" }
});

// Use in messages
await session.publish(
  text`Hello world! ${customEmoji(emojis.botkit)}`
);

Want to try it early? You can install the development version from JSR today:

deno add jsr:@fedify/botkit@0.2.0-dev.82+8a0438e6

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to announce that 0.2.0 will introduce custom emoji support! This feature allows your bots to express themselves with more personality and engagement.

What's included:

  • Add custom emojis to your bot with Bot.addCustomEmojis()
  • Use emoji in messages with the customEmoji() function
  • Support for both local image files and remote URLs as emoji sources
  • Full integration with BotKit's text formatting system

Simple example:

// Define custom emojis
const emojis = bot.addCustomEmojis({
  botkit: { file: "./botkit.png", type: "image/png" },
  fedify: { url: "https://fedify.dev/logo.png", type: "image/png" }
});

// Use in messages
await session.publish(
  text`Hello world! ${customEmoji(emojis.botkit)}`
);

Want to try it early? You can install the development version from JSR today:

deno add jsr:@fedify/botkit@0.2.0-dev.82+8a0438e6

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to announce that 0.2.0 will introduce custom emoji support! This feature allows your bots to express themselves with more personality and engagement.

What's included:

  • Add custom emojis to your bot with Bot.addCustomEmojis()
  • Use emoji in messages with the customEmoji() function
  • Support for both local image files and remote URLs as emoji sources
  • Full integration with BotKit's text formatting system

Simple example:

// Define custom emojis
const emojis = bot.addCustomEmojis({
  botkit: { file: "./botkit.png", type: "image/png" },
  fedify: { url: "https://fedify.dev/logo.png", type: "image/png" }
});

// Use in messages
await session.publish(
  text`Hello world! ${customEmoji(emojis.botkit)}`
);

Want to try it early? You can install the development version from JSR today:

deno add jsr:@fedify/botkit@0.2.0-dev.82+8a0438e6

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

We're excited to announce that 0.2.0 will introduce custom emoji support! This feature allows your bots to express themselves with more personality and engagement.

What's included:

  • Add custom emojis to your bot with Bot.addCustomEmojis()
  • Use emoji in messages with the customEmoji() function
  • Support for both local image files and remote URLs as emoji sources
  • Full integration with BotKit's text formatting system

Simple example:

// Define custom emojis
const emojis = bot.addCustomEmojis({
  botkit: { file: "./botkit.png", type: "image/png" },
  fedify: { url: "https://fedify.dev/logo.png", type: "image/png" }
});

// Use in messages
await session.publish(
  text`Hello world! ${customEmoji(emojis.botkit)}`
);

Want to try it early? You can install the development version from JSR today:

deno add jsr:@fedify/botkit@0.2.0-dev.82+8a0438e6

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

もしかしたらご存じないかもしれませんが、Fedifyには DiscordとMatrixのコミュニティがあります。ここでは、サポートを受けたり、機能について議論したり、ActivityPubやフェデレーテッドソーシャルネットワークについて話し合うことができます。

お好みのコミュニティにご参加ください。どちらのチャンネルでも、Fedifyやフェデレーション関連のトピックについて活発な議論が行われています。

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

もしかしたらご存じないかもしれませんが、Fedifyには DiscordとMatrixのコミュニティがあります。ここでは、サポートを受けたり、機能について議論したり、ActivityPubやフェデレーテッドソーシャルネットワークについて話し合うことができます。

お好みのコミュニティにご参加ください。どちらのチャンネルでも、Fedifyやフェデレーション関連のトピックについて活発な議論が行われています。

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

もしかしたらご存じないかもしれませんが、Fedifyには DiscordとMatrixのコミュニティがあります。ここでは、サポートを受けたり、機能について議論したり、ActivityPubやフェデレーテッドソーシャルネットワークについて話し合うことができます。

お好みのコミュニティにご参加ください。どちらのチャンネルでも、Fedifyやフェデレーション関連のトピックについて活発な議論が行われています。

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

혹시 모르고 계셨다면, Fedify는 Discord와 Matrix 커뮤니티를 운영하고 있습니다. 이곳에서 도움을 받거나, 기능에 대해 논의하거나, ActivityPub와 연합 소셜 네트워크에 대해 대화를 나눌 수 있습니다.

여러분의 선호도에 따라 어느 커뮤니티든 참여해 주세요. 두 채널 모두 Fedify와 연합 관련 주제에 대한 활발한 논의가 이루어지고 있습니다.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

もしかしたらご存じないかもしれませんが、Fedifyには DiscordとMatrixのコミュニティがあります。ここでは、サポートを受けたり、機能について議論したり、ActivityPubやフェデレーテッドソーシャルネットワークについて話し合うことができます。

お好みのコミュニティにご参加ください。どちらのチャンネルでも、Fedifyやフェデレーション関連のトピックについて活発な議論が行われています。

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

혹시 모르고 계셨다면, Fedify는 Discord와 Matrix 커뮤니티를 운영하고 있습니다. 이곳에서 도움을 받거나, 기능에 대해 논의하거나, ActivityPub와 연합 소셜 네트워크에 대해 대화를 나눌 수 있습니다.

여러분의 선호도에 따라 어느 커뮤니티든 참여해 주세요. 두 채널 모두 Fedify와 연합 관련 주제에 대한 활발한 논의가 이루어지고 있습니다.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In case you weren't aware, has both and communities where you can get help, discuss features, or just chat about and federated social networks.

Feel free to join either community based on your preference. Both channels have active discussions about Fedify and federation topics.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As someone who has developed several software implementations (Fedify, Hollo, BotKit, and Hackers' Pub), I believe one of the most frustrating features to implement in the is .

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 . 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Before I go though and file my own issue for this, does anyone know whats up with @peertube's support for remote edits / updates of comments/replies? It seems like its not implemented and I didn't find any issues filed for this which seemed strange to me. Maybe I am overlooking something?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

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 ecosystem, I've identified three key features that would significantly enhance the framework's capabilities:

  1. 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.

  2. 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()).

  3. 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 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

I've been wrestling with implementing content support in Hackers' Pub, our -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:

  1. Creating separate posts for each language with clear language indicators, linking them through inReplyTo relationships (so translations appear as replies to the original post)
  2. Using the primary language in content while storing translations in contentMap
  3. Adding "View in other languages" links at the bottom of each post
  4. 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.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Don't build from scratch! It's complex. See why using the framework is the smarter way to develop for the fediverse in my new post:

https://hackers.pub/@hongminhee/2025/why-use-fedify

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

So, you're captivated by the fediverse—the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycle… blindfolded. It’s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modeling—Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everything—posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)—using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ""
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": ""
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interface—non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when needed—a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identity—Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanics—Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)—Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processing—Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Security—Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authentication—a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenance—Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experience—Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harder—was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
✔ The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
✔ Sent follow request to @<some_test_account>@activitypub.academy.
╭───────────────┬─────────────────────────────────────────╮
│ Actor handle: │ i@<unique_id>.lhr.life                  │
├───────────────┼─────────────────────────────────────────┤
│   Actor URI:  │ https://<unique_id>.lhr.life/i          │
├───────────────┼─────────────────────────────────────────┤
│  Actor inbox: │ https://<unique_id>.lhr.life/i/inbox    │
├───────────────┼─────────────────────────────────────────┤
│ Shared inbox: │ https://<unique_id>.lhr.life/inbox      │
╰───────────────┴─────────────────────────────────────────╯

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

╭────────────────┬─────────────────────────────────────╮
│     Request #: │ 2                                   │
├────────────────┼─────────────────────────────────────┤
│ Activity type: │ Follow                              │
├────────────────┼─────────────────────────────────────┤
│  HTTP request: │ POST /i/inbox                       │
├────────────────┼─────────────────────────────────────┤
│ HTTP response: │ 202                                 │
├────────────────┼─────────────────────────────────────┤
│       Details  │ https://<unique_id>.lhr.life/r/2    │
╰────────────────┴─────────────────────────────────────╯

Crucially, the detailed information about the received request—including the full headers (like Signature), the request body (the Activity JSON), and the signature verification status—is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for you—data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fetching remote objects or actors often involves handling lookups, content negotiation, and then parsing potentially untyped JSON.

With , it's much simpler: use Context.lookupObject(). Pass it a URI (e.g., https://instance.tld/users/alice) or a handle (e.g., @alice@instance.tld), and Fedify handles the lookup and content negotiation automatically.

The real power comes from the return value: a type-safe Activity Vocabulary object, not just raw JSON. This allows you to confidently access properties and methods directly. For example, you can safely traverse account moves using .getSuccessor() like this:

let actor = await ctx.lookupObject("@alice@instance.tld");
while (isActor(actor)) {
  const successor = await actor.getSuccessor();
  if (successor == null) break;
  actor = successor;
}
// actor now holds the latest account after moves

This is readily available in handlers where the Context object is provided (like actor dispatchers or inbox listeners).

Focus on your app's logic, not protocol boilerplate!

Learn more: https://fedify.dev/manual/context#looking-up-remote-objects

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

I have been thinking that — having a regular DEMO DAY for Fediverse developers might be desirable.

Maybe something once a month, where Fediverse developers get together (online), and —

• show what they have been working on,
• talk about Fediverse development issues,
• etc

Not a conference. Just something quick.

(It could be under existing "banner" that already exists. Doesn't necessarily have to be something new.)

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

Misskey and the Misskey forks (ex: Firefish, Sharkey, etc) seem to also be prone to their storage drives filling with:

• logs
• npm cache
• yarn cache

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

RE: mastodon.social/@reiver/114019

The number one cause of Fediverse servers crashing seems to be the storage drives filling up with cached Fediverse user data — posts, profiles, avatar images, header images, etc.

But, Misskey and the Misskey forks (ex: Firefish, Sharkey, etc) also have an additional challenge that fills up their storage drives —

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

A nice side-effect of using a Fediverse caching server is — for some Fediverse software, it would enable the Fediverse software to run on a less expensive computer.

(For example, compressing and shrinking images can make the computer needs higher. If that is delegated to a caching server, etc, then the Fediverse server doesn't incur that higher computer needs. Which makes hosting less expensive.)

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

I think a good strategy to broadly address this is — for Fediverse software to have a concept of caching-servers they could delegate to, to do the caching for them.

These caching servers could even be shared.

...

I have been working on such a Fediverse caching server.

But the various Fediverse software out there would need to be modified to use it.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

I can tell you from experience of hosting many people's Fediverse server instances for a number of years now that —

Many Fediverse software (at least currently) do a poor job of cleaning-up their various caches

Caching other people's profiles, images, posts, etc

And, this often ends up filling up the storage drive

And as a result, this is a very common thing that causes down-time for people. Probably the most common

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

📣 Exciting news! Fedify CLI is now available via Homebrew!

If you're using on macOS or 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!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

Abelio's avatar
Abelio

@abelio@mastodon.social

FYI: Abelio will provide couple of ways of publishing visual contents. One of them is part of the article editor and it let's you organise multiple images in a form of a flexible grid you can arrange as needed.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Listen, as someone that follows many fediverse platforms, @thisismissem is one of the most active in the community. She has jumped in and assisted with security and ActivityPub issues across them all.

Please consider contributing to her tip jar if you can, especially for this last bit of advocacy work. Find her contribution options on her profile.

hachyderm.io/@thisismissem/114

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Listen, as someone that follows many fediverse platforms, @thisismissem is one of the most active in the community. She has jumped in and assisted with security and ActivityPub issues across them all.

Please consider contributing to her tip jar if you can, especially for this last bit of advocacy work. Find her contribution options on her profile.

hachyderm.io/@thisismissem/114

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Listen, as someone that follows many fediverse platforms, @thisismissem is one of the most active in the community. She has jumped in and assisted with security and ActivityPub issues across them all.

Please consider contributing to her tip jar if you can, especially for this last bit of advocacy work. Find her contribution options on her profile.

hachyderm.io/@thisismissem/114

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Listen, as someone that follows many fediverse platforms, @thisismissem is one of the most active in the community. She has jumped in and assisted with security and ActivityPub issues across them all.

Please consider contributing to her tip jar if you can, especially for this last bit of advocacy work. Find her contribution options on her profile.

hachyderm.io/@thisismissem/114

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Listen, as someone that follows many fediverse platforms, @thisismissem is one of the most active in the community. She has jumped in and assisted with security and ActivityPub issues across them all.

Please consider contributing to her tip jar if you can, especially for this last bit of advocacy work. Find her contribution options on her profile.

hachyderm.io/@thisismissem/114

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Holloを紹介します!

Holloは、個人向けの連合型マイクロブログソフトウェアです。FedifyBunを基盤に構築され、ActivityPubプロトコルを通じて他のインスタンスやサービスと連携することができます。

Holloの特徴は、一人のユーザーのために設計された専用のインスタンスという点です。これにより、ユーザーは自分だけのスペースを持ちながら、Mastodon、Misskey、その他のActivityPub対応サービスのユーザーとも交流できます。

独自のウェブインターフェースを持たない代わりに、MastodonのAPIと互換性があるため、既存の多くのMastodonクライアントアプリを使用してHolloにアクセスできます。これにより、使い慣れたインターフェースでHolloを利用することができます。

主な機能には、投稿の作成・編集・削除、返信、メディア添付、投票、お気に入り、ブックマーク、ピン留めなどがあります。また、プロフィール編集、フォロー/フォロワー管理、リスト作成なども可能です。さらに、Markdownをサポートしているため、投稿やプロフィールの書式設定が容易に行えます。

Holloは現在開発の初期段階にあり、継続的に機能の追加や改善が行われています。Bunを使用することで、高速なパフォーマンスと効率的な開発が実現されています。オープンソースプロジェクトとして、GitHubで公開されており、コミュニティからの貢献を歓迎しています。

個人のブログとソーシャルメディアの利点を組み合わせたHolloは、プライバシーを重視しながら、より広いコミュニティとのつながりを求める人々に適したプラットフォームとなっています。

https://github.com/dahlia/hollo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

The ActivityPub specification does not have an example of the "sharedInbox" field in use.

Although it does say "An optional endpoint..." — I suspect a lot of people won't know (with confidence) that it can go under the "endpoints" field. For example:

"endpoints": {
"sharedInbox": "https://social.example/inbox"
},

Especially if the person is still trying to understand ActivityPub, and isn't aware of the "endpoints" field yet.

sharedInbox

An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
ALT text detailssharedInbox An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A reasonable ActivityPub / ActivityStreams API to schedule something to be posted in the future might be — to HTTP POST something to an account's outbox with the `published` field set to a date-time in the future.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A reasonable ActivityPub / ActivityStreams API to schedule something to be posted in the future might be — to HTTP POST something to an account's outbox with the `published` field set to a date-time in the future.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A reasonable ActivityPub / ActivityStreams API to schedule something to be posted in the future might be — to HTTP POST something to an account's outbox with the `published` field set to a date-time in the future.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

The ActivityPub specification does not have an example of the "sharedInbox" field in use.

Although it does say "An optional endpoint..." — I suspect a lot of people won't know (with confidence) that it can go under the "endpoints" field. For example:

"endpoints": {
"sharedInbox": "https://social.example/inbox"
},

Especially if the person is still trying to understand ActivityPub, and isn't aware of the "endpoints" field yet.

sharedInbox

An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
ALT text detailssharedInbox An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A reasonable ActivityPub / ActivityStreams API to schedule something to be posted in the future might be — to HTTP POST something to an account's outbox with the `published` field set to a date-time in the future.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Currently, the way I am determining if content is valid ActivityPub / ActivityStreams content is —

№1:

Determining if it is valid JSON.

№2:

Checking if it has a "type" field.

And that is it.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Dealing with JSON-LD would be easier in many ways if everything was defined inline.

Rather than having to get the content from a URL in the context, parse it, etc.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Hello @MastodonEngineering,

I wanted to share some feedback on the documentation provided in the Highlighting Journalism on Mastodon blog post.

Specifically, in The technical section, the example code for the fediverse:creator meta tag is given as:

<meta name="fediverse:creator" content="@Gargron@mastodon.social" />

Based on my testing (and that of others), Mastodon doesn't seem to recognize the creator link correctly when the leading @ is present in the content attribute. It only works when the @ is removed, like this:

<meta name="fediverse:creator" content="Gargron@mastodon.social" />

Following the blog's example directly led to some wasted time figuring out why it wasn't working. It would be great if either the example in the blog post could be corrected to reflect the current requirement, or if Mastodon's parser could be made more flexible to accept the handle with or without the leading @.

Appreciate all you do for !

Andrew Graves :arch: :linux:'s avatar
Andrew Graves :arch: :linux:

@graves501@fosstodon.org

I've been thinking of contributing to the for a while now, but I haven't really found a project or an idea that would fit my tech stack requirements yet.

Like Pixelfed and Loops have a PHP backend, but I'd rather contribute something with Golang or Typescript/Javascript.

Does anyone have some ideas?

Andrew Graves :arch: :linux:'s avatar
Andrew Graves :arch: :linux:

@graves501@fosstodon.org

I've been thinking of contributing to the for a while now, but I haven't really found a project or an idea that would fit my tech stack requirements yet.

Like Pixelfed and Loops have a PHP backend, but I'd rather contribute something with Golang or Typescript/Javascript.

Does anyone have some ideas?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

Andrew Graves :arch: :linux:'s avatar
Andrew Graves :arch: :linux:

@graves501@fosstodon.org

I've been thinking of contributing to the for a while now, but I haven't really found a project or an idea that would fit my tech stack requirements yet.

Like Pixelfed and Loops have a PHP backend, but I'd rather contribute something with Golang or Typescript/Javascript.

Does anyone have some ideas?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I received a heartwarming about today!

@bgl shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

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

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 behavior
await 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 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 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:

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 Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

The ActivityPub specification does not have an example of the "sharedInbox" field in use.

Although it does say "An optional endpoint..." — I suspect a lot of people won't know (with confidence) that it can go under the "endpoints" field. For example:

"endpoints": {
"sharedInbox": "https://social.example/inbox"
},

Especially if the person is still trying to understand ActivityPub, and isn't aware of the "endpoints" field yet.

sharedInbox

An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
ALT text detailssharedInbox An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.
Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

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.

docs.joinmastodon.org/methods/

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

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.

docs.joinmastodon.org/methods/

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

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.

docs.joinmastodon.org/methods/

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

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.

docs.joinmastodon.org/methods/

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

"Activities addressed to this special [public address] URI shall be accessible to all users, without authentication."

w3.org/TR/activitypub/#public-

The "public address" is:
w3.org/ns/activitystreams#Publ

(Yes, I am posting this for a reason.)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

I think there is a need for a "dumb" document format.

HTML is no longer that.

Markdown probably isn't it.

No one really uses enriched-text (IETF RFC 1896).

(I prefer wiki like formats, for various reasons, but —)

I don't think there is an obvious choice for a "dumb" document format, right now.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

I think HTML being the default content type for ActivityPub / ActivityStreams is unfortunate in some ways.

HTML was originally a "dumb" document format. But, it is now a "smart" application format — with privacy & security concerns.

mastodon.social/@reiver/108237

You should NOT just take whatever HTML is in the 'content', and put it in the web-browser to view it.

You have to sanitize it. Or, render (unsafe) HTML to (safe) HTML.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Previews in ActivityPub / ActivityStreams is what should bind the disparate software and user-experiences on the Fediverse.

Not the ActivityStreams 'Note'.

...

Previews using 'icon', 'image', 'name', 'summary', etc.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I just discovered why some of my followers from larger instances (like mastodon.social) would mysteriously unfollow me after a while!

A pull request was just merged in Mastodon that fixes a critical bug in their follower synchronization mechanism.

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 and other -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 !

This is why I love open source—we can identify, understand, and fix these kinds of interoperability issues together. 😊

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

I think it would be better for the Fediverse if back-end servers and front-end clients were not only decoupled, but separate projects.

mastodon.social/@reiver/111030

mastodon.social/@reiver/111223

mastodon.social/@reiver/112746

mastodon.social/@reiver/112921

People being able to have a service acting on their behalf as (at least part of) the back-end could be a path towards this back-end / front-end decoupling and separation.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

In fact, it is an old idea. I remember ideas like this floating around in the 1990s. Including in the P2P scene.

(It is common for ideas to get rediscovered over and over and over again. Different people trying to solve similar problems, and independently coming up with similar solutions.)

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

In many ways, I like the basic idea of ActivityPods, Bluesky PDS, Account Abstraction.

mastodon.social/@reiver/114216

A service acting on your behalf, and in many ways representing you (the user), with other software.

And something to which data gets "attached".

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

ActivityPods

3/

But — then, ActivityPods seems to have a spec:

activitypods.org/specs/activit

And talks about supporting other specs:

activitypods.org/specs/activit

activitypods.org/specs/solid

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

ActivityPods

2/

When I re-watch this talk (that was originally presented at FOSDEM 2025) —

peertube.virtual-assembly.org/

— it seems as if ActivityPods is software.

But —

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

ActivityPods

1/

One thing that still isn't completely clear to me about ActivityPods is —

Is ActivityPods a specification?, or is ActivityPods software?

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

programming

There is a comparison between the (proposed) ActivityPods and the Bluesky PDS.

(I am not the first person to say that.)

But, I think there is also some comparison between both of those and Account Abstraction in the EVM space.

All, in some ways, have a service acting on your behalf and in many ways representing you (the user), with other software.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

programming, did key

The did:key Method

A DID Method for Static Cryptographic Keys

w3c-ccg.github.io/did-key-spec/

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Getting back to development today! Working on optimizing the outgoing activity queue to improve response times. Currently focusing on reducing latency when sending posts to large follower counts—should make the whole publishing experience feel much snappier.

https://github.com/fedify-dev/fedify/issues/220

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Oooh @snarfed.org will be speaking about "All the protocols, compared" in 45 minutes at 4:45 PM CT.

atprotocol.dev/atmosphereconf-

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Oooh @snarfed.org will be speaking about "All the protocols, compared" in 45 minutes at 4:45 PM CT.

atprotocol.dev/atmosphereconf-

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Theres a new interview with @hongminhee (of @fedify, @hollo, and now fame). It's in with Korean subtitles but quite readable with YouTube's autogenerated English subs.

youtube.com/watch?v=sqxR8zscSD

hollo.social/@hongminhee/0195a

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Getting back to development today! Working on optimizing the outgoing activity queue to improve response times. Currently focusing on reducing latency when sending posts to large follower counts—should make the whole publishing experience feel much snappier.

https://github.com/fedify-dev/fedify/issues/220

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

The code behind this would make good developers cry. But I have fun fiddling with it on the weekends, and have learned tons about Vue.js

A webpage displaying a collection of posts organized by authors and tags. It shows a total of 21 bookmarks, with sections for different authors and various tags related to topics like "fediverse," "activitypub," and "mastodon." A linked video is also included at the bottom.
ALT text detailsA webpage displaying a collection of posts organized by authors and tags. It shows a total of 21 bookmarks, with sections for different authors and various tags related to topics like "fediverse," "activitypub," and "mastodon." A linked video is also included at the bottom.
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

What about the Fediverse or Mastodon, etc, frustrates you or confuses you?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

What about the Fediverse or Mastodon, etc, frustrates you or confuses you?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Coming soon in 1.5.0: Smart fan-out for efficient activity delivery!

After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.

As we discussed in our previous post, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.

Our solution? A new two-stage “fan-out” approach:

  1. When you call Context.sendActivity(), we'll now enqueue just one consolidated message containing your activity payload and recipient list
  2. A background worker then processes this message and re-enqueues individual delivery tasks

The benefits are substantial:

  • Context.sendActivity() returns almost instantly, even for massive follower counts
  • Memory usage is dramatically reduced by avoiding payload duplication
  • UI responsiveness improves since web requests complete quickly
  • The same reliability for individual deliveries is maintained

For developers with specific needs, we're adding a fanout option with three settings:

  • "auto" (default): Uses fanout for large recipient lists, direct delivery for small ones
  • "skip": Bypasses fanout when you need different payload per recipient
  • "force": Always uses fanout even with few recipients
// Example with custom fanout setting
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "skip" }  // Directly enqueues individual messages
);

This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!

For more details, check out our docs.

What other optimizations would you like to see in future Fedify releases?

Flowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery.

The current approach shows:

1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck)
2. These individual messages are queued in outbox
3. Messages are processed independently
4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The fan-out approach shows:

1. sendActivity creates a single message with multiple recipients
2. This single message is queued in fan-out queue (marked as providing quick response)
3. A background worker processes the fan-out message
4. The worker re-enqueues individual messages in outbox
5. These are then processed independently
6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server)

The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
ALT text detailsFlowchart comparing Fedify's current approach versus the new fan-out approach for activity delivery. The current approach shows: 1. sendActivity calls create separate messages for each recipient (marked as a response time bottleneck) 2. These individual messages are queued in outbox 3. Messages are processed independently 4. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The fan-out approach shows: 1. sendActivity creates a single message with multiple recipients 2. This single message is queued in fan-out queue (marked as providing quick response) 3. A background worker processes the fan-out message 4. The worker re-enqueues individual messages in outbox 5. These are then processed independently 6. Three delivery outcomes: Recipient 1 (fast delivery), Recipient 2 (fast delivery), and Recipient 3 (slow server) The diagram highlights how the fan-out approach moves the heavy processing out of the response path, providing faster API response times while maintaining the same delivery characteristics.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

What about the Fediverse or Mastodon, etc, frustrates you or confuses you?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've been working on adding custom background task support to as planned for version 1.5.0. After diving deeper into implementation, we've realized this is a more substantial undertaking than initially anticipated.

The feature would require significant API changes that would be too disruptive for a minor version update. Therefore, we've decided to postpone this feature to Fedify 2.0.0.

This allows us to:

  • Design a more robust and flexible worker architecture
  • Ensure better integration with existing task queue systems
  • Properly document the new APIs without rushing

We believe this decision will result in a more stable and well-designed feature that better serves your needs. However, some smaller improvements from our work that don't require API changes will still be included in Fedify 1.5.0 or subsequent minor updates.

We appreciate your understanding and continued support.

If you have specific use cases or requirements for background task support, please share them in our GitHub issue. Your input will help shape this feature for 2.0.0.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've been working on adding custom background task support to as planned for version 1.5.0. After diving deeper into implementation, we've realized this is a more substantial undertaking than initially anticipated.

The feature would require significant API changes that would be too disruptive for a minor version update. Therefore, we've decided to postpone this feature to Fedify 2.0.0.

This allows us to:

  • Design a more robust and flexible worker architecture
  • Ensure better integration with existing task queue systems
  • Properly document the new APIs without rushing

We believe this decision will result in a more stable and well-designed feature that better serves your needs. However, some smaller improvements from our work that don't require API changes will still be included in Fedify 1.5.0 or subsequent minor updates.

We appreciate your understanding and continued support.

If you have specific use cases or requirements for background task support, please share them in our GitHub issue. Your input will help shape this feature for 2.0.0.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Getting back to development today! Working on optimizing the outgoing activity queue to improve response times. Currently focusing on reducing latency when sending posts to large follower counts—should make the whole publishing experience feel much snappier.

https://github.com/fedify-dev/fedify/issues/220

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Getting back to development today! Working on optimizing the outgoing activity queue to improve response times. Currently focusing on reducing latency when sending posts to large follower counts—should make the whole publishing experience feel much snappier.

https://github.com/fedify-dev/fedify/issues/220

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've been working on adding custom background task support to as planned for version 1.5.0. After diving deeper into implementation, we've realized this is a more substantial undertaking than initially anticipated.

The feature would require significant API changes that would be too disruptive for a minor version update. Therefore, we've decided to postpone this feature to Fedify 2.0.0.

This allows us to:

  • Design a more robust and flexible worker architecture
  • Ensure better integration with existing task queue systems
  • Properly document the new APIs without rushing

We believe this decision will result in a more stable and well-designed feature that better serves your needs. However, some smaller improvements from our work that don't require API changes will still be included in Fedify 1.5.0 or subsequent minor updates.

We appreciate your understanding and continued support.

If you have specific use cases or requirements for background task support, please share them in our GitHub issue. Your input will help shape this feature for 2.0.0.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've been working on adding custom background task support to as planned for version 1.5.0. After diving deeper into implementation, we've realized this is a more substantial undertaking than initially anticipated.

The feature would require significant API changes that would be too disruptive for a minor version update. Therefore, we've decided to postpone this feature to Fedify 2.0.0.

This allows us to:

  • Design a more robust and flexible worker architecture
  • Ensure better integration with existing task queue systems
  • Properly document the new APIs without rushing

We believe this decision will result in a more stable and well-designed feature that better serves your needs. However, some smaller improvements from our work that don't require API changes will still be included in Fedify 1.5.0 or subsequent minor updates.

We appreciate your understanding and continued support.

If you have specific use cases or requirements for background task support, please share them in our GitHub issue. Your input will help shape this feature for 2.0.0.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've been working on adding custom background task support to as planned for version 1.5.0. After diving deeper into implementation, we've realized this is a more substantial undertaking than initially anticipated.

The feature would require significant API changes that would be too disruptive for a minor version update. Therefore, we've decided to postpone this feature to Fedify 2.0.0.

This allows us to:

  • Design a more robust and flexible worker architecture
  • Ensure better integration with existing task queue systems
  • Properly document the new APIs without rushing

We believe this decision will result in a more stable and well-designed feature that better serves your needs. However, some smaller improvements from our work that don't require API changes will still be included in Fedify 1.5.0 or subsequent minor updates.

We appreciate your understanding and continued support.

If you have specific use cases or requirements for background task support, please share them in our GitHub issue. Your input will help shape this feature for 2.0.0.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Patch releases for versions 1.0.21, 1.1.18, 1.2.18, 1.3.14, and 1.4.7 are now available. These updates address two important bugs across all supported release lines:

  1. Fixed a WebFinger handler bug that prevented matching acct: URIs with port numbers in the host. Thanks to @revathskumar for reporting and debugging the bug!
  2. Resolved server errors that occurred when invalid URLs were passed to the base-url parameter of followers collections.

We recommend all users upgrade to these latest patch versions for improved stability and federation compatibility.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Patch releases for versions 1.0.21, 1.1.18, 1.2.18, 1.3.14, and 1.4.7 are now available. These updates address two important bugs across all supported release lines:

  1. Fixed a WebFinger handler bug that prevented matching acct: URIs with port numbers in the host. Thanks to @revathskumar for reporting and debugging the bug!
  2. Resolved server errors that occurred when invalid URLs were passed to the base-url parameter of followers collections.

We recommend all users upgrade to these latest patch versions for improved stability and federation compatibility.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Patch releases for versions 1.0.21, 1.1.18, 1.2.18, 1.3.14, and 1.4.7 are now available. These updates address two important bugs across all supported release lines:

  1. Fixed a WebFinger handler bug that prevented matching acct: URIs with port numbers in the host. Thanks to @revathskumar for reporting and debugging the bug!
  2. Resolved server errors that occurred when invalid URLs were passed to the base-url parameter of followers collections.

We recommend all users upgrade to these latest patch versions for improved stability and federation compatibility.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Patch releases for versions 1.0.21, 1.1.18, 1.2.18, 1.3.14, and 1.4.7 are now available. These updates address two important bugs across all supported release lines:

  1. Fixed a WebFinger handler bug that prevented matching acct: URIs with port numbers in the host. Thanks to @revathskumar for reporting and debugging the bug!
  2. Resolved server errors that occurred when invalid URLs were passed to the base-url parameter of followers collections.

We recommend all users upgrade to these latest patch versions for improved stability and federation compatibility.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Patch releases for versions 1.0.21, 1.1.18, 1.2.18, 1.3.14, and 1.4.7 are now available. These updates address two important bugs across all supported release lines:

  1. Fixed a WebFinger handler bug that prevented matching acct: URIs with port numbers in the host. Thanks to @revathskumar for reporting and debugging the bug!
  2. Resolved server errors that occurred when invalid URLs were passed to the base-url parameter of followers collections.

We recommend all users upgrade to these latest patch versions for improved stability and federation compatibility.

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

A collection of silly Mastodon apps (the best kind). It includes a Fax-To-Mastodon app. :omgdotlol:

halcy.de/blog/2025/03/18/silly

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

A collection of silly Mastodon apps (the best kind). It includes a Fax-To-Mastodon app. :omgdotlol:

halcy.de/blog/2025/03/18/silly

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

A collection of silly Mastodon apps (the best kind). It includes a Fax-To-Mastodon app. :omgdotlol:

halcy.de/blog/2025/03/18/silly

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

今回、@lqez さんの『我々のコードを求めて』というYouTubeに出演させていただき、 等についてお話させていただきました。日本語字幕が用意されていますので、FedifyやHolloの開発秘話などが気になる方はぜひご覧ください!

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Just noticed this "Open in the application? " banner on @framasoft's "What is the fediverse" @peertube video and I have the app installed thru @fdroidorg but it takes me to the Google Play download page for it instead of opening it in the app. Makes for a really bad fediverse experience, we need to figure out these sorts of flows and make sure they reliably work.

A screenshot of a peertube video
ALT text detailsA screenshot of a peertube video
A screenshot of peertube on Google Play
ALT text detailsA screenshot of peertube on Google Play
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

What about the Fediverse or Mastodon, etc, frustrates you or confuses you?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

()@lqez 님의 《우리의 코드를 찾아서》에 出演(출연)하여 , , , ()()해 이야기를 나눴습니다. Fedify와 Hollo의 開發(개발) 祕話(비화) 같은 게 궁금하시다면 한 () 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ

https://www.youtube.com/watch?v=sqxR8zscSDo

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Good overview of JSON-LD

digitalcourage.video/w/jUKxSj7

Light

@light@noc.social · Reply to Light's post

Light

@light@noc.social · Reply to Light's post

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

I set up a web-site for GreatApe.

greata.pe/

A URL I can use when I talk about GreatApe.

Until now, it was just the GitHub repos. Now, GreatApe has its own web-site.

For now, it is very basic. More needs to be added to it.

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

in my dream last night @peertube announced support for fediverse:creator tags attached to channels

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

大部分(대부분) 具顯(구현)들이 NoteArticle內容(내용) (content) 안에서 누군가 다른 액터를 멘션할 境遇(경우) tag 屬性(속성)으로 該當(해당)하는 Mention 客體(객체)들을 包含(포함)시킵니다. 그러면 Person, Group () 액터 客體(객체)들도 略歷(약력) (summary) 안에서 누군가 다른 액터를 멘션할 境遇(경우) tag 屬性(속성)으로 該當(해당)하는 Mention 客體(객체)들을 包含(포함)해야 할까요? 或是(혹시) 이미 그렇게 動作(동작)하는 具顯(구현)이 있을까요? (Mastodon은 確認(확인)해 본 結果(결과) 包含(포함)시키지 않는 것 같습니다만.) 어떻게 보시나요?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

殆どのActivityPub実装では、NoteArticleの内容(content)内で他のアクター(actor)に言及(メンション)する場合、tag属性に該当するMentionオブジェクトを含めています。では、PersonGroupなどのアクターオブジェクトも、自己紹介(summary)内で他のアクターに言及する場合、tag属性に該当するMentionオブジェクトを含めるべきでしょうか?既にその様に動作している実装はあるでしょうか?(Mastodonは確認した結果、含めていない様です。)どの様にお考えですか?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

大部分(대부분) 具顯(구현)들이 NoteArticle內容(내용) (content) 안에서 누군가 다른 액터를 멘션할 境遇(경우) tag 屬性(속성)으로 該當(해당)하는 Mention 客體(객체)들을 包含(포함)시킵니다. 그러면 Person, Group () 액터 客體(객체)들도 略歷(약력) (summary) 안에서 누군가 다른 액터를 멘션할 境遇(경우) tag 屬性(속성)으로 該當(해당)하는 Mention 客體(객체)들을 包含(포함)해야 할까요? 或是(혹시) 이미 그렇게 動作(동작)하는 具顯(구현)이 있을까요? (Mastodon은 確認(확인)해 본 結果(결과) 包含(포함)시키지 않는 것 같습니다만.) 어떻게 보시나요?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

殆どのActivityPub実装では、NoteArticleの内容(content)内で他のアクター(actor)に言及(メンション)する場合、tag属性に該当するMentionオブジェクトを含めています。では、PersonGroupなどのアクターオブジェクトも、自己紹介(summary)内で他のアクターに言及する場合、tag属性に該当するMentionオブジェクトを含めるべきでしょうか?既にその様に動作している実装はあるでしょうか?(Mastodonは確認した結果、含めていない様です。)どの様にお考えですか?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

大部分(대부분) 具顯(구현)들이 NoteArticle內容(내용) (content) 안에서 누군가 다른 액터를 멘션할 境遇(경우) tag 屬性(속성)으로 該當(해당)하는 Mention 客體(객체)들을 包含(포함)시킵니다. 그러면 Person, Group () 액터 客體(객체)들도 略歷(약력) (summary) 안에서 누군가 다른 액터를 멘션할 境遇(경우) tag 屬性(속성)으로 該當(해당)하는 Mention 客體(객체)들을 包含(포함)해야 할까요? 或是(혹시) 이미 그렇게 動作(동작)하는 具顯(구현)이 있을까요? (Mastodon은 確認(확인)해 본 結果(결과) 包含(포함)시키지 않는 것 같습니다만.) 어떻게 보시나요?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Most 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?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Got an interesting question today about 's outgoing design!

Some users noticed we create separate queue messages for each recipient inbox rather than queuing a single message and handling the splitting later. There's a good reason for this approach.

In the , server response times vary dramatically—some respond quickly, others slowly, and some might be temporarily down. If we processed deliveries in a single task, the entire batch would be held up by the slowest server in the group.

By creating individual queue items for each recipient:

  • Fast servers get messages delivered promptly
  • Slow servers don't delay delivery to others
  • Failed deliveries can be retried independently
  • Your UI remains responsive while deliveries happen in the background

It's a classic trade-off: we generate more queue messages, but gain better resilience and user experience in return.

This is particularly important in federated networks where server behavior is unpredictable and outside our control. We'd rather optimize for making sure your posts reach their destinations as quickly as possible!

What other aspects of Fedify's design would you like to hear about? Let us know!

A flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
ALT text detailsA flowchart comparing two approaches to message queue design. The top half shows “Fedify's Current Approach” where a single sendActivity call creates separate messages for each recipient, which are individually queued and processed independently. This results in fast delivery to working recipients while slow servers only affect their own delivery. The bottom half shows an “Alternative Approach” where sendActivity creates a single message with multiple recipients, queued as one item, and processed sequentially. This results in all recipients waiting for each delivery to complete, with slow servers blocking everyone in the queue.
Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

Just published a post about Hackers' Pub's unique username change policy! Unlike most platforms, they allow a one-time username change while preserving your connections and content history. It's all possible thanks to some clever implementation using UUID-based actor URIs instead of username-based ones. If you're interested in trying it out, the platform is currently in invitation-only beta—check the post for details on how to request access!

https://hackers.pub/@hongminhee/2025/hackers-pub-introduces-flexible-username-changes

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

Hackers' Pub is a community-focused platform where programmers and technology enthusiasts share knowledge and experiences. As an ActivityPub-enabled social network, it allows users to connect with others across the broader fediverse ecosystem, bringing technical discussions and insights directly to followers' feeds.

In the fediverse landscape, your username is typically set in stone once chosen. Most ActivityPub-powered platforms like Mastodon, Pleroma, and others enforce this permanence as a fundamental design principle. However, Hackers' Pub is charting a different course with a more flexible approach to digital identity.

One-Time Username Change: Freedom with Responsibility

Unlike most fediverse platforms, Hackers' Pub now allows users to change their username (the part before the @ in your Fediverse handle) exactly once during the lifetime of their account. This policy acknowledges that people grow, interests evolve, and the username that seemed perfect when you joined might not represent who you are today.

This one-time change limit strikes a careful balance—offering flexibility while maintaining the stability and reliability that's essential for a federated network.

Username Recycling: New Opportunities

When you change your username on Hackers' Pub, your previous username becomes available for other users to claim. This recycling mechanism creates new opportunities for meaningful usernames to find their most fitting owners, rather than remaining permanently locked to accounts that no longer use them.

For newcomers to the platform, this means a wider selection of desirable usernames might become available over time—something virtually unheard of in the traditional fediverse ecosystem.

Worried about broken links after changing your username? Hackers' Pub has implemented a thoughtful solution. All permalinks containing your original username will continue to function until someone else claims that username. This approach helps preserve the web of connections and conversations that make the fediverse valuable.

This temporary preservation period gives your connections time to adjust to your new identity while preventing immediate link rot across the federation.

The Technical Foundation: ActivityPub Actor URIs

What enables Hackers' Pub to offer username changes while other fediverse platforms can't? The answer lies in how actor identities are implemented at the protocol level.

Hackers' Pub uses UUID-based actor URIs that don't contain the username. For example, a user with handle @hongminhee has an underlying ActivityPub actor URI that looks like https://hackers.pub/ap/actors/019382d3-63d7-7cf7-86e8-91e2551c306c. Since the username isn't part of this permanent identifier, it can be changed without breaking federation connections.

This contrasts sharply with platforms like Mastodon, where a user @hongminhee has an actor URI of https://mastodon.social/users/hongminhee. With the username embedded directly in the URI, changing it would break all federation connections, which is why these platforms don't allow username changes.

This architectural choice gives Hackers' Pub the technical flexibility to implement username changes while maintaining account continuity across the fediverse.

GitHub-Inspired Approach

Those familiar with GitHub might recognize this model—Hackers' Pub has adapted GitHub's username change policy for the fediverse context. This approach brings the best of both worlds: the option for identity evolution from centralized platforms and the federation benefits of the fediverse.

What This Means for Users

For Hackers' Pub users, this policy offers a significant advantage over other fediverse instances:

  • You can correct an unfortunate username choice
  • Your online identity can evolve as you do
  • Your content history remains intact during the transition
  • You maintain your social connections despite the change

The Future of Fediverse Identity

Hackers' Pub's username policy represents an interesting experiment in the fediverse—testing whether more flexible identity management can coexist with the stability needed for federation. If successful, we might see other platforms adopt similar approaches, creating a more adaptable yet still interconnected social web.

For now, users should consider this policy a compelling reason to choose Hackers' Pub as their fediverse home, especially if username flexibility matters to their online experience.


Hackers' Pub is currently in invitation-only beta. If you're interested in trying out the platform and its unique username policy, please leave your email address in the comments below. We'll add you to the allowlist, enabling you to sign up directly on the website. Note that this doesn't involve sending invitation emails—your address will simply be approved for registration when you visit the signup page.

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

I'm finally unveiling the project that has been consuming my weekends: Encyclia, an bridge that will make ORCID records followable and interactable on the fediverse. 🙂

It's early-stage and the ORCID following function is not publicly available yet. We're seeking community feedback on functionality and safety aspects. Read more at encyclia.pub or follow @encyclia for news!

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

in my dream last night @peertube announced support for fediverse:creator tags attached to channels

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries

we now have some GoToSocial docs about importing your archived posts in general: https://docs.gotosocial.org/en/latest/user_guide/importing_posts/

most of the specifics are in the slurp docs, but if you write your own importer and think it might be of general interest to GTS users, please let us know.

#GoToSocial #GTS #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries

we now have some GoToSocial docs about importing your archived posts in general: https://docs.gotosocial.org/en/latest/user_guide/importing_posts/

most of the specifics are in the slurp docs, but if you write your own importer and think it might be of general interest to GTS users, please let us know.

#GoToSocial #GTS #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries

we now have some GoToSocial docs about importing your archived posts in general: https://docs.gotosocial.org/en/latest/user_guide/importing_posts/

most of the specifics are in the slurp docs, but if you write your own importer and think it might be of general interest to GTS users, please let us know.

#GoToSocial #GTS #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries

we now have some GoToSocial docs about importing your archived posts in general: https://docs.gotosocial.org/en/latest/user_guide/importing_posts/

most of the specifics are in the slurp docs, but if you write your own importer and think it might be of general interest to GTS users, please let us know.

#GoToSocial #GTS #FediDev

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering packaging the Fedify CLI for Homebrew to make installation easier on macOS and Linux (via Linuxbrew).

Would you use a formula for CLI?

OptionVoters
Yes, I'd definitely use it on macOS.8 (32%)
Yes, I'd definitely use it on Linux.3 (12%)
Maybe, depending on the implementation.4 (16%)
No, I prefer other installation methods.10 (40%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

If you answered “No”, which installation method do you prefer?

Your feedback helps us prioritize distribution channels! Thanks for contributing to the Fedify ecosystem.

OptionVoters
npm3 (25%)
Deno3 (25%)
Manual download5 (42%)
Other (please specify in replies)1 (8%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering packaging the Fedify CLI for Homebrew to make installation easier on macOS and Linux (via Linuxbrew).

Would you use a formula for CLI?

OptionVoters
Yes, I'd definitely use it on macOS.8 (32%)
Yes, I'd definitely use it on Linux.3 (12%)
Maybe, depending on the implementation.4 (16%)
No, I prefer other installation methods.10 (40%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering packaging the Fedify CLI for Homebrew to make installation easier on macOS and Linux (via Linuxbrew).

Would you use a formula for CLI?

OptionVoters
Yes, I'd definitely use it on macOS.8 (32%)
Yes, I'd definitely use it on Linux.3 (12%)
Maybe, depending on the implementation.4 (16%)
No, I prefer other installation methods.10 (40%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

If you answered “No”, which installation method do you prefer?

Your feedback helps us prioritize distribution channels! Thanks for contributing to the Fedify ecosystem.

OptionVoters
npm3 (25%)
Deno3 (25%)
Manual download5 (42%)
Other (please specify in replies)1 (8%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

If you answered “No”, which installation method do you prefer?

Your feedback helps us prioritize distribution channels! Thanks for contributing to the Fedify ecosystem.

OptionVoters
npm3 (25%)
Deno3 (25%)
Manual download5 (42%)
Other (please specify in replies)1 (8%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering packaging the Fedify CLI for Homebrew to make installation easier on macOS and Linux (via Linuxbrew).

Would you use a formula for CLI?

OptionVoters
Yes, I'd definitely use it on macOS.8 (32%)
Yes, I'd definitely use it on Linux.3 (12%)
Maybe, depending on the implementation.4 (16%)
No, I prefer other installation methods.10 (40%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

If you answered “No”, which installation method do you prefer?

Your feedback helps us prioritize distribution channels! Thanks for contributing to the Fedify ecosystem.

OptionVoters
npm3 (25%)
Deno3 (25%)
Manual download5 (42%)
Other (please specify in replies)1 (8%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering packaging the Fedify CLI for Homebrew to make installation easier on macOS and Linux (via Linuxbrew).

Would you use a formula for CLI?

OptionVoters
Yes, I'd definitely use it on macOS.8 (32%)
Yes, I'd definitely use it on Linux.3 (12%)
Maybe, depending on the implementation.4 (16%)
No, I prefer other installation methods.10 (40%)
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

A good file-extension for ActivityPub / ActivityStream files might be:

.activity

And maybe also:

.jsonactivity

Those could be used to trigger a web-server to respond with the Content-Type "application/activity+json".

.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

.json isn't sufficient, since it would produce a Content-Type of "application/json" rather than "application/activity+json".

ActivityPub / ActivityStream files need their own file-extension.

...

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

A file-extension for ActivityPub /ActivityStream files.

...

On many web-servers, the Content-Type returned when serving a file is based on the file-extension of the file.

Ex: .txt for text files, .gz for gzip files, .gmni for gemtext files, etc.

I am not aware of a widely used file-extension for ActivityStreams / ActivityPub files.

...

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

4/

This needs some testing to see what extant Fediverse software actually does.

For example — with the extant Fediverse software —

Does the avatar image, the (actor) name, etc show up with the post?

Does the post show up?

Etc?

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

Now, this would probably break like counts, share counts, a replies to some degree.

But, if you didn't care about that, I think it should work.

...

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

For example, at:

http;//example·com/object/123

You might have the activity-JSON (application/activity+json):

{

....

"attributedTo": "https;//mastodon·social/users/reiver",

...

}

I.e., a Note or Article or whatever is saying that the author is NOT an actor on the same server host (example·com), but an actor over on the server host mastodon·social.

...

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

You could have a post on one server host attribute and account on another server host as its author.

All you have to do is set the "attributedTo" field appropriately.

w3.org/TR/activitystreams-voca

For example....

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

ActivityPub outboxes are the new RSS / Atom / WebFeed.

You can just read from them to get a JSON feed of someone's posts.

I.e., you do NOT have to implement the full suite of Fediverse protocols, or Follow, or run your own server, or anything else to get someone's posts on the Fediverse — just read from their outbox.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

ActivityPub outboxes are the new RSS / Atom / WebFeed.

You can just read from them to get a JSON feed of someone's posts.

I.e., you do NOT have to implement the full suite of Fediverse protocols, or Follow, or run your own server, or anything else to get someone's posts on the Fediverse — just read from their outbox.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

ActivityPub & ActivityStreams are based on JSON-LD — a format that is not (non-programmer) human-legible & human-writable

Maybe we need an alternative way of encoding ActivityPub & ActivityStreams in situations where (non-programmer) humans might read it or write it

Maybe the INI file data format? Or something else that is friendly to (non-programmer) humans?

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

I agree that an open protocol is better and more important than just an application.

But I also think that an open file data format is better and more important than just an open protocol.

I.e.,:

file data format ≫ protocol ≫ app

...

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

JSON-LD is not (non-programmer) human-legible format because — JSON is not (non-programmer) human-legible format.

JSON-LD and JSON are both also not (non-programmer) human-writable.

...

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

ActivityPub outboxes are the new RSS / Atom / WebFeed.

You can just read from them to get a JSON feed of someone's posts.

I.e., you do NOT have to implement the full suite of Fediverse protocols, or Follow, or run your own server, or anything else to get someone's posts on the Fediverse — just read from their outbox.

BeBo's avatar
BeBo

@aslmewes@ruhr.social

Are there any good for small teams outside?

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

ActivityPub outboxes are the new RSS / Atom / WebFeed.

You can just read from them to get a JSON feed of someone's posts.

I.e., you do NOT have to implement the full suite of Fediverse protocols, or Follow, or run your own server, or anything else to get someone's posts on the Fediverse — just read from their outbox.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

What if a (new type of) Fediverse server automagically created an ActivityPub actor for each hash-tag.

So, for example, if someone on the server used:

⋕banana

(Then if the domain of the server is "example.com") then we would automagically have the actor:

@banana@example·com

Probably a group actor.

And it boosted any local post with that hash-tag.

Then you could follow a hash-tag on a server.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

ActivityPub outboxes are the new RSS / Atom / WebFeed.

You can just read from them to get a JSON feed of someone's posts.

I.e., you do NOT have to implement the full suite of Fediverse protocols, or Follow, or run your own server, or anything else to get someone's posts on the Fediverse — just read from their outbox.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

This feels so wasteful —

Including the same content twice — once in "content" and again in "contentMap".

  "content": "<p><a href=\"https://mastodon.social/tags/GreatApe\" class=\"mention hashtag\" rel=\"tag\">#<span>GreatApe</span></a></p><p>.</p>",
  "contentMap": {
    "en": "<p><a href=\"https://mastodon.social/tags/GreatApe\" class=\"mention hashtag\" rel=\"tag\">#<span>GreatApe</span></a></p><p>.</p>"
  },
ALT text details "content": "<p><a href=\"https://mastodon.social/tags/GreatApe\" class=\"mention hashtag\" rel=\"tag\">#<span>GreatApe</span></a></p><p>.</p>", "contentMap": { "en": "<p><a href=\"https://mastodon.social/tags/GreatApe\" class=\"mention hashtag\" rel=\"tag\">#<span>GreatApe</span></a></p><p>.</p>" },
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

BeBo's avatar
BeBo

@aslmewes@ruhr.social

Are there any good for small teams outside?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Fedifyの関連プロジェクトをご紹介したいと思います。ActivityPubアプリケーション開発をより簡単にするツール群です:

Fedify :fedify:

Fedify@fedify)はActivityPubやその他のフェディバース標準を活用する連合型サーバーアプリケーションを構築するためのTypeScriptライブラリです。Activity Vocabularyの型安全なオブジェクト、WebFingerクライアント・サーバー、HTTP Signaturesなどを提供し、ボイラープレートコードを削減してアプリケーションロジックに集中できるようにします。

Hollo :hollo:

Hollo@hollo)はFedifyで動作するお一人様用マイクロブログサーバーです。個人向けに設計されていますが、ActivityPubを通じて完全に連合化されており、フェディバース全体のユーザーと交流することができます。HolloはMastodon互換APIを実装しているため、独自のウェブインターフェースがなくても、ほとんどのMastodonクライアントと互換性があります。

Holloはまた、正式リリース前の最新Fedify機能をテストする実験場としても活用されています。

BotKit :botkit:

BotKit@botkit)は私たちの最も新しいメンバーで、ActivityPubボットを作成するために特別に設計されたフレームワークです。従来のMastodonボットとは異なり、BotKitはプラットフォーム固有の制限(文字数制限など)に縛られない独立したActivityPubサーバーを作成します。

BotKitのAPIは意図的にシンプルに設計されており、単一のTypeScriptファイルで完全なボットを作成できます!


これら三つのプロジェクトはすべて@fedify-dev GitHubオーガニゼーションでオープンソースとして公開されています。それぞれ異なる目的を持っていますが、ActivityPub開発をより身近にし、フェディバースのエコシステムを拡大するという共通の目標を共有しています。

これらのプロジェクトを試してみたり、開発に貢献したりすることに興味がある場合は、以下をご覧ください:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce two major features coming in 1.5.0, focused on giving you more control over domain names in your federated apps:

Separate WebFinger Host from Server Origin

Want different domains for your WebFinger handles and server URIs? Fedify 1.5.0 will let you use domains like @alice@example.com as fediverse handles while serving content from https://ap.example.com. This gives you more flexibility in how you structure your federated services.

Canonical Origin Support

Need to ensure consistent URLs across your infrastructure? The new canonical origin support lets you explicitly set your server's authoritative domain. This is particularly useful when running behind reverse proxies or load balancers—no more unexpected URLs generated from internal hostnames.


These features represent our ongoing commitment to making Fedify more flexible and production-ready.

Can't wait to try these features? You can experiment with them today using our unstable release v1.5.0-dev.680+562e3dc0 (JSR & npm). Keep in mind that this is an unstable release intended for testing—use it in production at your own risk.

Otherwise, stay tuned for the stable Fedify 1.5.0 release!

Separating WebFinger host from the server origin

This API is available since Fedify 1.5.0.

Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle.

In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object:

const federation = createFederation({
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
});

NOTE

Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized.

In the above example, two fediverse handles are recognized as the same:

• @alice@example.com
• @alice@ap.example.com
ALT text detailsSeparating WebFinger host from the server origin This API is available since Fedify 1.5.0. Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle. In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object: const federation = createFederation({ origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, }); NOTE Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized. In the above example, two fediverse handles are recognized as the same: • @alice@example.com • @alice@ap.example.com
Explicitly setting the canonical origin

This API is available since Fedify 1.5.0.

Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin.

For example, if you want to set the canonical origin to https://example.com, you can pass the string:

const federation = createFederation({
  origin: "https://example.com",
});

NOTE

The origin option has to include the leading https:// or http:// scheme.

Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer.

CAUTION

For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
ALT text detailsExplicitly setting the canonical origin This API is available since Fedify 1.5.0. Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin. For example, if you want to set the canonical origin to https://example.com, you can pass the string: const federation = createFederation({ origin: "https://example.com", }); NOTE The origin option has to include the leading https:// or http:// scheme. Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer. CAUTION For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce two major features coming in 1.5.0, focused on giving you more control over domain names in your federated apps:

Separate WebFinger Host from Server Origin

Want different domains for your WebFinger handles and server URIs? Fedify 1.5.0 will let you use domains like @alice@example.com as fediverse handles while serving content from https://ap.example.com. This gives you more flexibility in how you structure your federated services.

Canonical Origin Support

Need to ensure consistent URLs across your infrastructure? The new canonical origin support lets you explicitly set your server's authoritative domain. This is particularly useful when running behind reverse proxies or load balancers—no more unexpected URLs generated from internal hostnames.


These features represent our ongoing commitment to making Fedify more flexible and production-ready.

Can't wait to try these features? You can experiment with them today using our unstable release v1.5.0-dev.680+562e3dc0 (JSR & npm). Keep in mind that this is an unstable release intended for testing—use it in production at your own risk.

Otherwise, stay tuned for the stable Fedify 1.5.0 release!

Separating WebFinger host from the server origin

This API is available since Fedify 1.5.0.

Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle.

In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object:

const federation = createFederation({
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
});

NOTE

Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized.

In the above example, two fediverse handles are recognized as the same:

• @alice@example.com
• @alice@ap.example.com
ALT text detailsSeparating WebFinger host from the server origin This API is available since Fedify 1.5.0. Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle. In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object: const federation = createFederation({ origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, }); NOTE Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized. In the above example, two fediverse handles are recognized as the same: • @alice@example.com • @alice@ap.example.com
Explicitly setting the canonical origin

This API is available since Fedify 1.5.0.

Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin.

For example, if you want to set the canonical origin to https://example.com, you can pass the string:

const federation = createFederation({
  origin: "https://example.com",
});

NOTE

The origin option has to include the leading https:// or http:// scheme.

Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer.

CAUTION

For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
ALT text detailsExplicitly setting the canonical origin This API is available since Fedify 1.5.0. Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin. For example, if you want to set the canonical origin to https://example.com, you can pass the string: const federation = createFederation({ origin: "https://example.com", }); NOTE The origin option has to include the leading https:// or http:// scheme. Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer. CAUTION For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce two major features coming in 1.5.0, focused on giving you more control over domain names in your federated apps:

Separate WebFinger Host from Server Origin

Want different domains for your WebFinger handles and server URIs? Fedify 1.5.0 will let you use domains like @alice@example.com as fediverse handles while serving content from https://ap.example.com. This gives you more flexibility in how you structure your federated services.

Canonical Origin Support

Need to ensure consistent URLs across your infrastructure? The new canonical origin support lets you explicitly set your server's authoritative domain. This is particularly useful when running behind reverse proxies or load balancers—no more unexpected URLs generated from internal hostnames.


These features represent our ongoing commitment to making Fedify more flexible and production-ready.

Can't wait to try these features? You can experiment with them today using our unstable release v1.5.0-dev.680+562e3dc0 (JSR & npm). Keep in mind that this is an unstable release intended for testing—use it in production at your own risk.

Otherwise, stay tuned for the stable Fedify 1.5.0 release!

Separating WebFinger host from the server origin

This API is available since Fedify 1.5.0.

Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle.

In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object:

const federation = createFederation({
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
});

NOTE

Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized.

In the above example, two fediverse handles are recognized as the same:

• @alice@example.com
• @alice@ap.example.com
ALT text detailsSeparating WebFinger host from the server origin This API is available since Fedify 1.5.0. Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle. In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object: const federation = createFederation({ origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, }); NOTE Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized. In the above example, two fediverse handles are recognized as the same: • @alice@example.com • @alice@ap.example.com
Explicitly setting the canonical origin

This API is available since Fedify 1.5.0.

Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin.

For example, if you want to set the canonical origin to https://example.com, you can pass the string:

const federation = createFederation({
  origin: "https://example.com",
});

NOTE

The origin option has to include the leading https:// or http:// scheme.

Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer.

CAUTION

For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
ALT text detailsExplicitly setting the canonical origin This API is available since Fedify 1.5.0. Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin. For example, if you want to set the canonical origin to https://example.com, you can pass the string: const federation = createFederation({ origin: "https://example.com", }); NOTE The origin option has to include the leading https:// or http:// scheme. Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer. CAUTION For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce two major features coming in 1.5.0, focused on giving you more control over domain names in your federated apps:

Separate WebFinger Host from Server Origin

Want different domains for your WebFinger handles and server URIs? Fedify 1.5.0 will let you use domains like @alice@example.com as fediverse handles while serving content from https://ap.example.com. This gives you more flexibility in how you structure your federated services.

Canonical Origin Support

Need to ensure consistent URLs across your infrastructure? The new canonical origin support lets you explicitly set your server's authoritative domain. This is particularly useful when running behind reverse proxies or load balancers—no more unexpected URLs generated from internal hostnames.


These features represent our ongoing commitment to making Fedify more flexible and production-ready.

Can't wait to try these features? You can experiment with them today using our unstable release v1.5.0-dev.680+562e3dc0 (JSR & npm). Keep in mind that this is an unstable release intended for testing—use it in production at your own risk.

Otherwise, stay tuned for the stable Fedify 1.5.0 release!

Separating WebFinger host from the server origin

This API is available since Fedify 1.5.0.

Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle.

In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object:

const federation = createFederation({
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
});

NOTE

Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized.

In the above example, two fediverse handles are recognized as the same:

• @alice@example.com
• @alice@ap.example.com
ALT text detailsSeparating WebFinger host from the server origin This API is available since Fedify 1.5.0. Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle. In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object: const federation = createFederation({ origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, }); NOTE Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized. In the above example, two fediverse handles are recognized as the same: • @alice@example.com • @alice@ap.example.com
Explicitly setting the canonical origin

This API is available since Fedify 1.5.0.

Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin.

For example, if you want to set the canonical origin to https://example.com, you can pass the string:

const federation = createFederation({
  origin: "https://example.com",
});

NOTE

The origin option has to include the leading https:// or http:// scheme.

Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer.

CAUTION

For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
ALT text detailsExplicitly setting the canonical origin This API is available since Fedify 1.5.0. Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin. For example, if you want to set the canonical origin to https://example.com, you can pass the string: const federation = createFederation({ origin: "https://example.com", }); NOTE The origin option has to include the leading https:// or http:// scheme. Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer. CAUTION For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce two major features coming in 1.5.0, focused on giving you more control over domain names in your federated apps:

Separate WebFinger Host from Server Origin

Want different domains for your WebFinger handles and server URIs? Fedify 1.5.0 will let you use domains like @alice@example.com as fediverse handles while serving content from https://ap.example.com. This gives you more flexibility in how you structure your federated services.

Canonical Origin Support

Need to ensure consistent URLs across your infrastructure? The new canonical origin support lets you explicitly set your server's authoritative domain. This is particularly useful when running behind reverse proxies or load balancers—no more unexpected URLs generated from internal hostnames.


These features represent our ongoing commitment to making Fedify more flexible and production-ready.

Can't wait to try these features? You can experiment with them today using our unstable release v1.5.0-dev.680+562e3dc0 (JSR & npm). Keep in mind that this is an unstable release intended for testing—use it in production at your own risk.

Otherwise, stay tuned for the stable Fedify 1.5.0 release!

Separating WebFinger host from the server origin

This API is available since Fedify 1.5.0.

Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle.

In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object:

const federation = createFederation({
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
});

NOTE

Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized.

In the above example, two fediverse handles are recognized as the same:

• @alice@example.com
• @alice@ap.example.com
ALT text detailsSeparating WebFinger host from the server origin This API is available since Fedify 1.5.0. Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle. In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object: const federation = createFederation({ origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, }); NOTE Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized. In the above example, two fediverse handles are recognized as the same: • @alice@example.com • @alice@ap.example.com
Explicitly setting the canonical origin

This API is available since Fedify 1.5.0.

Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin.

For example, if you want to set the canonical origin to https://example.com, you can pass the string:

const federation = createFederation({
  origin: "https://example.com",
});

NOTE

The origin option has to include the leading https:// or http:// scheme.

Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer.

CAUTION

For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
ALT text detailsExplicitly setting the canonical origin This API is available since Fedify 1.5.0. Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin. For example, if you want to set the canonical origin to https://example.com, you can pass the string: const federation = createFederation({ origin: "https://example.com", }); NOTE The origin option has to include the leading https:// or http:// scheme. Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer. CAUTION For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce two major features coming in 1.5.0, focused on giving you more control over domain names in your federated apps:

Separate WebFinger Host from Server Origin

Want different domains for your WebFinger handles and server URIs? Fedify 1.5.0 will let you use domains like @alice@example.com as fediverse handles while serving content from https://ap.example.com. This gives you more flexibility in how you structure your federated services.

Canonical Origin Support

Need to ensure consistent URLs across your infrastructure? The new canonical origin support lets you explicitly set your server's authoritative domain. This is particularly useful when running behind reverse proxies or load balancers—no more unexpected URLs generated from internal hostnames.


These features represent our ongoing commitment to making Fedify more flexible and production-ready.

Can't wait to try these features? You can experiment with them today using our unstable release v1.5.0-dev.680+562e3dc0 (JSR & npm). Keep in mind that this is an unstable release intended for testing—use it in production at your own risk.

Otherwise, stay tuned for the stable Fedify 1.5.0 release!

Separating WebFinger host from the server origin

This API is available since Fedify 1.5.0.

Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle.

In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object:

const federation = createFederation({
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
});

NOTE

Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized.

In the above example, two fediverse handles are recognized as the same:

• @alice@example.com
• @alice@ap.example.com
ALT text detailsSeparating WebFinger host from the server origin This API is available since Fedify 1.5.0. Sometimes you may want to use different domain names for WebFinger handles (i.e., fediverse handles) and the server origin. For example, you may want to use https://ap.example.com/actors/alice as an actor URI but want to use @alice@example.com as its fediverse handle. In such cases, you can set the handleHost different from the webOrigin in the origin option. The handleHost is used to construct the WebFinger handles, and the webOrigin is used to construct the URLs in the Context object: const federation = createFederation({ origin: { handleHost: "example.com", webOrigin: "https://ap.example.com", }, }); NOTE Even if you set the handleHost different from the webOrigin, the other fediverse handle with the same domain name as the webOrigin will still be recognized. In the above example, two fediverse handles are recognized as the same: • @alice@example.com • @alice@ap.example.com
Explicitly setting the canonical origin

This API is available since Fedify 1.5.0.

Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin.

For example, if you want to set the canonical origin to https://example.com, you can pass the string:

const federation = createFederation({
  origin: "https://example.com",
});

NOTE

The origin option has to include the leading https:// or http:// scheme.

Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer.

CAUTION

For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
ALT text detailsExplicitly setting the canonical origin This API is available since Fedify 1.5.0. Or you can explicitly set the canonical origin of the server by passing the origin option to the createFederation() function. The origin option is either a string or a FederationOrigin object, which consists of two fields: handleHost and webOrigin. For example, if you want to set the canonical origin to https://example.com, you can pass the string: const federation = createFederation({ origin: "https://example.com", }); NOTE The origin option has to include the leading https:// or http:// scheme. Such a configuration leads the constructed URLs using Context to use the canonical origin instead of the origin from the incoming HTTP requests, which avoids constructing unexpected URLs when a request bypasses a reverse proxy or a load balancer. CAUTION For example, suppose that your federated server (upstream) is accessible at the http://1.2.3.4:8000 and your load balancer (downstream) is accessible at the https://example.com and forwards the requests to the upstream server. In this case, you should set the canonical origin to https://example.com to construct the correct URLs. Otherwise, when some malicious actor directly sends a request to the upstream server, the constructed URLs will start with http://1.2.3.4:8000 instead of https://example.com, which can lead to security issues.
Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Share this news with your favorite app developers!

GoToSocial has documented their new global and post level interaction policies. I know @Fedicat has already added these - would love to see them in other apps too.


gts.superseriousbusiness.org/@

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Share this news with your favorite app developers!

GoToSocial has documented their new global and post level interaction policies. I know @Fedicat has already added these - would love to see them in other apps too.


gts.superseriousbusiness.org/@

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A topical or community Fediverse Relays — ex: a Paleogenetics relay server, or an animal photography relay server, or a company focused relay server, etc —

Would be similar to the old PlanetPlanet river-of-news feed-reader blogs.

web.archive.org/web/2017102917

RE: mastodon.social/@reiver/114044

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

A topical or community Fediverse Relays could be very useful (in addition to generic ones).

Ex: a Paleogenetics relay server, or an animal photography relay server, or a company focused relay server, etc

Especially for single-user, community, team, organization, themed, etc server instances

It would also help save storage space on server instances, by the relay being selective in what it shares.

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

slurp can now import your pixelfed-statuses.json to a GoToSocial server and save your photos locally in the process, provided your original Pixelfed server and account are still available to provide the photos.

https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-pixelfed-archive

this is only lightly tested; please let me know if it works for you.

#GoToSocial #GTS #Pixelfed #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

slurp can now import your pixelfed-statuses.json to a GoToSocial server and save your photos locally in the process, provided your original Pixelfed server and account are still available to provide the photos.

https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-pixelfed-archive

this is only lightly tested; please let me know if it works for you.

#GoToSocial #GTS #Pixelfed #FediDev

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

9/

And just for the record —

Just like everyone else I contacted about their 'discoverable' flag being defaulted to 'false' —

He wasn't aware of the 'discoverable' flag existing (just like everyone else I contacted).

He didn't want to be hidden (just like everyone else I contacted).

He changed it to 'true' (just like everyone else I contacted).

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

8/

As it is now, I think the 'discoverable' flag is broken.

And, I think the whole user-experience (UX) around the 'discoverable' flag is poor.

And, I think Fediverse software treating a 'false' value for 'discoverable' as "not discoverable" (rather than "not discoverable" or "no choice made") has hugely negative consequences for the user-experience (UX) of the Fediverse

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

7/

So now I have to DM Ben to tell him that his 'discoverable' flag is set to false

He (just like everyone else I contacted) will likely not even be aware that the 'discoverable' flag exists

And (just like everyone else I contacted) wished it wasn't set to false

And then (just like everyone else I contacted) struggle to find where he can set it to true

And then set it

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

6/

As it is now, the 'discoverable' flag seems broken to me.

Because 'false' doesn't actually mean 'false'.

'false' (in practice) means both "not discoverable" and "no choice made". And this is a very unfortunate situation —

Because the idea of a 'discoverable' flag is a good idea — but this problem with the meaning of 'false' and the UX consequences a big deal.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

5/

JSON and has a 'null'. That could have been used for the 'discoverable' flag.

We could have had so that:

'discoverable' set to 'true' meant that the user explicitly chose to be discoverable.

'discoverable' set to 'false' meant that the user explicitly chose to not be discoverable.

And 'discoverable' set to 'null' meant that the user has not explicitly made a choice.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

4/

With other conceptions, this lack of choice — this lack of setting a value — isn't as muddled.

With optional-types (which are also called "option-types" and "maybe-types") when something isn't assigned a value it is represented as 'nothing' / 'none'.

In relation-databases, this is represented as 'null'.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

As it is right now, the 'discoverable' flag does not communicate whether the user actually made a 'true' or 'false' choice.

If it is 'true' we know they made a choice.

But if it is 'false' it either means the user chose 'false' or the user didn't make a choice. BUT WE CANNOT TELL THE DIFFERENCE.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

There are a HUGE number of people who (unknown to them) have their 'discoverable' flags set to 'false' who —

№2:

Do NOT know that they have a 'discoverable' flag —

And do NOT know that their 'discoverable' flag was automagically set to 'false' —

And do not understand the consequence of having their 'discoverable' flag set to false.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

A problem with the 'discoverable' flag (in Mastodon and any other Fediverse software that added it) is —

There are a HUGE number of people who (unknown to them) have their 'discoverable' flags set to 'false' who —

№1:

Did NOT set their 'discoverable' to 'false' themselves.

Mastodon assigned it for them without ever asking them before hand and getting consent.

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

i've documented how to use slurp to import a Mastodon archive into GoToSocial 0.18 with status backdating: https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive

#GoToSocial #GTS #FediDev

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

8/

As it is now, I think the 'discoverable' flag is broken.

And, I think the whole user-experience (UX) around the 'discoverable' flag is poor.

And, I think Fediverse software treating a 'false' value for 'discoverable' as "not discoverable" (rather than "not discoverable" or "no choice made") has hugely negative consequences for the user-experience (UX) of the Fediverse

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

7/

So now I have to DM Ben to tell him that his 'discoverable' flag is set to false

He (just like everyone else I contacted) will likely not even be aware that the 'discoverable' flag exists

And (just like everyone else I contacted) wished it wasn't set to false

And then (just like everyone else I contacted) struggle to find where he can set it to true

And then set it

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

6/

As it is now, the 'discoverable' flag seems broken to me.

Because 'false' doesn't actually mean 'false'.

'false' (in practice) means both "not discoverable" and "no choice made". And this is a very unfortunate situation —

Because the idea of a 'discoverable' flag is a good idea — but this problem with the meaning of 'false' and the UX consequences a big deal.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

5/

JSON and has a 'null'. That could have been used for the 'discoverable' flag.

We could have had so that:

'discoverable' set to 'true' meant that the user explicitly chose to be discoverable.

'discoverable' set to 'false' meant that the user explicitly chose to not be discoverable.

And 'discoverable' set to 'null' meant that the user has not explicitly made a choice.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

4/

With other conceptions, this lack of choice — this lack of setting a value — isn't as muddled.

With optional-types (which are also called "option-types" and "maybe-types") when something isn't assigned a value it is represented as 'nothing' / 'none'.

In relation-databases, this is represented as 'null'.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

As it is right now, the 'discoverable' flag does not communicate whether the user actually made a 'true' or 'false' choice.

If it is 'true' we know they made a choice.

But if it is 'false' it either means the user chose 'false' or the user didn't make a choice. BUT WE CANNOT TELL THE DIFFERENCE.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

There are a HUGE number of people who (unknown to them) have their 'discoverable' flags set to 'false' who —

№2:

Do NOT know that they have a 'discoverable' flag —

And do NOT know that their 'discoverable' flag was automagically set to 'false' —

And do not understand the consequence of having their 'discoverable' flag set to false.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

A problem with the 'discoverable' flag (in Mastodon and any other Fediverse software that added it) is —

There are a HUGE number of people who (unknown to them) have their 'discoverable' flags set to 'false' who —

№1:

Did NOT set their 'discoverable' to 'false' themselves.

Mastodon assigned it for them without ever asking them before hand and getting consent.

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

i've documented how to use slurp to import a Mastodon archive into GoToSocial 0.18 with status backdating: https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive

#GoToSocial #GTS #FediDev

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

I can tell you from experience of hosting many people's Fediverse server instances for a number of years now that —

Many Fediverse software (at least currently) do a poor job of cleaning-up their various caches

Caching other people's profiles, images, posts, etc

And, this often ends up filling up the storage drive

And as a result, this is a very common thing that causes down-time for people. Probably the most common

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

i've documented how to use slurp to import a Mastodon archive into GoToSocial 0.18 with status backdating: https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive

#GoToSocial #GTS #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

i've documented how to use slurp to import a Mastodon archive into GoToSocial 0.18 with status backdating: https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive

#GoToSocial #GTS #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

i've documented how to use slurp to import a Mastodon archive into GoToSocial 0.18 with status backdating: https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive

#GoToSocial #GTS #FediDev

by luna's silver soil's avatar
by luna's silver soil

@vyr@princess.industries · Reply to by luna's silver soil's post

i've documented how to use slurp to import a Mastodon archive into GoToSocial 0.18 with status backdating: https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive

#GoToSocial #GTS #FediDev

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st · Reply to ꧁ wakest ꧂'s post

Oh totally a coincidence! Looks like @suvam is implementing this exact thing already in ! is fast paced!

mastodon.social/@suvam/1139355

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st · Reply to ꧁ wakest ꧂'s post

Oh totally a coincidence! Looks like @suvam is implementing this exact thing already in ! is fast paced!

mastodon.social/@suvam/1139355

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Is there any apps that let you bookmark posts into folders or categories? This is something that I see a lot of people using on Instagram that is incredibly useful. Could totally be done entirely client side too if someone wanted to implement it.

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Really annoying gripe that I hope someone on the is working on. If there is a long thread with many participants and 1 out of the many in that thread has your instance defederated, it breaks viewing the whole thread while logged in, so I have to go to another instance or a logged out view to *read* the whole thread.

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Is there any apps that let you bookmark posts into folders or categories? This is something that I see a lot of people using on Instagram that is incredibly useful. Could totally be done entirely client side too if someone wanted to implement it.

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Really annoying gripe that I hope someone on the is working on. If there is a long thread with many participants and 1 out of the many in that thread has your instance defederated, it breaks viewing the whole thread while logged in, so I have to go to another instance or a logged out view to *read* the whole thread.

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

"we can’t ignore the composition of the Unicode Consortium’s members, directors, and officers, the people who define the everyday writing systems of all languages across the globe. They are comprised largely of white men (and a few white women) whose first language was either English or another European language"
hci.social/@peterpur/114014097

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

This is the best rant about the I have read in a while. Bravo @annie, this is an amazing resource to have at hand.
social.lol/@annie/114010645430

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

User profiles, posts, images, and other content is cached across the various servers on the Fediverse.

Conceptually, software could access any of that from any server that cached it (and not just the origin server).

You could have a type of Fediverse content-distribution-network (CDN) if you did.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Has anyone made a directory page of all the with simple descriptions of what they are for yet?

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Could ActivityPub / ActivityStreams be used to synchronize files across separate machines / computers / devices‽

I think the answer is, YES.

The inbox-outbox system could enable you to send messages between separate machines / computers / devices.

The 'messages' transfer the changed 'blocks' / 'chunks' that make up a file, notify about deletions, file creations, etc

Existing Activity Types might be sufficient to do this

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

the Fediverse Core.

I.e., the people who make the technology of and for the Fediverse.

fedidevs.com/s/MTI1/

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Is any Fediverse software using or generating the 'View' activity-type?

w3.org/TR/activitystreams-voca

You could create view-counts on posts, profiles, etc, using this.

Of course, there are privacy concerns with this.

And, also, what counts as a "view".

Although, I sometimes use a "Like" to indicate I viewed something. If a 'View' was something manual (such a pressing a button) that could be more semantically clean.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

To me, it feels like the Activity Types should have been past-tense verbs, rather than present-tense verbs.

I.e.:

• "Accepted" rather than "Accept"
• "Added" rather than "Add"
• "Announced" rather than "Announce"
• "Arrived" rather than "Arrive"
• "Blocked" rather than "Block"
• "Created" rather than "Create"
• etc

Present-tense verbs feel like commands.

Past-tense verbs feel like events.

Activities are events not commands.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

To me, it feels like the Activity Types should have been past-tense verbs, rather than present-tense verbs.

I.e.:

• "Accepted" rather than "Accept"
• "Added" rather than "Add"
• "Announced" rather than "Announce"
• "Arrived" rather than "Arrive"
• "Blocked" rather than "Block"
• "Created" rather than "Create"
• etc

Present-tense verbs feel like commands.

Past-tense verbs feel like events.

Activities are events not commands.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

To me, it feels like the Activity Types should have been past-tense verbs, rather than present-tense verbs.

I.e.:

• "Accepted" rather than "Accept"
• "Added" rather than "Add"
• "Announced" rather than "Announce"
• "Arrived" rather than "Arrive"
• "Blocked" rather than "Block"
• "Created" rather than "Create"
• etc

Present-tense verbs feel like commands.

Past-tense verbs feel like events.

Activities are events not commands.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Excited to share that Fedify CLI is now available on Scoop for users! You can easily install it with scoop install fedify. One more way to get started with development!

https://github.com/ScoopInstaller/Main/pull/6371

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Visualize your server in the fediverse with the fedify node command and share it with us using the hashtag!

(See also how to install the fedify command.)

The result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Visualize your server in the fediverse with the fedify node command and share it with us using the hashtag!

(See also how to install the fedify command.)

The result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Visualize your server in the fediverse with the fedify node command and share it with us using the hashtag!

(See also how to install the fedify command.)

The result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

I have been talking about Custom Feeds for the Fediverse.

I will be setting up a demo server for Custom Feeds — so Fediverse developers can ad support for Fediverse Custom Feeds to their software.

(And have something to test again.)

marius's avatar
marius

@mariusor@metalhead.club

@silverpill any idea if there's a FEP regarding how to sign an activity that gets propagated through the Forwarding from Inbox mechanism? w3.org/TR/activitypub/#inbox-f

My first instinct is to use the instance actor for the server that received it, but I'm not sure.

Maybe the actor that received it in their inbox would be better, but that feels slightly unsanitary.

marius's avatar
marius

@mariusor@metalhead.club · Reply to marius's post

Anyone else keeping track of these tags feel free to jump in if you have any actionable ideas. :) TY

marius's avatar
marius

@mariusor@metalhead.club

@silverpill any idea if there's a FEP regarding how to sign an activity that gets propagated through the Forwarding from Inbox mechanism? w3.org/TR/activitypub/#inbox-f

My first instinct is to use the instance actor for the server that received it, but I'm not sure.

Maybe the actor that received it in their inbox would be better, but that feels slightly unsanitary.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

A milestone worth celebrating— just hit 100+ releases! From day one, we've been committed to building a robust framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the together! :fedify:

Screenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
ALT text detailsScreenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

A milestone worth celebrating— just hit 100+ releases! From day one, we've been committed to building a robust framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the together! :fedify:

Screenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
ALT text detailsScreenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

A milestone worth celebrating— just hit 100+ releases! From day one, we've been committed to building a robust framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the together! :fedify:

Screenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
ALT text detailsScreenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

A milestone worth celebrating— just hit 100+ releases! From day one, we've been committed to building a robust framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the together! :fedify:

Screenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
ALT text detailsScreenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

A milestone worth celebrating— just hit 100+ releases! From day one, we've been committed to building a robust framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the together! :fedify:

Screenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
ALT text detailsScreenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

A milestone worth celebrating— just hit 100+ releases! From day one, we've been committed to building a robust framework, and each release has brought us closer to that goal. Here's to many more releases as we continue growing the together! :fedify:

Screenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
ALT text detailsScreenshot shows release stats for Fedify: latest version 1.4.1 was released 6 minutes ago, with a green tag showing “Latest.” Total release count shows “+ 100 releases.” A green icon resembling a tag appears next to the Fedify name.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

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

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering adding custom background task support to 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 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.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

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 by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

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

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Doing some fediverse research and discovered that @tkithrta is attempting to "implement using 16 different web frameworks" in a project called
gitlab.com/acefed

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering adding custom background task support to 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 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.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering adding custom background task support to 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 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.

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Take a look at the AP Activities that are supported by @fedify

Going far beyond your every day social timeline - woud love to see some AP platforms add support for Listen, Offer, or Travel/Arrive/Leave.

github.com/fedify-dev/fedify/b

Gorgasbord's avatar
Gorgasbord

@geo@social.collectivemoo.net

This idea is a bit premature but I have decently functioning prototype. What does the think of federated gaming? A specific implementation is Club Penguin servers that federate user actions and messages so that separate servers can still have users render on other servers. Allows for full Mastodon integration, i.e. CP conversations show up as threads and a Mas user can respond and appear as a penguin message to CP users. Like CP is the front-end client.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering adding custom background task support to 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 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.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

However, "orderedItems" is mentioned in the ActivityStreams Core spec:

w3.org/TR/activitystreams-core/

Maybe the closest thing to a definition is:

"Collection are represented using the 'items' property while ordered items are represented using the 'orderedItems' property."

So, "orderedItems" is just like "items":

w3.org/TR/activitystreams-voca

... except renamed and the interpretation is different

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

"orderedItems" also isn't in the ActivityPub spec:

w3.org/TR/activitypub/

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

"orderedItems" shows up in the examples in the ActivityStreams Vocabulary spec:

w3.org/TR/activitystreams-voca

But, I don't see a definition for "orderedItems" in there (in the ActivityStreams Vocabulary spec).

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering adding custom background task support to 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 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.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're considering adding custom background task support to 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 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.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

Gorgasbord's avatar
Gorgasbord

@geo@social.collectivemoo.net

This idea is a bit premature but I have decently functioning prototype. What does the think of federated gaming? A specific implementation is Club Penguin servers that federate user actions and messages so that separate servers can still have users render on other servers. Allows for full Mastodon integration, i.e. CP conversations show up as threads and a Mas user can respond and appear as a penguin message to CP users. Like CP is the front-end client.

Gorgasbord's avatar
Gorgasbord

@geo@social.collectivemoo.net

This idea is a bit premature but I have decently functioning prototype. What does the think of federated gaming? A specific implementation is Club Penguin servers that federate user actions and messages so that separate servers can still have users render on other servers. Allows for full Mastodon integration, i.e. CP conversations show up as threads and a Mas user can respond and appear as a penguin message to CP users. Like CP is the front-end client.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

Gorgasbord's avatar
Gorgasbord

@geo@social.collectivemoo.net

This idea is a bit premature but I have decently functioning prototype. What does the think of federated gaming? A specific implementation is Club Penguin servers that federate user actions and messages so that separate servers can still have users render on other servers. Allows for full Mastodon integration, i.e. CP conversations show up as threads and a Mas user can respond and appear as a penguin message to CP users. Like CP is the front-end client.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Doing some fediverse research and discovered that @tkithrta is attempting to "implement using 16 different web frameworks" in a project called
gitlab.com/acefed

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

Growing better social media can be hard.

Many of the developers, moderators, and teams behind the projects that make up decentralised social media do it because they believe in what they're building. Projects which are self-funded, both in time and money then shared with you for little to no cost.

So, take some time today to say thank you to the people behind your favourite Fediverse tools and platforms. We're sure they'd appreciate it.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

BeAware :fediverse:'s avatar
BeAware :fediverse:

@BeAware@social.beaware.live

Just a warning for Fedi devs:

If you plan on building discovery features for Fedi, BeAware of the "Fedi Mafia" that harasses, threatens, and abuses any dev on Fedi that DARES to make an open platform a little bit more usable.🤦‍♂️

Over the past 2 months, I've seen 4 Fedi projects that were building tools to help people find accounts and servers to make it easier to find content on Fedi, get shut down because people who don't understand that Fedi is OPEN, harassed and threatened the devs until they shut their projects down.🤬

So, if you plan on building these tools, PLEASE just be prepared to block and continue building your tools.

Ignorant people should not dictate how this protocol is built. Don't let the abusers win.

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

Growing better social media can be hard.

Many of the developers, moderators, and teams behind the projects that make up decentralised social media do it because they believe in what they're building. Projects which are self-funded, both in time and money then shared with you for little to no cost.

So, take some time today to say thank you to the people behind your favourite Fediverse tools and platforms. We're sure they'd appreciate it.

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Take a look at the AP Activities that are supported by @fedify

Going far beyond your every day social timeline - woud love to see some AP platforms add support for Listen, Offer, or Travel/Arrive/Leave.

github.com/fedify-dev/fedify/b

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Take a look at the AP Activities that are supported by @fedify

Going far beyond your every day social timeline - woud love to see some AP platforms add support for Listen, Offer, or Travel/Arrive/Leave.

github.com/fedify-dev/fedify/b

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Take a look at the AP Activities that are supported by @fedify

Going far beyond your every day social timeline - woud love to see some AP platforms add support for Listen, Offer, or Travel/Arrive/Leave.

github.com/fedify-dev/fedify/b

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Take a look at the AP Activities that are supported by @fedify

Going far beyond your every day social timeline - woud love to see some AP platforms add support for Listen, Offer, or Travel/Arrive/Leave.

github.com/fedify-dev/fedify/b

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Take a look at the AP Activities that are supported by @fedify

Going far beyond your every day social timeline - woud love to see some AP platforms add support for Listen, Offer, or Travel/Arrive/Leave.

github.com/fedify-dev/fedify/b

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're excited to announce the release of Fedify 1.4.0! This release brings significant improvements to enhance compatibility and flexibility in federation.

Key Highlights

Activity transformers

Introduced a new system to adjust outgoing activities for better compatibility with various ActivityPub implementations. This includes automatic ID assignment for activities and actor dehydration to satisfy implementation quirks (looking at you, Threads!).

WebFinger customization

Added the ability to customize WebFinger responses through the new mapAlias() API, giving you more control over how your actors are discovered.

New interaction collections

Added support for shares, likes, and emojiReactions properties to the Object class, making it easier to access and traverse these interaction collections.

More flexible document/context loader

Document loader and context loader are now configurable through factory functions, giving you more control over how your application handles JSON-LD documents.

CLI improvements

The fedify lookup command now supports two new options:

Other enhancements

  • Added Context.getNodeInfo() method for easier NodeInfo access
  • Improved error handling in collection traversal and JSON-LD processing
  • Added support for private network access control in WebFinger lookups
  • User-Agent headers now automatically include your instance URL, making it easier for other servers to identify your instance

For the complete list of changes and bugfixes, please visit our changelog.

Whether you're building a new federated application or maintaining an existing one, 1.4.0 provides the tools you need for robust ActivityPub federation.

Supporting us

We're grateful to all our sponsors who make this project possible. Check out our new sponsors showcase page to see the amazing individuals and organizations supporting Fedify's development. If you'd like to support Fedify's development, please consider becoming a sponsor!

Upgrade now

You can install Fedify 1.4.0 from JSR or npm. Upgrade today and let us know what you think!

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

"meeting people in real life remains one of the best ways to build trust and relationships ... by getting the , ActivityPub plugin, and developers together and recognising themselves as the ‘longform’ people. This group of developers getting together this way helps with the various projects becoming more interoperable, and better support for longform content in the ."
-@laurenshof in fediversereport.com/fediverse-

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Has anyone made a directory page of all the with simple descriptions of what they are for yet?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

now supports in your bot messages!

You can now add searchable hashtags to your bot's posts using either our dedicated hashtag() function or through BotKit's extended Markdown syntax. This makes your bot's content more discoverable across the fediverse and helps engage with broader conversations.

Whether you're building a news bot, content curator, or community engagement tool, hashtags can help your bot reach the right audience.

Check out our docs to learn more about implementing hashtags in your bots!

Documentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
ALT text detailsDocumentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
Documentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
ALT text detailsDocumentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

now supports in your bot messages!

You can now add searchable hashtags to your bot's posts using either our dedicated hashtag() function or through BotKit's extended Markdown syntax. This makes your bot's content more discoverable across the fediverse and helps engage with broader conversations.

Whether you're building a news bot, content curator, or community engagement tool, hashtags can help your bot reach the right audience.

Check out our docs to learn more about implementing hashtags in your bots!

Documentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
ALT text detailsDocumentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
Documentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
ALT text detailsDocumentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

now supports in your bot messages!

You can now add searchable hashtags to your bot's posts using either our dedicated hashtag() function or through BotKit's extended Markdown syntax. This makes your bot's content more discoverable across the fediverse and helps engage with broader conversations.

Whether you're building a news bot, content curator, or community engagement tool, hashtags can help your bot reach the right audience.

Check out our docs to learn more about implementing hashtags in your bots!

Documentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
ALT text detailsDocumentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
Documentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
ALT text detailsDocumentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

now supports in your bot messages!

You can now add searchable hashtags to your bot's posts using either our dedicated hashtag() function or through BotKit's extended Markdown syntax. This makes your bot's content more discoverable across the fediverse and helps engage with broader conversations.

Whether you're building a news bot, content curator, or community engagement tool, hashtags can help your bot reach the right audience.

Check out our docs to learn more about implementing hashtags in your bots!

Documentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
ALT text detailsDocumentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
Documentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
ALT text detailsDocumentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

now supports in your bot messages!

You can now add searchable hashtags to your bot's posts using either our dedicated hashtag() function or through BotKit's extended Markdown syntax. This makes your bot's content more discoverable across the fediverse and helps engage with broader conversations.

Whether you're building a news bot, content curator, or community engagement tool, hashtags can help your bot reach the right audience.

Check out our docs to learn more about implementing hashtags in your bots!

Documentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
ALT text detailsDocumentation showing BotKit's hashtag() function usage. It demonstrates how to use the hashtag() function in template literals and explains that the function automatically adds the “#” prefix if missing. The note section explains that hashtags are made discoverable for ActivityPub software.
Documentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
ALT text detailsDocumentation showing BotKit's Markdown hashtag syntax. It demonstrates how to use hashtags in markdown() function with examples and explains that the function denotes hashtags for ActivityPub discoverability. It also shows how to disable hashtag syntax using the hashtags: false option.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

As the maintainer of , I'd be grateful for your support to help keep the project sustainable! :fedify:

https://hollo.social/@fedify/0194b112-b604-7d03-84e0-4faaf4ab46cd

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

🎉 Excited to announce that is now on Open Collective! Support the project's development starting at:

  • Backer (from $5/mo)
  • Supporter (from $25/mo)
  • Sponsor (from $100/mo)
  • Corporate Sponsor (from $500/mo)
  • Custom donations welcome

Your support will help us maintain and improve Fedify. Check it out here:

https://opencollective.com/fedify

:fedify:

Fedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
ALT text detailsFedify's Open Collective page showing the project logo, description as “A TypeScript library for building federated server apps powered by ActivityPub and other standards”, and five contribution tiers starting from $5/month Backer to $500/month Corporate Sponsor, with custom contribution options available.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Valtteri Laitinen (@valtlai) managed to get running on Workers!

https://fedi.valtlai.fi/@valtlai/113906145660141267

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

📢 Important announcement! 's repository has moved to a new home! 🏠

The repository is now located at @fedify-dev/botkit (previously @dahlia/botkit). All future development will continue at the new location.

Don't worry—everything's the same, just a new address! Please update your bookmarks and project references. Thanks for being part of our community! :botkit:

https://hollo.social/@fedify/0194a851-581d-779c-b777-dc39e753ef14

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've just moved the project and related repositories to our new GitHub organization account, @fedify-dev! 🎉

Here's what moved:

All repositories have been transferred and GitHub's automatic redirects are in place, so existing links will continue to work. Also, the project's core functionality and development process remain unchanged.

Thanks to everyone who participated in our naming poll. Looking forward to Fedify's continued growth under its new organizational home!

:fedify: New GitHub organization: https://github.com/fedify-dev.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

📢 Important announcement! 's repository has moved to a new home! 🏠

The repository is now located at @fedify-dev/botkit (previously @dahlia/botkit). All future development will continue at the new location.

Don't worry—everything's the same, just a new address! Please update your bookmarks and project references. Thanks for being part of our community! :botkit:

https://hollo.social/@fedify/0194a851-581d-779c-b777-dc39e753ef14

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've just moved the project and related repositories to our new GitHub organization account, @fedify-dev! 🎉

Here's what moved:

All repositories have been transferred and GitHub's automatic redirects are in place, so existing links will continue to work. Also, the project's core functionality and development process remain unchanged.

Thanks to everyone who participated in our naming poll. Looking forward to Fedify's continued growth under its new organizational home!

:fedify: New GitHub organization: https://github.com/fedify-dev.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

📢 Important announcement! 's repository has moved to a new home! 🏠

The repository is now located at @fedify-dev/botkit (previously @dahlia/botkit). All future development will continue at the new location.

Don't worry—everything's the same, just a new address! Please update your bookmarks and project references. Thanks for being part of our community! :botkit:

https://hollo.social/@fedify/0194a851-581d-779c-b777-dc39e753ef14

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've just moved the project and related repositories to our new GitHub organization account, @fedify-dev! 🎉

Here's what moved:

All repositories have been transferred and GitHub's automatic redirects are in place, so existing links will continue to work. Also, the project's core functionality and development process remain unchanged.

Thanks to everyone who participated in our naming poll. Looking forward to Fedify's continued growth under its new organizational home!

:fedify: New GitHub organization: https://github.com/fedify-dev.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

📢 Important announcement! 's repository has moved to a new home! 🏠

The repository is now located at @fedify-dev/botkit (previously @dahlia/botkit). All future development will continue at the new location.

Don't worry—everything's the same, just a new address! Please update your bookmarks and project references. Thanks for being part of our community! :botkit:

https://hollo.social/@fedify/0194a851-581d-779c-b777-dc39e753ef14

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've just moved the project and related repositories to our new GitHub organization account, @fedify-dev! 🎉

Here's what moved:

All repositories have been transferred and GitHub's automatic redirects are in place, so existing links will continue to work. Also, the project's core functionality and development process remain unchanged.

Thanks to everyone who participated in our naming poll. Looking forward to Fedify's continued growth under its new organizational home!

:fedify: New GitHub organization: https://github.com/fedify-dev.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

📢 Important announcement! 's repository has moved to a new home! 🏠

The repository is now located at @fedify-dev/botkit (previously @dahlia/botkit). All future development will continue at the new location.

Don't worry—everything's the same, just a new address! Please update your bookmarks and project references. Thanks for being part of our community! :botkit:

https://hollo.social/@fedify/0194a851-581d-779c-b777-dc39e753ef14

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've just moved the project and related repositories to our new GitHub organization account, @fedify-dev! 🎉

Here's what moved:

All repositories have been transferred and GitHub's automatic redirects are in place, so existing links will continue to work. Also, the project's core functionality and development process remain unchanged.

Thanks to everyone who participated in our naming poll. Looking forward to Fedify's continued growth under its new organizational home!

:fedify: New GitHub organization: https://github.com/fedify-dev.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

📢 Important announcement! 's repository has moved to a new home! 🏠

The repository is now located at @fedify-dev/botkit (previously @dahlia/botkit). All future development will continue at the new location.

Don't worry—everything's the same, just a new address! Please update your bookmarks and project references. Thanks for being part of our community! :botkit:

https://hollo.social/@fedify/0194a851-581d-779c-b777-dc39e753ef14

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

We've just moved the project and related repositories to our new GitHub organization account, @fedify-dev! 🎉

Here's what moved:

All repositories have been transferred and GitHub's automatic redirects are in place, so existing links will continue to work. Also, the project's core functionality and development process remain unchanged.

Thanks to everyone who participated in our naming poll. Looking forward to Fedify's continued growth under its new organizational home!

:fedify: New GitHub organization: https://github.com/fedify-dev.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

's web interface now supports theme customization! 🎨 You can set your preferred color theme using the pages.color option in createBot(). Here are some examples showing the same interface in different colors: "violet", "pumpkin", "azure", and "green" (default).

const bot = createBot<void>({
  // ... other options
  pages: {
    color: "violet"  // or "pumpkin", "azure", etc.
  }
});

We support all color themes from Pico CSS—including "amber", "fuchsia", "indigo", "jade", "lime", "pink", "sand", "slate", "yellow", "zinc", and more! Check out Pico CSS's Colors docs for the full list of available themes.

Which color is your favorite? 🤔

BotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
ALT text detailsBotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
Default green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
ALT text detailsDefault green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
BotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
ALT text detailsBotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
BotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
ALT text detailsBotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
Stefan Bohacek's avatar
Stefan Bohacek

@stefan@stefanbohacek.online

The @Mastodon team will be at the upcoming annual free and open source event in Brussels this upcoming weekend to talk about their (opt-in!) Fediverse Discovery Providers project:

fosdem.org/2025/schedule/event

More about the project: fediscovery.org/

Via mastodon.social/@Mastodon/1139

Stefan Bohacek's avatar
Stefan Bohacek

@stefan@stefanbohacek.online

The @Mastodon team will be at the upcoming annual free and open source event in Brussels this upcoming weekend to talk about their (opt-in!) Fediverse Discovery Providers project:

fosdem.org/2025/schedule/event

More about the project: fediscovery.org/

Via mastodon.social/@Mastodon/1139

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

's web interface now supports theme customization! 🎨 You can set your preferred color theme using the pages.color option in createBot(). Here are some examples showing the same interface in different colors: "violet", "pumpkin", "azure", and "green" (default).

const bot = createBot<void>({
  // ... other options
  pages: {
    color: "violet"  // or "pumpkin", "azure", etc.
  }
});

We support all color themes from Pico CSS—including "amber", "fuchsia", "indigo", "jade", "lime", "pink", "sand", "slate", "yellow", "zinc", and more! Check out Pico CSS's Colors docs for the full list of available themes.

Which color is your favorite? 🤔

BotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
ALT text detailsBotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
Default green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
ALT text detailsDefault green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
BotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
ALT text detailsBotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
BotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
ALT text detailsBotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

's web interface now supports theme customization! 🎨 You can set your preferred color theme using the pages.color option in createBot(). Here are some examples showing the same interface in different colors: "violet", "pumpkin", "azure", and "green" (default).

const bot = createBot<void>({
  // ... other options
  pages: {
    color: "violet"  // or "pumpkin", "azure", etc.
  }
});

We support all color themes from Pico CSS—including "amber", "fuchsia", "indigo", "jade", "lime", "pink", "sand", "slate", "yellow", "zinc", and more! Check out Pico CSS's Colors docs for the full list of available themes.

Which color is your favorite? 🤔

BotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
ALT text detailsBotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
Default green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
ALT text detailsDefault green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
BotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
ALT text detailsBotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
BotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
ALT text detailsBotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

's web interface now supports theme customization! 🎨 You can set your preferred color theme using the pages.color option in createBot(). Here are some examples showing the same interface in different colors: "violet", "pumpkin", "azure", and "green" (default).

const bot = createBot<void>({
  // ... other options
  pages: {
    color: "violet"  // or "pumpkin", "azure", etc.
  }
});

We support all color themes from Pico CSS—including "amber", "fuchsia", "indigo", "jade", "lime", "pink", "sand", "slate", "yellow", "zinc", and more! Check out Pico CSS's Colors docs for the full list of available themes.

Which color is your favorite? 🤔

BotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
ALT text detailsBotKit web interface in pumpkin theme, displaying Greet Bot's profile. Headers and interactive elements are styled in warm orange tones.
Default green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
ALT text detailsDefault green-themed BotKit interface displaying Greet Bot's profile. UI elements are styled in forest green colors, showing the default color scheme.
BotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
ALT text detailsBotKit web interface in violet theme, showing Greet Bot's profile with greeting message. The interface elements including headings and links are colored in shades of purple.
BotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
ALT text detailsBotKit web interface themed in azure blue, showing Greet Bot's profile and activity. Navigation elements and links feature various shades of blue.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm looking for your opinions from the developers of the fediverse.

A common HTML web page can contain related links via the <link> tag. I would like to do the same for Activity Streams objects, for example:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://writings.hongminhee.org/ap/2024/12/a-year-with-the-fediverse.json",
  "type": "Article",
  "name": "A year with the fediverse",
  "content": "2024 was truly a year where I was deeply immersed in the fediverse. …",
  "url": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/",
  "attachment": [
    {
      "type": "Link",
      "rel": "alternate",
      "hreflang": "ko",
      "href": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/index.ko-hang-kr.html",
      "mediaType": "text/html"
    },
    {
      "type": "Link",
      "rel": "alternate",
      "hreflang": "ja",
      "href": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/index.ja.html",
      "mediaType": "text/html"
    }
  ]
}

Do you think this makes sense, and would it be appropriate to put Link objects in the attachment?

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Exciting update on : we've introduced a new Repository abstraction layer that provides cleaner data access. While previously data operations went directly through KvStore, they now go through Repository—improving separation of concerns and making the codebase more maintainable. Don't worry though—there are no breaking changes to the public API that BotKit users rely on!

Key benefits:

  • Better abstraction over data sources
  • Cleaner internal architecture
  • Fully backwards compatible

Check out our docs for the technical details: https://botkit.fedify.dev/concepts/repository.

https://hollo.social/@hongminhee/0194a0d4-1d67-7c81-80ba-e7ade212d27a

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Exciting update on : we've introduced a new Repository abstraction layer that provides cleaner data access. While previously data operations went directly through KvStore, they now go through Repository—improving separation of concerns and making the codebase more maintainable. Don't worry though—there are no breaking changes to the public API that BotKit users rely on!

Key benefits:

  • Better abstraction over data sources
  • Cleaner internal architecture
  • Fully backwards compatible

Check out our docs for the technical details: https://botkit.fedify.dev/concepts/repository.

https://hollo.social/@hongminhee/0194a0d4-1d67-7c81-80ba-e7ade212d27a

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Exciting update on : we've introduced a new Repository abstraction layer that provides cleaner data access. While previously data operations went directly through KvStore, they now go through Repository—improving separation of concerns and making the codebase more maintainable. Don't worry though—there are no breaking changes to the public API that BotKit users rely on!

Key benefits:

  • Better abstraction over data sources
  • Cleaner internal architecture
  • Fully backwards compatible

Check out our docs for the technical details: https://botkit.fedify.dev/concepts/repository.

https://hollo.social/@hongminhee/0194a0d4-1d67-7c81-80ba-e7ade212d27a

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

Exciting update on : we've introduced a new Repository abstraction layer that provides cleaner data access. While previously data operations went directly through KvStore, they now go through Repository—improving separation of concerns and making the codebase more maintainable. Don't worry though—there are no breaking changes to the public API that BotKit users rely on!

Key benefits:

  • Better abstraction over data sources
  • Cleaner internal architecture
  • Fully backwards compatible

Check out our docs for the technical details: https://botkit.fedify.dev/concepts/repository.

https://hollo.social/@hongminhee/0194a0d4-1d67-7c81-80ba-e7ade212d27a

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm looking for your opinions from the developers of the fediverse.

A common HTML web page can contain related links via the <link> tag. I would like to do the same for Activity Streams objects, for example:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://writings.hongminhee.org/ap/2024/12/a-year-with-the-fediverse.json",
  "type": "Article",
  "name": "A year with the fediverse",
  "content": "2024 was truly a year where I was deeply immersed in the fediverse. …",
  "url": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/",
  "attachment": [
    {
      "type": "Link",
      "rel": "alternate",
      "hreflang": "ko",
      "href": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/index.ko-hang-kr.html",
      "mediaType": "text/html"
    },
    {
      "type": "Link",
      "rel": "alternate",
      "hreflang": "ja",
      "href": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/index.ja.html",
      "mediaType": "text/html"
    }
  ]
}

Do you think this makes sense, and would it be appropriate to put Link objects in the attachment?

bouncepaw 🍄's avatar
bouncepaw 🍄

@bouncepaw@merveilles.town

Does it make sense to roll out an ad-hoc federated bookmark search API? Please convince me I should take a different approach.

git.sr.ht/~bouncepaw/betula/tr

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

I mostly use Phanpy these days but I periodically go back and use @elk. The other day was one of those days. While I was browsing @mjtsai's profile I noticed that Elk supported the new fediverse:creator OG tag but for some reason it was quite borked when viewed from this profile. So I filed an issue in the Elk repo and forgot about it. Today I noticed that @shuuji3 already fixed it and now these badges look great!

a screenshot of a blog post on linked in a Mastodon post loaded in Elk with an OpenGraph tag featuring a fediverse:creator badge
ALT text detailsa screenshot of a blog post on linked in a Mastodon post loaded in Elk with an OpenGraph tag featuring a fediverse:creator badge
꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Anyone working on / / want to have a look at this weirdly inconsistent @elk bug?
github.com/elk-zone/elk/issues

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Anyone working on / / want to have a look at this weirdly inconsistent @elk bug?
github.com/elk-zone/elk/issues

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

I mostly use Phanpy these days but I periodically go back and use @elk. The other day was one of those days. While I was browsing @mjtsai's profile I noticed that Elk supported the new fediverse:creator OG tag but for some reason it was quite borked when viewed from this profile. So I filed an issue in the Elk repo and forgot about it. Today I noticed that @shuuji3 already fixed it and now these badges look great!

a screenshot of a blog post on linked in a Mastodon post loaded in Elk with an OpenGraph tag featuring a fediverse:creator badge
ALT text detailsa screenshot of a blog post on linked in a Mastodon post loaded in Elk with an OpenGraph tag featuring a fediverse:creator badge
꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

Doing some fediverse research and discovered that @tkithrta is attempting to "implement using 16 different web frameworks" in a project called
gitlab.com/acefed

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

the Fediverse Core.

I.e., the people who make the technology of and for the Fediverse.

fedidevs.com/s/MTI1/

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

the Fediverse Core.

I.e., the people who make the technology of and for the Fediverse.

fedidevs.com/s/MTI1/

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

A YunoHost type project, but specific to fediverse platforms. Definitely one I’m going to follow more closely.

Fedi Developers take note, there are some grants available to implement your fedi services as packages here!

“The Fediversity Project enables easy hosting for a wide variety of fediverse platforms, all based on NixOS. At the start, the project will support Mastodon, PixelFed,PeerTube...”

fediversity.eu/fediversity/

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

If you'd like to support the development of @fedify or @hollo or @botkit, you can sponsor me on GitHub!

https://github.com/sponsors/dahlia

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

The docs now have Recipes! It contains practical examples for common tasks like:

More recipes are on the way. Check it out now.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

The docs now have Recipes! It contains practical examples for common tasks like:

More recipes are on the way. Check it out now.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

The docs now have Recipes! It contains practical examples for common tasks like:

More recipes are on the way. Check it out now.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

The docs now have Recipes! It contains practical examples for common tasks like:

More recipes are on the way. Check it out now.

BotKit by Fedify :botkit:'s avatar
BotKit by Fedify :botkit:

@botkit@hollo.social

The docs now have Recipes! It contains practical examples for common tasks like:

More recipes are on the way. Check it out now.

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Happy to hear some good news. NodeBB officially released their ActivtyPub federated forums. And, for new forums, it’s automatically enabled! 🎉

Congratulations to the team, especially @julian

I’ve enjoyed reading the progress posts for this one. A lot of hard work and good collaborations between groups. They should be proud.

community.nodebb.org/post/1027

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Happy to hear some good news. NodeBB officially released their ActivtyPub federated forums. And, for new forums, it’s automatically enabled! 🎉

Congratulations to the team, especially @julian

I’ve enjoyed reading the progress posts for this one. A lot of hard work and good collaborations between groups. They should be proud.

community.nodebb.org/post/1027

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Fediverse Labeler update:

I have been working on a site that anyone can use to see Fediverse Labelers in action.

This is what it looks like if the user it looks up doesn't provide an avatar image or a header image.

I.e., this (in the screenshot) shows the default avatar image and header image.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

Although what I mentioned here doesn't resolve the problem with changing ones username.

That problem still exists with this technique.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

For example —

If the "username" is part of it, then there is a straightforward unique ID for this user as an acct-URL:

acct:joeblow@example·com

But there are many ways an HTTP-URL as an ID gets represented. Ex:

• http;//example·com/users/joeblow
• http;//example·com/user/joeblow
• http;//example·com/api/users/joeblow
• http;//example·com/api/user/joeblow
• http;//example·com/~joeblow
• etc

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

If ActivityPub and ActivityStreams used acct-URI rather than HTTP-URL to identify users, then there would less problems with switching between different Fediverse software.

(Different Fediverse software represent users with different style HTTP-URLs — which creates the problem.)

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

For previous posts on Fediverse Labelers, see:

mastodon.social/@reiver/113833

And:

mastodon.social/@reiver/113825

And:

mastodon.social/@reiver/113822

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Fediverse Labeler update:

I have been working on a site that anyone can use to see Fediverse Labelers in action.

This is what it looks like if the user it looks up doesn't provide an avatar image or a header image.

I.e., this (in the screenshot) shows the default avatar image and header image.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

For discussion on some of the technical / programming side of Fediverse Labelers, see:

mastodon.social/@reiver/113822

.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

More on Fediverse Labelers —

Here is how text-labels from multiple Fediverse Labelers could appear in an application on a person's profile.

...

In this example, the application pulled in 7 labels from 4 different Fediverse Labelers.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

For previous threads on Fediverse Labelers see:

mastodon.social/@reiver/113825

And:

mastodon.social/@reiver/113822

.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

For previous threads on Fediverse Labelers see:

mastodon.social/@reiver/113825

And:

mastodon.social/@reiver/113822

.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Fediverse Labeler update:

I have been working on site that anyone can use to see Fediverse Labelers in action.

I am hoping to get it done soon. (Maybe by the weekend or next week.)

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

This screen mock-up only shows text-labels.

Other types of labels can exist — image labels of different types, virtual object labels, space-time labels, etc.

And labels can have different use-case (in addition to human-readable text) — more on that later.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

For discussion on some of the technical / programming side of Fediverse Labelers, see:

mastodon.social/@reiver/113822

.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

More on Fediverse Labelers —

Here is how text-labels from multiple Fediverse Labelers could appear in an application on a person's profile.

...

In this example, the application pulled in 7 labels from 4 different Fediverse Labelers.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

This screen mock-up only shows text-labels.

Other types of labels can exist — image labels of different types, virtual object labels, space-time labels, etc.

And labels can have different use-case (in addition to human-readable text) — more on that later.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

For discussion on some of the technical / programming side of Fediverse Labelers, see:

mastodon.social/@reiver/113822

.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

More on Fediverse Labelers —

Here is how text-labels from multiple Fediverse Labelers could appear in an application on a person's profile.

...

In this example, the application pulled in 7 labels from 4 different Fediverse Labelers.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

4/

Note that even in this example, that there are different types of labels!

I have some examples of text labels.

But I also have some examples of Icon labels.

(Other types of labels could exist, too.)

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

3/

The "describes" field would point to the thing being labelled.

The "attributedTo" field would point to the person or machine that create these label.

And the "attachment" field would be a list of labels.

The (top level) "icon" field would be an icon that would be shown next to the label in the user-interface (UI).

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social · Reply to @reiver ⊼ (Charles) :batman:'s post

2/

A Fediverse Labeler would output a separate ActivityStreams "Profile" Object for each thing it wants to label.

Each of these should be at a separate URL.

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

1/

This is how a Fediverse Labeler could work.

In particular, This is how a Fediverse Labeler could be represented as ActivityPub / ActivityStreams / JSON-LD data.

{
  "@context": [
    "https://www.w3.org/ns/activitystreams"
  ],
  "type": "Profile",
  "describes": "acct:reiver@mastodon.social",
  "attributedTo": "https://example.com/apps/ratel",
  "icon": {
    "type": "Icon",
    "mediaType": "image/png",
    "url": "https://example.com/apps/ratel/img/icon.png"
  },
  "attachment": [
    {
      "type": "Label",
      "name": "Programmer"
    },
    {
      "type": "Label",
      "name": "Canadian"
    },
    {
      "type": "Icon",
      "mediaType": "image/png",
      "url": "https://example.com/pfp/751f76ed540a40a3b4caae50e50cc867.png"
    },
    {
      "type": "Icon",
      "mediaType": "image/png",
      "url": "https://example.com/pfp/45f7b459257940f490133070a975924b.png"
    }
  ]
}
ALT text details{ "@context": [ "https://www.w3.org/ns/activitystreams" ], "type": "Profile", "describes": "acct:reiver@mastodon.social", "attributedTo": "https://example.com/apps/ratel", "icon": { "type": "Icon", "mediaType": "image/png", "url": "https://example.com/apps/ratel/img/icon.png" }, "attachment": [ { "type": "Label", "name": "Programmer" }, { "type": "Label", "name": "Canadian" }, { "type": "Icon", "mediaType": "image/png", "url": "https://example.com/pfp/751f76ed540a40a3b4caae50e50cc867.png" }, { "type": "Icon", "mediaType": "image/png", "url": "https://example.com/pfp/45f7b459257940f490133070a975924b.png" } ] }
@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

Is any Fediverse (or other) software using or returning an ActivityStreams 'Profile'?

w3.org/TR/activitystreams-voca

@reiver ⊼ (Charles) :batman:'s avatar
@reiver ⊼ (Charles) :batman:

@reiver@mastodon.social

the Fediverse Core.

I.e., the people who make the technology of and for the Fediverse.

fedidevs.com/s/MTI1/

Jessie Nabein :neofox_peek_owo:'s avatar
Jessie Nabein :neofox_peek_owo:

@jessienab@wetdry.world

Hey so at some point changed the way that notifications work, and I can only clear ALL my notifications instead of SPECIFIC notifications.

I hate this change and I wish it never happened.

Please someone tell me there's a way to revert this; same shit happens with Tusky too...

Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

The last "big" code thing I need to get done before the alpha test of my current @fedify project is the task queue - make sure routine data updates happen, consider individual importance and urgency, respect external API rate limits, etc.

But that's super intimidating so I'm currently procrastinating by making it a cute lil home page instead. 🙃

Photo of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
ALT text detailsPhoto of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

The last "big" code thing I need to get done before the alpha test of my current @fedify project is the task queue - make sure routine data updates happen, consider individual importance and urgency, respect external API rate limits, etc.

But that's super intimidating so I'm currently procrastinating by making it a cute lil home page instead. 🙃

Photo of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
ALT text detailsPhoto of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

The last "big" code thing I need to get done before the alpha test of my current @fedify project is the task queue - make sure routine data updates happen, consider individual importance and urgency, respect external API rate limits, etc.

But that's super intimidating so I'm currently procrastinating by making it a cute lil home page instead. 🙃

Photo of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
ALT text detailsPhoto of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

The last "big" code thing I need to get done before the alpha test of my current @fedify project is the task queue - make sure routine data updates happen, consider individual importance and urgency, respect external API rate limits, etc.

But that's super intimidating so I'm currently procrastinating by making it a cute lil home page instead. 🙃

Photo of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
ALT text detailsPhoto of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
Julian Fietkau's avatar
Julian Fietkau

@julian@fietkau.social

The last "big" code thing I need to get done before the alpha test of my current @fedify project is the task queue - make sure routine data updates happen, consider individual importance and urgency, respect external API rate limits, etc.

But that's super intimidating so I'm currently procrastinating by making it a cute lil home page instead. 🙃

Photo of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
ALT text detailsPhoto of a monitor showing some CSS code. The code hints at a website where images are animated and zoomed.
Stefan Bohacek's avatar
Stefan Bohacek

@stefan@stefanbohacek.online

Pretty neat. I've now seen three examples of fediverse bots that run as independent fediverse servers, rather than using some platform's (most commonly Mastodon's) API.

- castling.club: "Challenge someone to a game of chess"
- transit.alerts.social: transit alerts
- fedimeteo.com: real-time weather updates

Minoru's avatar
Minoru

@minoru@functional.cafe

The list of Fediverse instances over at nodes.fediverse.party/ hasn't been updated for about three months, and nobody contacted me about it. Is anyone even using the service?

Minoru's avatar
Minoru

@minoru@functional.cafe

The list of Fediverse instances over at nodes.fediverse.party/ hasn't been updated for about three months, and nobody contacted me about it. Is anyone even using the service?

Stefan Bohacek's avatar
Stefan Bohacek

@stefan@stefanbohacek.online

Pretty neat. I've now seen three examples of fediverse bots that run as independent fediverse servers, rather than using some platform's (most commonly Mastodon's) API.

- castling.club: "Challenge someone to a game of chess"
- transit.alerts.social: transit alerts
- fedimeteo.com: real-time weather updates

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text detailsimport { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;
Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

If you're curious how ActivityPub works exactly (like me) this site does a great job of show and tell.

On the surface it looks like any other Mastodon instance, but on closer inspection, provides you insight into the ActivityPub back and forth going on behind the scenes!

Check out the great work by @crepels

activitypub.academy/

The Activity Log shows the ActivityPub objects that are passed back and forth when a follow request is sent from one instance to another.
ALT text detailsThe Activity Log shows the ActivityPub objects that are passed back and forth when a follow request is sent from one instance to another.
Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

bouncepaw 🍄's avatar
bouncepaw 🍄

@bouncepaw@merveilles.town

Does it make sense to roll out an ad-hoc federated bookmark search API? Please convince me I should take a different approach.

git.sr.ht/~bouncepaw/betula/tr

bouncepaw 🍄's avatar
bouncepaw 🍄

@bouncepaw@merveilles.town

Does it make sense to roll out an ad-hoc federated bookmark search API? Please convince me I should take a different approach.

git.sr.ht/~bouncepaw/betula/tr

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

I'm looking for your opinions from the developers of the fediverse.

A common HTML web page can contain related links via the <link> tag. I would like to do the same for Activity Streams objects, for example:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://writings.hongminhee.org/ap/2024/12/a-year-with-the-fediverse.json",
  "type": "Article",
  "name": "A year with the fediverse",
  "content": "2024 was truly a year where I was deeply immersed in the fediverse. …",
  "url": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/",
  "attachment": [
    {
      "type": "Link",
      "rel": "alternate",
      "hreflang": "ko",
      "href": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/index.ko-hang-kr.html",
      "mediaType": "text/html"
    },
    {
      "type": "Link",
      "rel": "alternate",
      "hreflang": "ja",
      "href": "https://writings.hongminhee.org/2024/12/a-year-with-the-fediverse/index.ja.html",
      "mediaType": "text/html"
    }
  ]
}

Do you think this makes sense, and would it be appropriate to put Link objects in the attachment?

Jeff C. 🇺🇦's avatar
Jeff C. 🇺🇦

@jeff@indieweb.social

Still not a fan of Mastodon's hashtag-centric discovery and topical discussion paradigm.

I want to keep up-to-date with goings-on in Ukraine, but the relevant hashtags have been co-opted by tankies and such spreading Russian agitprop.

I hope one day Mastodon "un-nerfs" list functionality so that users can subscribe to well-curated lists created by known and trusted sources/experts and read posts from those people, w/o committing to manually following each member directly.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Besides WordPress and Ghost, are there any other implementations that send out an Article type rather than a Note?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

If you update an account profile in the fediverse, who should you send the Update(Person) activity to?

OptionVoters
Every follower18 (78%)
Every peer actor you've encountered so far5 (22%)
Tokyo Outsider (337ppm)'s avatar
Tokyo Outsider (337ppm)

@tokyo_0@mas.to

Developer question: If you build a minimal ActivityPub server for development purposes, do you have to run it on a registered domain with an SSL certificate for it to be able to connect to anything else (like a big Mastodon instance)?

Or is running it on some kind of dynDNS or ngrok type service (so it has a static domain name) enough just to test things out?

(Boosts for reach gratefully received 🙏)

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

If you'd like to support the development of @fedify or @hollo, you can sponsor me on GitHub!

github.com/sponsors/dahlia

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I have a question about signature handling in relays. As I understand it, relays forward activities between instances that aren't directly connected. Let's say we have this flow: foo.com (source) → bar.com (relay) → baz.com (destination). The activity created by foo.com includes HTTP Signatures, but when bar.com forwards it to baz.com, wouldn't the original signature become invalid since the Host header needs to change? How do relay implementations handle this issue?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Have you heard of Val Town? Val Town is a kind of code pastebin + serverless function.

Actually, works just fine with Val Town. Here's a piece of ActivityPub software, implemented in about 170 lines of code, running on Val Town. Of course, it's built with Fedify!

Give it a follow @demo, and it will follow you back.

Curious to see how it was implemented? Check out the source code!

https://www.val.town/v/minhee/FedifyOnValTown

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We've added the build guide to the CONTRIBUTING.md docs in the repository. We hope this is helpful for those who want to contribute to Fedify!

https://github.com/dahlia/fedify/blob/main/CONTRIBUTING.md#build

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

What are your thoughts on Fedify's docs?

OptionVoters
Comprehensive and easy to understand4 (67%)
Comprehensive but hard to understand0 (0%)
Limited but easy to understand1 (17%)
Limited and hard to understand1 (17%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Visualize your server in the fediverse with the fedify node command and share it with us using the hashtag!

(See also how to install the fedify command.)

The result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify node https://hollo.social/@fedify command. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup venera.social. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup misskey.io. The NodeInfo document is visualized along with the favicon.
The result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
ALT text detailsThe result of fedify lookup fosstodon.org. The NodeInfo document is visualized along with the favicon.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

The version 1.2.0 of , an server framework, released! The key changes include:

For details, see the full changelog as well!

Fedify 1.2.0 is available at JSR and npm.

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

It's been a busy year at Newsmast for The Newsmast Foundation team, but we've done a lot!

We've actually done too much to fit it into one post 👀

So, we broke out the video editing skills... hope you like it!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Starting with the next release of , v1.2.0, we will support traceable logs for easier debugging. Fedify's traceable logs are implemented using the implicit contexts introduced in LogTape 0.7.0, and most of the logs that Fedify records are given a requestId or messageId. This means that logs can be grouped into requests or background tasks for better analysis.

Want to try it out in advance? Try Fedify v1.2.0-dev.468+2e17cd69 (JSR & npm)!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

In , does the icon for the server information that I see in the remote note come from the favicon for that server?

jonny (good kind)'s avatar
jonny (good kind)

@jonny@neuromatch.social

Alright, , backend edition is open as a PR against upstream masto: github.com/mastodon/mastodon/p

Please roast me for my code and help me get it into a state where we can make this default behavior for masto instances and remove one of the biggest contributors to the reply guy problem on the fedi <3

Steffo's avatar
Steffo

@steffo@junimo.party

#FediDev: What’s the point of having separate signing keys for each actor if they all end up getting managed by the same instance?

Ideally (“even if no fedi client does it atm”), should users hold keys in their client, and sign the posts on the local machine before passing them to their server to forward to the recipients?

Or am I missing something?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

The version 1.1.0 of , an server framework, released! The key changes include:

  • Added uility functions for traversing remote collections. See also the Traversing remote collections section in the docs.

  • Added EmojiReact class to Activity Vocabulary API. [FEP-c0e0]

  • Added successor property to the Actor types in the Activity Vocabulary API.

  • Added DidService class to Activity Vocabulary API. [FEP-9091]

  • Added Export class to Activity Vocabulary API. [FEP-9091]

  • Added service property to the Actor types in the Activity Vocabulary API. [FEP-9091]

  • The default time window for verifying HTTP Signatures of incoming requests is now an hour (was a minute). This new default window is according to the ActivityPub and HTTP Signatures document.

  • In the fedify inbox command's web interface, the Raw Activity tab is added to show the raw JSON object of the received activity.

For details, see the full changelog as well!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

A summary of the two existing emoji reaction APIs: the Pleroma/Akkoma family and the Fedibird/kmyblue family.

github.com/cheeaun/phanpy/issu

There are two kinds of emoji reaction APIs:

Pleroma/Akkoma family

• POST /api/v1/statuses/:id/react/:emoji
• POST /api/v1/statuses/:id/unreact/:emoji

This can be detected by looking up pleroma_emoji_reactions and custom_emoji_reactions from pleroma.metadata.features responded by GET /api/v1/instance, e.g., seafoam.space/api/v1/instance.

Fedibird/kmyblue family

• PUT /api/v1/statuses/:id/emoji_reactions/:emoji
• DELETE /api/v1/statuses/:id/emoji_reactions/:emoji

This can be detected by looking up emoji_reaction from fedibird_capabilities responded by GET /api/v1/instance, e.g., fedibird.com/api/v1/instance, kmy.blue/api/v1/instance.
ALT text detailsThere are two kinds of emoji reaction APIs: Pleroma/Akkoma family • POST /api/v1/statuses/:id/react/:emoji • POST /api/v1/statuses/:id/unreact/:emoji This can be detected by looking up pleroma_emoji_reactions and custom_emoji_reactions from pleroma.metadata.features responded by GET /api/v1/instance, e.g., seafoam.space/api/v1/instance. Fedibird/kmyblue family • PUT /api/v1/statuses/:id/emoji_reactions/:emoji • DELETE /api/v1/statuses/:id/emoji_reactions/:emoji This can be detected by looking up emoji_reaction from fedibird_capabilities responded by GET /api/v1/instance, e.g., fedibird.com/api/v1/instance, kmy.blue/api/v1/instance.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

The value of the form at://… in the alsoKnownAs property of the actor generated by @bsky.brid.gy is not actually a valid URL? It cannot be represented as a URL object in Node.js or Deno.

Node.js:

> new URL("at://did:plc:x7xdowahlhm5xulzqw4ehv6q")
Uncaught TypeError: Invalid URL
    at new URL (node:internal/url:816:29) {
  code: 'ERR_INVALID_URL',
  input: 'at://did:plc:x7xdowahlhm5xulzqw4ehv6q'
}

Deno:

> new URL("at://did:plc:x7xdowahlhm5xulzqw4ehv6q")
Uncaught TypeError: Invalid URL: 'at://did:plc:x7xdowahlhm5xulzqw4ehv6q'
    at getSerialization (ext:deno_url/00_url.js:98:11)
    at new URL (ext:deno_url/00_url.js:405:27)
    at <anonymous>:1:22
ALT text detailsNode.js: > new URL("at://did:plc:x7xdowahlhm5xulzqw4ehv6q") Uncaught TypeError: Invalid URL at new URL (node:internal/url:816:29) { code: 'ERR_INVALID_URL', input: 'at://did:plc:x7xdowahlhm5xulzqw4ehv6q' } Deno: > new URL("at://did:plc:x7xdowahlhm5xulzqw4ehv6q") Uncaught TypeError: Invalid URL: 'at://did:plc:x7xdowahlhm5xulzqw4ehv6q' at getSerialization (ext:deno_url/00_url.js:98:11) at new URL (ext:deno_url/00_url.js:405:27) at <anonymous>:1:22
꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

(a threadiverse/lemmy/mbin/piefed web frontend project) want to open source it and are looking for someone to do a code review/security analysis first... Are you into security and the fediverse *and* stuff being open source? Then respond here!

found via this post [lemmy.world/post/20828200] on Lemmy by ClubsAll dev @vinay_clubsall

:fediverse:
clubsall.com

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

now has an driver! This means you can use as Fedify's message queue. To use it, first install the @fedify/amqp package, then set it up like below:

import { createFederation } from "@fedify/fedify";
import { AmqpMessageQueue } from "@fedify/amqp";
import { connect } from "amqplib";

const federation = createFederation({
  queue: new AmqpMessageQueue(await connect("amqp://localhost")),
  // ... other configurations
});

Oh, and we've also added results from AmqpMessageQueue to our benchmarks.

The results of the benchmarks for Fedify's outbox queue.
ALT text detailsThe results of the benchmarks for Fedify's outbox queue.
Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Write.as announces an integration with sub.club, a way to offer premium content in the fediverse to subscribers.

write.as/blog/write-as-x-sub-c

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Even though I am a slow coder, it only took me about a month to create most of 's features in . Having a framework makes a huge difference in productivity.

Mochikovski's avatar
Mochikovski

@mochi@mochi.mochikov.ski

Hamabē is born! :bunhdhappy: :repost_pls:

I just released the very first version of Hamabē, and the official demo instance went live!

Hamabē is a successor of Audon, but a new platform speaking ActivityPub and independent of Mastodon API.

You can follow Hamabē accounts from AP platforms and can receive notifications when a space starts (if your platform supports Event activity)

Right now Hamabē only has voice chat (along with simple text chat) to cover Audon's use cases, but there's a plan to add text-based group chat later.

I also created Matrix Space for general discussion. Comments and suggestions are very appreciated!

The documentation is not ready yet. I'd write deployment guide soon.

If you wanna give it a shot, you can create your account here: https://try.hamabe.space

(Disclaimer) Hamabē is still in the very early stage of development. Expect a lot of bugs!

Thank you and happy chatting :bunhdheart:

#hamabe #audon #fedidev

The left panel and the right panel are different accounts of Hamabē on different servers. They are chatting in the same room.
ALT text detailsThe left panel and the right panel are different accounts of Hamabē on different servers. They are chatting in the same room.
The notifications from Hamabē federate to Mitra on the right panel.
ALT text detailsThe notifications from Hamabē federate to Mitra on the right panel.
The notifications from Hamabē federate to Mastodon on the right panel.
ALT text detailsThe notifications from Hamabē federate to Mastodon on the right panel.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

According to the Activity Vocabulary specification, the summary property should be HTML encoded, but is putting plain text in the summary property. is putting in the summary, but should I change Hollo's behavior? :blobcatthink:

w3.org/TR/activitystreams-voca

The Activity Vocabulary specification says that the summary property is “a natural language summarization of the object encoded as HTML.”
ALT text detailsThe Activity Vocabulary specification says that the summary property is “a natural language summarization of the object encoded as HTML.”
Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Looks like around a month ago, the developer of Kaiteki, a flutter based fediverse client, closed shop. They left the source code available to anyone that might want to pick it up, however!

activitypub.software/TransFem-

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Yay! Another music platform adding support for the fediverse. 🎶🎶

mastodon.moule.world/@MOULE/11

Grow Your Own Services 🌱's avatar
Grow Your Own Services 🌱

@homegrown@social.growyourown.services

If you're an advanced user with programming skills who is wanting to do custom stuff with Fediverse connections (or even wanting to create your own Fedi platform), you might want to check out the activitypub.rocks SocialHub forum:

:Fediverse: socialhub.activitypub.rocks

I'm not a software developer so I can't help with these topics, but enough people have asked that it seemed a good idea to give the forum a mention!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

If you're considering creating your own implementation of , consider .

Implementing ActivityPub from scratch requires more than you might think. WebFinger, HTTP Signatures, Linked Data Signatures, Object Integrity Proofs, NodeInfo, queues for sending and receiving activities, followers collection synchronization, remote object lookups, interoperability with Mastodon, Akkoma, Misskey, Threads, and more…

Just use Fedify and feel free to create your own ActivityPub implementation!

https://fedify.dev/

洪 民憙(ホン・ミンヒ)'s avatar
洪 民憙(ホン・ミンヒ)

@hongminhee@fedibird.com

独自のActivityPubの実装を作りたい方は、Fedifyを検討してみてください。

ActivityPubをゼロから実装するには、想像以上に多くの物を作る必要が有ります。WebFinger、HTTP Signatures、Linked Data Signatures、Object Integrity Proofs、NodeInfo、アクティビティの送受信のキュー、フォロワーコレクションのシンクロ、リモートオブジェクトの照会、MastodonやMisskey等との相互運用性の為の雑多な処理まで…Fedifyを使えば簡単に自分だけのActivityPubの実装を作る事が出来ます!

fedify.dev/

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Adding vocabularies for FEP-9091 to .

github.com/dahlia/fedify/issue

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Did you know that? The CLI has a command called fedify lookup, which can easily look up ActivityStreams objects on servers with authorized fetch (a.k.a. secure mode) enabled by turning on the -a/--authorized-fetch flag.

Here's demo!

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

You can now see in (but you can't leave emoji reactions yet). We've implemented the FEP-c0e0 spec and tested it on , , and .

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Introducing Fedify: Build Your Own Fediverse App with Ease! 🚀

Are you excited about the but find implementing daunting? Meet , a framework that simplifies building federated server apps. Whether you're creating the next Mastodon, Pixelfed, or something entirely new, Fedify has you covered.

What Fedify Offers:

Fedify abstracts away the complexities of ActivityPub, letting you focus on your app's unique features. It's designed to work seamlessly with popular web frameworks like Hono, Express, and Fresh.

Get Started Today!

Check out our step-by-step tutorial to create a microblog: https://fedify.dev/tutorial/microblog

Explore the discussions, contribute, or just star us on GitHub: https://github.com/dahlia/fedify

Join the Fedify community! Questions? Ideas? Find us on Matrix: #fedify:matrix.org.

Let's build a more diverse and interoperable fediverse together with Fedify!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I'm adding the (FEP-c0e0) class to … It will be coming in Fedify 1.1.0.

w3id.org/fep/c0e

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

Today is so we thought we'd shout out truefans.fm - a podcast marketplace built on the Fediverse by @samsethi

It was really exciting seeing Sam's demo of True Fans at @fediforum a few weeks ago.

If you're looking for a podcasting alternative on the Fediverse, check it out!

jonny (good kind)'s avatar
jonny (good kind)

@jonny@neuromatch.social

Oh gr8, apparently being able to await the results of a batch of sidekiq jobs is an exclusive "sidekiq pro" feature.

So here's the deal: for we need to set some kind of global fetch limit so a maliciously crafted thread tree doesn't keep us fetching forever. Currently it's implemented as a recursive fetch, but I want to move the "expansion" part where we gather the URIs of all the posts to fetch at a top level, and then just dispatch workers to fetch those posts in a flat queue with a global limit

Problem: with current masto impl, you have to already have a status to fetch its replies, so we need to await the results of prior fetch level before starting the next one. Does anyone know how to await sidekiq jobs? We already know the URIs of the posts that are being fetched, but I can't tell how to either a) await the redis job being popped from the queue or b) await a Status object with a matching uri being created. Im also not sure how I could c) use a callback to signal to the initiating worker that a status has been fetched.

Anyone know what the move here is? Im sure there must be some chained workers like this somewhere in masto, but all the examples I can find for sidekiq use the "pro" features.

PR here shows the current recursion I'm trying to flatten: github.com/NeuromatchAcademy/m

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fedify, an ActivityPub framework, has finally released its first stable version, 1.0.0! Here are key changes:

Deprecation of the term handle

From this version, the term handle across Fedify will only be used to refer to fediverse handles (e.g., @hongminhee@fosstodon.org). An actor's internal unique ID (e.g., b379dbdc-3b4f-4ef4-88c2-fc25632d1c22) is referred to as an identifier, and the WebFinger name (e.g., hongminhee) is referred to as a username.

The term handle in the API will be maintained for a while for backward compatibility, but deprecation warnings will be logged, and it is planned to be removed in the future.

For more details, please refer to the related documentation.

Linked Data Signatures

Linked Data Signatures is an outdated standard, but it's still relied upon by major fediverse implementations such as Mastodon.

In addition to HTTP Signatures and Object Integrity Proofs, Fedify now supports Linked Data Signatures from this version, thus supporting all types of signature methods used in the fediverse. This makes Fedify an ActivityPub implementation with the best interoperability.

However, Fedify users don't need to do anything special to use Linked Data Signatures. If an incoming activity has Linked Data Signatures, it automatically verifies the signature, and all outgoing activities will have signatures in three formats: HTTP Signatures, Linked Data Signatures, and Object Integrity Proofs.

For more details, please refer to the related documentation.

Activity forwarding

From this version, you can forward activities received in the inbox to other actors using the InboxContext.forwardActivity() method.

At first glance, you might think that you could just resend an activity received in the inbox using the Context.sendActivity() method. However, if you do this, the original signature is removed before the activity is delivered to the inbox, and when sending it, the signature of the forwarding actor is attached instead, causing the receiving side of the forwarded activity to not trust it.

On the other hand, when using the InboxContext.forwardActivity() method, the activity is forwarded with the original signature preserved, avoiding this problem. (Of course, the original activity itself must be signed with Linked Data Signatures or Object Integrity Proofs.)

For more details, please refer to the related documentation.

Sending Delete(Application) on fedify inbox termination

From this version, fedify inbox will send a Delete(Application) activity to all peer servers it encountered when terminated. This is typically an activity sent when deleting an account, which will help prevent residual data related to temporary actors from remaining on other servers.

PostgreSQL drivers

The @fedify/postgres package, which implements PostgreSQL drivers for the KvStore and MessageQueue interfaces, has been released alongside this version.

The PostgreSQL driver is a backend that can be sufficiently used in production, especially recommended for projects already using PostgreSQL.

Additionally, an option to select the PostgreSQL driver has been added to the fedify init command.

Celebrating Fedify 1.0.0

With the release of version 1.0.0, Fedify will now maintain API backward compatibility as much as possible. (Of course, in the long term, there may be a 2.0.0 that breaks backward compatibility.) This should be good news for those who have been hesitant to use Fedify because there hasn't been a stable version until now!

So, hoping that more services will support ActivityPub in the future, I conclude this post!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Looks like v1.0.0 will be released this week! Is there anything you'd like to see added or fixed before then?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I'm polishing the and filling in the gaps before releasing v1.0. Is there something else you'd like to see in the @fedify docs?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

The next version of , v1.0, adds ParallelMessageQueue, which makes it easy to parallelize sending and receiving activities without increasing the number of processes or nodes.

It's available for preview in v1.0.0-dev.408+f4e245b4 (JSR & npm).

https://unstable.fedify.dev/manual/mq#parallel-message-processing

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

We were very excited to demo Channel. org & Patchwork at the fourth edition of FediForum - the virtual unconference moving the decentralised social web forwards.

You can see the video here: spectra.video/w/42kMTHaxxqYwD6 or on YouTube (we'll add a link further down the thread).

Keep reading to see a summary of our time at @fediforum from @FreddieJ 🧵 👇

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Q: Which does your implementation implement, HTTP Signatures, Linked Data Signatures, or Object Integrity Proofs?

Fedify: Y·E·S!

洪 民憙(ホン・ミンヒ)'s avatar
洪 民憙(ホン・ミンヒ)

@hongminhee@fedibird.com

Fedifyの次のバージョンであるv1.0.0がリリースされれば、APIは安定化される予定です。APIが安定化する前に入れて欲しい機能は何か有りますか?


QT: hollo.social/@fedify/019208ce-
[参照]

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Once the next version of , v1.0.0, is released, the API will be stabilized. Are there any features you'd like to see before the API is stabilized?

jonny (good kind)'s avatar
jonny (good kind)

@jonny@neuromatch.social

alright, after like a year of halfheartedly trying on and off, is pretty much finished - the problem of not being able to see all replies to a post is one of the largest complaints that people have with mastodon in particular but also the fedi in general. It is an especially potent problem for smaller servers, making them feel lonely, and making the whole fedi seem quiet. It is also a large contributor to the 'reply guy' problem where a moderately popular post will get the same replies over and over again and people won't even know they're doing it.

This patch recursively fetches replies using activitypub collections. it does it respectfully, only when someone is explicitly looking at a post (rather than fetching all replies for everything all the time) with some debounce, and spaces out the recursive calls to the other servers in deep threads.

the only thing left is to make the posts get inserted into the web client as they are received, currently you need to refresh to see them.

trying it locally now and it is a game changer.

i'm not "good at ruby" so if you ever wanna see this upstream, kindly spare a code review?

github.com/NeuromatchAcademy/m

silverpill's avatar
silverpill

@silverpill@mitra.social

I'm working on a Rust library for building ActivityPub apps:

https://codeberg.org/silverpill/mitra/src/branch/main/apx_sdk

This code was originally a part of Mitra, but over time I moved re-usable functions into independent packages and then started using them in other projects, Activity Connect and fep-ae97-client. Compared to activitypub-federation-rust, it is a low-level library with fewer dependencies, suitable for both servers and clients. The key feature is support for nomadic identity.

Currently there's no documentation and API is not well designed, but I will be improving it. The license is AGPL-3.0

#fedidev #fep_ef61

:neobread: Bolet :neobread:'s avatar
:neobread: Bolet :neobread:

@javascript@app.wafrn.net

Wafrn mobile app now can like, rewoot, follow, and react with emojis

It's only a few more improvements till it's completed and it's going to be great
#fedidev #wafrn-dev
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to 洪 民憙 (Hong Minhee)'s post

One of the benefits of is that you don't have to worry about whether a property of an Activity Vocabulary object has a URL or embeds an actual object. If you need an object, you can call the `getObject()` method (which will fetch a remote object if necessary). If you need a URI, you can access the `objectId` property.

fedify.dev/manual/vocab#object

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Quick question: would it be okay to embed a collection object in the `as:replies` property of `as:Note` & `as:Article` objects instead of putting the URL to the collection in the `as:replies` property? In theory, it would be okay, but would the actual implementations handle it well?

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Phanpy and Elk are both great web clients for fediverse platforms that support the mastodon api.

Did you know that both utilize a third party mastodon api library written in JavaScript?

Masto.js makes those applications possible! Give some props to the creator and maintainer, @neet

github.com/neet/masto.js

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

has a Saturday schedule, and it's starting in less than two hours. You can still register to attend, with some (almost) free tickets available at $1.99 if the regular rate is too high - a bargain for attending a single day of the event.

My favorite part is the demos - you get to see the people behind the sites and apps you use (or will be using), demoing their latest fediverse related projects!

fediforum.org/

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Compared to @hollo, @fedify seems to have less people contributing patches. Would this imply that 's codebase is harder to read or to modify?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

The next version of will support (), which means that Fedify will be able to verify activities forwarded by from other servers.

In addition, activities sent with the Context.sendActivity() method will have Linked Data Signatures attached in addition to HTTP Signatures if any RSA-PKCS-v1.5 key pairs are present.

We were not motivated by implementing Linked Data Signatures, which is already an outdated standard, but we hope this change will lead to better compatibility and interoperability of Fedify apps!

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

Show time: Patchwork & Channel. org debut 💫

In a couple of hours we’ll be back at and we’re excited to be debuting our new projects on Saturday, Channel. org and Patchwork - opening for early access soon.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Working on @fedify's docs about … I hope someday drop the support for Linked Data Signatures… 😇

The combination of HTTP Signatures and Linked Data Signatures is the most widely supported way to sign activities in the fediverse, as of September 2024. Despite Linked Data Signatures is outdated and not recommended for new implementations, it is still widely used in the fediverse due to Mastodon and other major implementations' reliance on it.

However, for new implementations, you should consider using both Object Integrity Proofs and Linked Data Signatures for maximum compatibility and future-proofing.
ALT text detailsThe combination of HTTP Signatures and Linked Data Signatures is the most widely supported way to sign activities in the fediverse, as of September 2024. Despite Linked Data Signatures is outdated and not recommended for new implementations, it is still widely used in the fediverse due to Mastodon and other major implementations' reliance on it. However, for new implementations, you should consider using both Object Integrity Proofs and Linked Data Signatures for maximum compatibility and future-proofing.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

The next release will finally be 1.0.0. Stay tuned!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

has a side effect that when you call the getter method of an Activity Vocabulary object, the property that was internally a URI is populated with the actual ActivityStreams object. Today, someone at Ghost gave us a cool term for this: .

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Does also attach to activities? If so, what types of activities does it attach LD Signatures to?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

The `fedify inbox` command, which is shipped with @fedify/cli, is a tool that creates an ephemeral server so that you can debug and test the activities you send.

Here's a demo of it.

fedify.dev/cli#fedify-inbox-ep

A demo video of fedify inbox command.
ALT text detailsA demo video of fedify inbox command.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I received a request from @ghost today to add to @fedify for compatibility with , as Mastodon does not plan to implement Object Integrity Proofs (FEP-8b32) for the near future. 😩

However, Mastodon's implementation of LD Signatures does not even use valid JSON-LD properties (despite the name), so I'm not sure how to make it compatible with Mastodon since does JSON-LD processing. 🤔

The JSON-LD representation of a Create(Note) activity containing LD Signatures produced by Mastodon and its expanded form. The “signature” property and its child properties are not properly namespaced.
ALT text detailsThe JSON-LD representation of a Create(Note) activity containing LD Signatures produced by Mastodon and its expanded form. The “signature” property and its child properties are not properly namespaced.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fedify, an server framework, has released v0.15.0! The key changes include:

It is now available in JSR and npm.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I have a question about the `liked` collection in the specification. According to section 5.5, the liked collection is “a list of every object from all of the actor's `Like` activities”, whereas the side note in section 5.7 says it is “a collection of `Like` activities performed by the actor”. What is the element type of the liked collection, `Object` or `Like`?

• Section 5.5: w3.org/TR/activitypub/#liked
• Section 5.7: w3.org/TR/activitypub/#likes

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

I'm glad that @fediforum added a weekend date. It's tough to get away during the week for me. FYI, the demos are usually first thing in the mornings and are a can't miss - worth the price for those alone IMO.

Check WeDistribute for live coverage of the event!

flipboard.com/@wedistribute/ac

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

As Firefish maintenance begins to wind down, IceShrimp offers a migration guide.

iceshrimp.dev/iceshrimp/iceshr

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to 洪 民憙 (Hong Minhee)'s post

In the next version of , it will allow you to decouple actor URIs from WebFinger usernames with the mapHandle() method. For example, you can use UUIDs for actor URIs but let users use their own username of choice for their fediverse handle.

You can preview it in v0.15.0-dev.382+a8a9b73b: JSR & npm.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I wish would just implement FEP-8b32 instead of the LD Signatures which is obsolete.

w3id.org/fep/8b32

marius's avatar
marius

@mariusor@metalhead.club

I often struggle with working on non-trivial, long standing projects because when I sit down to do the work after some hiatus, I can't seem to find the pain points I wanted to fix quickly enough.

It feels like trying to get a bandaid off when you can't find an edge where it comes unstuck easily enough.

The largest piece of bandaid that I wasn't able to get unstuck from the ActivityPub adjacent work is getting the HTTP-signatures working well with the rest of the fediverse (by which I mean Mastodon).

Today I might have got the corner of another little bit of bandaid unstuck which hopefully will help in the long run.

Chee Aun 🤔's avatar
Chee Aun 🤔

@cheeaun@mastodon.social

👀 Very interesting post visibility comparison table by Stefano, on this code review for adding Akkoma/Pleroma's Local-only posting on Phanpy github.com/cheeaun/phanpy/pull

Table comparing visibility options on Akkoma and Pleroma federated software, detailing who can see posts in different timelines (Direct messages, Home timeline, Public profile, Local timeline, Federated timeline) using various emojis to represent visibility levels.
ALT text detailsTable comparing visibility options on Akkoma and Pleroma federated software, detailing who can see posts in different timelines (Direct messages, Home timeline, Public profile, Local timeline, Federated timeline) using various emojis to represent visibility levels.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We just finished drafting a new tutorial for ! This tutorial will walk you through the steps of creating your own federated . It's pretty long, though.

Please read it, give us feedback, and have fun!

https://unstable.fedify.dev/tutorial/microblog

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Are there any features you'd like to see in ?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fedifyは、TypeScriptとJavaScriptで書かれたActivityPubサーバーフレームワークです。分散型のソーシャルネットワークを構築するためのサーバーアプリケーションを作る際の複雑さと冗長なコードを排除し、ビジネスロジックとユーザー体験の開発に集中できるようにすることを目指しています。

現在提供している主な機能は以下の通りです:

  • Activity Vocabularyのための型安全なオブジェクト(一部のベンダー固有の拡張機能を含む)
  • WebFingerクライアントとサーバー
  • HTTP SignaturesObject Integrity Proofs
  • ウェブフックを処理するためのミドルウェア
  • NodeInfoプロトコル
  • Node.js、Deno、Bunのサポート
  • テストとデバッグのためのCLIツールチェーン

興味がある方は、Fedifyのウェブサイトをご覧ください!包括的なドキュメント、デモ、チュートリアル、サンプルコードなどが用意されています:

https://fedify.dev/

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

During the development of , I ended up with too many accounts that I created to test.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Question for those who have followed the tutorial: How long did it take you to follow the tutorial?

OptionVoters
30 minutes or shorter1 (33%)
1 hour or shorter1 (33%)
2 hours or shorter1 (33%)
4 hours or shorter0 (0%)
More than 4 hours0 (0%)
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I finally finished the first draft of the new tutorial, but it's still in Korean. Now I just need to polish it up and translate it into English.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Did you know? offers the markdown-it plugins for parsing -style mentions and hashtags syntax:

Check it out!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I wish there was a more fancy canonical permalink for each document.

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

@index is out with another amusing blog post about their fediverse journey. But the most important thing we learned is that this account exists.

mastodon.social/@activitypugte

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Dear developers of the , has anyone ever encountered a case where a personal inbox in responds with a 404 Not Found for a POST request?

app.warp.dev/block/vKJGDbgWHBE

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

@subclub is a new way to add a paid subscriber link to your fediverse profile, allowing you to create subscriber only content! You get a really nice "Subscribe" button on the Mammoth and Ice Cubes app.

If you are a fediverse app developer and interested in adding this to your app, reach out to subclub directly and they can get your started!

Here's a walk through of how to get it setup.

video.everythingbagel.me/w/rXv

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Suddenly, I'm reminded of a service called Yahoo! Pipes from about 15 years ago. If anyone remembers, handled as its primitive, and now I'd like to see something like Pipes handle as its primitive.

en.wikipedia.org/wiki/Yahoo!_P

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We've released v0.14.0 of , the server framework, with the following key changes:

Fedify v0.14.0 is available from JSR and npm. See also the full changelog for details.

Happy !

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to John Spurlock's post

We've added the Inspecting ActivityPub objects section to the docs, introducing BrowserPub and the fedify lookup command!

https://unstable.fedify.dev/manual/test#inspecting-activitypub-objects

Inspecting ActivityPub objects

BrowserPub

BrowserPub is a browser for debugging ActivityPub and the fediverse. You can punch in any ActivityPub discoverable web URL or fediverse handle, and it will discover and display the underlying ActivityPub.

For example:

• hollo.social/@fedify
• @hongminhee@fosstodon.org

If you want to know further details about BrowserPub, read the creator's Mastodon thread.

fedify lookup command

Fedify provides a CLI toolchain for testing and debugging. The fedify lookup command is a simple tool for looking up an ActivityPub object by its URL or fediverse handle.
ALT text detailsInspecting ActivityPub objects BrowserPub BrowserPub is a browser for debugging ActivityPub and the fediverse. You can punch in any ActivityPub discoverable web URL or fediverse handle, and it will discover and display the underlying ActivityPub. For example: • hollo.social/@fedify • @hongminhee@fosstodon.org If you want to know further details about BrowserPub, read the creator's Mastodon thread. fedify lookup command Fedify provides a CLI toolchain for testing and debugging. The fedify lookup command is a simple tool for looking up an ActivityPub object by its URL or fediverse handle.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Do you know that? Some of the properties in Activity Vocabulary have been renamed in 's JavaScript APIs. Below are some examples:

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Even I have no idea how much 's API will change, so I don't know when I'll release Fedify 1.0.0. 🤦

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Is there any standardized for -style quotes?

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Hollo를 소개합니다!

Hollo는 개인을 위한 연합형 마이크로블로그 소프트웨어입니다. FedifyBun으로 만들어졌으며, 프로토콜을 통해 다른 인스턴스 및 서비스와 교류할 수 있습니다.

Hollo의 특징은 한 사용자를 위해 설계된 전용 인스턴스라는 점입니다. 이를 통해 사용자는 자신만의 공간을 가지면서도 , 및 기타 ActivityPub 지원 서비스의 사용자들과 소통할 수 있습니다.

독자적인 웹 인터페이스는 없지만, Mastodon API와 호환되어 기존의 많은 Mastodon 클라이언트 앱을 사용하여 Hollo에 접근할 수 있습니다. 이로 인해 익숙한 인터페이스로 Hollo를 이용할 수 있습니다.

주요 기능으로는 게시물 작성·편집·삭제, 답글, 미디어 첨부, 투표, 좋아요, 북마크, 고정 등이 있습니다. 또한 프로필 편집, 팔로우/팔로워 관리, 리스트 생성 등도 가능합니다. 더불어 Markdown을 지원하여 게시물이나 프로필의 서식 설정을 쉽게 할 수 있습니다.

Hollo는 현재 개발 초기 단계에 있으며, 지속적으로 기능 추가와 개선이 이루어지고 있습니다. Bun을 사용함으로써 빠른 성능과 효율적인 개발이 이뤄지고 있답니다. 오픈 소스 프로젝트로 GitHub에 공개되어 있으며, 커뮤니티의 기여를 환영합니다.

개인 블로그와 소셜 미디어의 장점을 결합한 Hollo는 프라이버시를 중시하면서도 더 넓은 커뮤니티와의 연결을 원하는 사람들에게 적합한 플랫폼으로 거듭나고 있습니다.

https://github.com/dahlia/hollo

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Holloを紹介します!

Holloは、個人向けの連合型マイクロブログソフトウェアです。FedifyBunを基盤に構築され、ActivityPubプロトコルを通じて他のインスタンスやサービスと連携することができます。

Holloの特徴は、一人のユーザーのために設計された専用のインスタンスという点です。これにより、ユーザーは自分だけのスペースを持ちながら、Mastodon、Misskey、その他のActivityPub対応サービスのユーザーとも交流できます。

独自のウェブインターフェースを持たない代わりに、MastodonのAPIと互換性があるため、既存の多くのMastodonクライアントアプリを使用してHolloにアクセスできます。これにより、使い慣れたインターフェースでHolloを利用することができます。

主な機能には、投稿の作成・編集・削除、返信、メディア添付、投票、お気に入り、ブックマーク、ピン留めなどがあります。また、プロフィール編集、フォロー/フォロワー管理、リスト作成なども可能です。さらに、Markdownをサポートしているため、投稿やプロフィールの書式設定が容易に行えます。

Holloは現在開発の初期段階にあり、継続的に機能の追加や改善が行われています。Bunを使用することで、高速なパフォーマンスと効率的な開発が実現されています。オープンソースプロジェクトとして、GitHubで公開されており、コミュニティからの貢献を歓迎しています。

個人のブログとソーシャルメディアの利点を組み合わせたHolloは、プライバシーを重視しながら、より広いコミュニティとのつながりを求める人々に適したプラットフォームとなっています。

https://github.com/dahlia/hollo

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

For educational purpose, I've created a federated microblog example using , with a total of about 30 commits, which you can follow step by step.

Now, I'm starting to write a hands-on Fedify tutorial based on this example code. I'll make it public when I'm done!

github.com/dahlia/microblog

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I've rewritten several times and in several languages. The first time it was written in , then , then C#, then back to TypeScript. (It was codenamed FediKit at the time of development.) I settled on TypeScript for the following reasons:

• It has a decent JSON-LD implementation.
• Lots of people use it. (I wanted Fedify to be widely used.)
• It's type-safe enough.

Even if I were to build Fedify again, I would choose TypeScript.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to 洪 民憙 (Hong Minhee)'s post

Also, a new logo for KR has been designed!

github.com/fedidevkr/logo

The new logo for FediDev KR with transparent background
ALT text detailsThe new logo for FediDev KR with transparent background
A variant of the new logo for FediDev KR with purple background
ALT text detailsA variant of the new logo for FediDev KR with purple background
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to 洪 民憙 (Hong Minhee)'s post

KR has decided to organize a sprint meetup later this month in Gangnam, Seoul (yes, the same Gangnam from Gangnam Style)!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Security alert for Fedify users

We've patched a vulnerability in the getActorHandle() function. Versions prior to 0.13.1 and 0.12.3 are affected.

Upgrade immediately:

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In the next version (v0.14.0) of , the performance of the Object.toJsonLd() method will be dramatically (~3k ×) faster. This is expected to improve the overall performance of Fedify apps!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I feel that the current abstraction level of is not high enough which makes the tutorial lengthy, so I'm considering adding a higher-level API. One way would be to add a façade to the @fedify/fedify package, and another way would be to create a sort of metaframework as a separate package (e.g., @fedify/start?). Which way would be better?

OptionVoters
Façade0 (0%)
Metaframework0 (0%)
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I'm writing a tutorial, and I keep saying things like “you don't need to know what Ed25519 is” and “you don't need to know what JWK is for this tutorial.” Would this be okay?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

The JSON-LD processor ended up being 's bottleneck, so I'm in the process of fixing Fedify to generate JSON-LD without the proper JSON-LD processor.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Does anyone know of any docs or specs for the activity type that and use?

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

"We want to bring organisations and content creators into the Fediverse, step by step."

Our Foundation co-founder has just published an interesting piece on how we're working to help organisations and content creators find their way to the Fediverse!

For more information on what we plan to do as a charity and how Patchwork, a new service we'll be launching soon, can help 👇
blog-pat.ch/enter-the-fedivers

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Fedify, the server framework, has released v0.13.0. Key changes include:

v0.13.0 is available now from JSR and npm.

https://github.com/dahlia/fedify/releases/tag/0.13.0

kopper [according to whom?] :colon_three:'s avatar
kopper [according to whom?] :colon_three:

@kopper@brain.d.on-t.work

question: is anyone federating thumbhashes of media yet? is there an existing extension i can adopt or should i just come up with my own?

i know mastodon federates blurhashes. i'm specifically asking about thumbhashes (
evanw.github.io/thumbhash/) instead.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

What other web frameworks would you like to see integrate with more?

OptionVoters
Koa4 (16%)
Fastify5 (20%)
Oak3 (12%)
Elysia3 (12%)
Next.js6 (24%)
Nuxt.js4 (16%)
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Introducing @fedify/express, a package that integrates Express, a popular web framework in Node.js, with Fedify. You can install it with the following command:

npm add @fedify/express

This package provides a middleware called integrateFederation() that allows you to integrate with :

import express from "express";
import { integrateFederation } from "@fedify/express";
import { federation } from "./federation";  // Your `Federation` instance

export const app = express();

app.set("trust proxy", true);

app.use(integrateFederation(federation, (req) => "context data goes here"));

https://github.com/dahlia/fedify-express

infinite love ⴳ's avatar
infinite love ⴳ

@trwnh@mastodon.social

i wonder how many people realize that building a fedi viewer is on the scale of complexity of building a web browser

꧁ wakest ꧂'s avatar
꧁ wakest ꧂

@liaizon@social.wake.st

This is a milestone worth celebrating! :fediverse:
In development as we speak, @forgejo can now federate comments (and tons of other stuff) from issues in repos!!!

The first screenshot is @algernon (a Forgejo account able to be tagged in this post!) commenting on the issue: shoes.forgejo.madhouse-project as seen in @phanpy while logged into my Mastodon account!

a screenshot of a Fogejo account with comments as seen through a Mastodon account logged into Phanpy
ALT text detailsa screenshot of a Fogejo account with comments as seen through a Mastodon account logged into Phanpy
a screenshot of a Fogejo issue that contains comments that are viewed in the previous screenshot
ALT text detailsa screenshot of a Fogejo issue that contains comments that are viewed in the previous screenshot
Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

@mastometrics is a unique way to look at statistics about your own account - for free. It's even connected directly from your profile in the @IceCubesApp app.

But all that data and storage costs money! Please consider contributing to keep this service going - and if the goal is reached, open sourced to make it self-hostable.

ko-fi.com/robertvh

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

We’re committed to helping people find their place in the Fediverse and wider Social Web.

We’ve helped hundreds of people, across multiple platforms, understand the idea by stripping down the tech and reimagining it.

We’ve put that learning in a video. It won’t answer all the questions, but it’s a strong starting point to help explain the Fediverse to outsiders.

Please share it to help educate others.

youtu.be/upEHFtO9vrI

ilja :pumpkin_owo:'s avatar
ilja :pumpkin_owo:

@ilja@ilja.space

this is my first FEP; there's a bunch of todo's left, but i think it already gives a good view of what it will become https://codeberg.org/ilja/fep/src/branch/fep-c16b_formatting_mfm_functions/fep/c16b/fep-c16b.md

#fedidev
Abelio's avatar
Abelio

@abelio@mastodon.social

FYI: Abelio will provide couple of ways of publishing visual contents. One of them is part of the article editor and it let's you organise multiple images in a form of a flexible grid you can arrange as needed.

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

If you read a , what software would you like to see as an in the tutorial?

OptionVoters
Microblog (like Mastodon)21 (32%)
Long-form blog (like WordPress)10 (15%)
Photo blog (like Pixelfed)7 (11%)
Forum (like NodeBB)6 (9%)
Link aggregator (like Lemmy)9 (14%)
Much simpler one!13 (20%)
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

A good issue to contribute to for the first time. Anybody interested?

github.com/dahlia/fedify/issue

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I finally turned the Federation class into an interface now!

github.com/dahlia/fedify/commi

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

"Our Foundation mission is “knowledge for all for good”. Using social media to share knowledge for the benefit of society."

Our co-founder, @michael , is discussing why The Newsmast Foundation is building new technology to benefit organisations and server admins on the Social Web.

Read it here: blog-pat.ch/content-technology

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

, an server framework, has released v0.12.0. It's a minor release in about a month, so there's quite a few changes:

It's available on JSR and npm now, and you can upgrade it using the deno add command on Deno:

deno add @fedify/fedify@^0.12.0

Or using the bun add command on Bun:

bun add @fedify/fedify@^0.12.0

Or using the npm add command on Bun:

npm add @fedify/fedify@^0.12.0

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Since v0.12.0, when verifying HTTP Signatures or Object Integrity Proofs, it will cache the public keys once fetched. It is okay even if a cached key becomes outdated because a verification failure due to a cached key will invalidate the cache and force a verification retry.

This feature is available for preview in v0.12.0-dev.307+235629d5 (JSR or npm).

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Working on the `fedify init` command, the project setup wizard for

A demo of the `fedify init` command. The JavaScript runtime choices are Deno, Node.js, and Bun, of which Deno is selected. The web framework choices are Bare-bones, Astro, Fresh, and Hono, with Hono selected. The key-value store options are No cache, Redis, and Deno KV, with Deno KV selected. The message queue options are No background jobs, Redis, Deno KV, and Deno KV is selected. Finally, an Hono project integrated with Fedify is created and the server is started by running the `deno task dev` command.
ALT text detailsA demo of the `fedify init` command. The JavaScript runtime choices are Deno, Node.js, and Bun, of which Deno is selected. The web framework choices are Bare-bones, Astro, Fresh, and Hono, with Hono selected. The key-value store options are No cache, Redis, and Deno KV, with Deno KV selected. The message queue options are No background jobs, Redis, Deno KV, and Deno KV is selected. Finally, an Hono project integrated with Fedify is created and the server is started by running the `deno task dev` command.
Newsmast's avatar
Newsmast

@newsmast@newsmast.social

"Our aim is to offer organisations and server admins an easy-to-use console where extra features can easily be added to their Mastodon server."

If you liked our update on Patchwork from @FreddieJ yesterday, we have good news!

Newsmast Foundation co-founder @michael has just shared a look behind the scenes at Patchwork production ready for @fediforum in September.

Check it out: blog-pat.ch/patchwork-progress

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Just read an email newsletter from @newsmast about their upcoming Patchwork platform. It’s a plugin system to extend existing fediverse platforms.

One of their upcoming plugins will be local only posts. It’s a nice feature I used on Firefish, allowing nonfederated community discussions. Looking forward to it!

newsmast.social/@newsmast/1128

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

This week we want to talk to you about Patchwork, an upcoming project, using technology we developed for Newsmast to make new and existing spaces on the social web more safe, more connected and more fun!

Here’s an update from our Foundation Ambassador @FreddieJ 👇

Newsmast's avatar
Newsmast

@newsmast@newsmast.social

It’s been a week since the UK General Election. As one of the UK’s leading Fediverse projects, we thought this would be a good time to look into the new government's digital policy and what it could mean for Fedi.

You can read the full blog by @FreddieJ here: newsmastfoundation.org/our-blo

Or check out the thread below 👇

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

offers robust logging capabilities through integration with LogTape. This feature allows you to easily debug and monitor your Fedify app!

To enable , simply install the @logtape/logtape package and configure it in your app's entry point:

import { configure, getConsoleSink } from "@logtape/logtape";

await configure({
  sinks: { console: getConsoleSink() },
  filters: {},
  loggers: [
    { category: "your-app", sinks: ["console"], level: "debug" },
    { category: "fedify",   sinks: ["console"], level: "info" },
  ],
});

Fedify uses hierarchical categories for fine-grained control over log output. Key categories include ["fedify", "federation", "http"] for HTTP requests/responses and ["fedify", "federation", "inbox"]/["fedify", "federation", "outbox"] for incoming/outgoing activities. (There are more categories.)

With integration, you gain valuable insights into your Fedify app's behavior, making troubleshooting and optimization much more straightforward!

https://fedify.dev/manual/log

Bivouac Wiki's avatar
Bivouac Wiki

@bivouacwiki@tech.lgbt

let's say Monday is the due date for the docs rewrite.

and July is single instance buildin' month.

August is fediverse vocab buildin' month.

Wanna have something to talk about at the Denver meetup September 3rd.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I want to create good first issues for @fedify, but I don't have a good idea of appropriate tasks for first-time contributors. Any ideas?

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social · Reply to Fedify: an ActivityPub server framework's post

Ready to simplify your ? Check out !

Join us in building a more connected and decentralized web! 🌐

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In 's next release, v0.12.0, we'll be adding support for integration with Astro, a web framework for content-driven websites.

https://unstable.fedify.dev/manual/integration#astro

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We released 0.9.2, 0.10.1, and 0.11.1, which patched the last reported , CVE-2024-39687, but the vulnerability of SSRF attacks via DNS rebinding still exists, so we released Fedify 0.9.3, 0.10.2, and 0.11.2, which fixes it.

If you are using an earlier version, please update as soon as possible.

Thanks to @benaryorg for reporting the vulnerability!

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Streams just nonchalantly mentions adding nomadic identity over ActivityPub in the latest release. 🤯

From: @streams
fediversity.site/item/d9dd01e1

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

We're releasing @fedify/h3! Now you can integrate with h3, an HTTP server framework behind Nitro, Analog, Vinxi, SolidStart, TanStack Start, and other many web frameworks.

https://github.com/dahlia/fedify-h3

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

This morning I'm working through some trailhead modules for Salesforce. They have a social activity feed called "Chatter" that allows you to follow objects of any kind - people, groups, articles, database records.

Sound familiar? For whatever reason, they put a limitation that each account can only follow up to 500 objects. How many heads would explode if someone built an ActivityPub, Nostr or ATProto plugin for Salesforce? :AngeryCat:

help.salesforce.com/s/articleV

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Finally, @ghost has open sourced their implementation powered by ! For Fedify users, this means another production-grade example code.

If you'd like to follow updates on 's ActivityPub implementation, you can do so by following @index!

https://github.com/TryGhost/ActivityPub

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I jsut wrote a detailed post on my blog about @ghost's for @fedify! (Both English and Korean available.)

writings.hongminhee.org/2024/0

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to 洪 民憙 (Hong Minhee)'s post

now has a queue for incoming activities and they are automatically retried when they fail. The default retry strategy is good enough (exponential backoff + decorrelated jitter), and it's even fully customizable. Updated also the docs:

unstable.fedify.dev/manual/inb

You can give it a try by installing 0.12.0-dev.265+cb851932, the latest unstable release:

jsr.io/@fedify/fedify@0.12.0-d
npmjs.com/package/@fedify/fedi

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

In the next version of , the type is introduced to let you fully customize the retry policy of the task queue for incoming and outgoing activities. Of course, you can also simply adjust the parameters of the built-in exponential backoff + decorrelated jitter policy.

outboxRetryPolicy

This API is available since Fedify 0.12.0.

The retry policy for sending activities to recipients' inboxes.

By default, this uses an exponential backoff strategy with a maximum of 10 attempts and a maximum delay of 12 hours.

You can fully customize the retry policy by providing a custom function that satisfies the RetryPolicy type. Or you can adjust the parameters of the createExponentialBackoffRetryPolicy() function, which is a default implementation of the retry policy.
ALT text detailsoutboxRetryPolicy This API is available since Fedify 0.12.0. The retry policy for sending activities to recipients' inboxes. By default, this uses an exponential backoff strategy with a maximum of 10 attempts and a maximum delay of 12 hours. You can fully customize the retry policy by providing a custom function that satisfies the RetryPolicy type. Or you can adjust the parameters of the createExponentialBackoffRetryPolicy() function, which is a default implementation of the retry policy.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Basic implementation of the inbox queue is complete and documentation is being worked on.

hollo.social/@fedify/0190687b-

Making inbox listeners non-blocking

This API is available since Fedify 0.12.0.

Usually, processes inside an inbox listener should be non-blocking because they may involve long-running tasks. Fortunately, you can easily turn inbox listeners into non-blocking by providing a queue option to createFederation() function. If it is not present, incoming activities are processed immediately and block the response to the sender until the processing is done.

While the queue option is not mandatory, it is highly recommended to use it in production environments to prevent the server from being overwhelmed by incoming activities.

Note: Activities with invalid signatures/proofs are silently ignored and not queued.
ALT text detailsMaking inbox listeners non-blocking This API is available since Fedify 0.12.0. Usually, processes inside an inbox listener should be non-blocking because they may involve long-running tasks. Fortunately, you can easily turn inbox listeners into non-blocking by providing a queue option to createFederation() function. If it is not present, incoming activities are processed immediately and block the response to the sender until the processing is done. While the queue option is not mandatory, it is highly recommended to use it in production environments to prevent the server from being overwhelmed by incoming activities. Note: Activities with invalid signatures/proofs are silently ignored and not queued.
Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

In the next version of , the Context.hostname, Context.host, and Context.origin properties will be added for better multitenancy/virtual hosting support.

https://github.com/dahlia/fedify/issues/66#issuecomment-2198967566

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to 洪 民憙 (Hong Minhee)'s post

When there is no queue, if the process fails, the inbox can just respond with a 500 server error and the sender will resend it.

But with a queue, by the time the inbox responds, it doesn't know if the process will fail because it hasn't run yet. So the sender won't retry whether it fails or not.

So, should it have its own retry logic when there is a queue?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I'm adding a queue for incoming activities in , and I have a concern. If an error occurs while processing an activity, should it retry?

hollo.social/@fedify/0190687b-

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

has always been queuing outgoing activities, but not incoming activities. Thanks to @ghost's sponsorship, we are now implementing queues for incoming activities!

https://github.com/dahlia/fedify/issues/70

Tokyo Outsider (337ppm)'s avatar
Tokyo Outsider (337ppm)

@tokyo_0@mas.to

, and question: If instances generally collect only one copy of each post and then share it with the users that need to see it, does that mean nonoriginating instances are trusted to not show that post to users the poster has blocked (or who shouldn't see it because they're not following etc depending on visibility)?

How do the collecting instances know who should see it? (A cached copy of the poster's follow list?)

And does change any of this?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Today we created KR, a community for Korean people who are not only implementing fediverse servers, but also those who are running them, such as server operators, moderators, client app developers, bot developers, writers, translators, researchers, and more. For now, we're based on a Discord server, but we hope to eventually organize offline meetups and workshops. We'd love your support!

fedidev.kr/

Tokyo Outsider (337ppm)'s avatar
Tokyo Outsider (337ppm)

@tokyo_0@mas.to

How long (hours, roughly) would it take to implement a basic server from scratch in — absoluet bare bones, like a proof of concept just capable of sending and receiving posts, which could then be developed more before becoming a finished, user-ready system?

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to 洪 民憙 (Hong Minhee)'s post

먼저 Discord에 KR 서버를 하나 만들었습니다!

discord.gg/B2ABMBpHNA

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

서울에서 모임하는 생각 💭

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

is an server framework in & . It aims to eliminate the complexity and redundant boilerplate code when building a federated server app, so that you can focus on your business logic and user experience.

The key features it provides currently are:

• Type-safe objects for Activity Vocabulary (including some vendor-specific extensions)
client and server
• HTTP Signatures
• Middleware for handling webhooks
protocol
.js, , and support
• CLI toolchain for testing and debugging

If you're curious, take a look at the Fedify website! There's comprehensive docs, a demo, a tutorial, example code, and more:

fedify.dev/

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

has supported optional queuing for outgoing activities, with two built-in message queue backends: InProcessMessageQueue, which is suitable for development, and DenoKvMessageQueue, which is only available in Deno.

Fedify has also had two built-in cache backends, MemoryKvStore, which is suitable for development, and DenoKvStore, which is only available in Deno.

Now, however, by installing the @fedify/redis package, you can use as both a message queue backend and a cache backend! Unlike DenoKvMessageQueue and DenoKvStore, it's also available for .js and .

This feature was made possible with the support of @ghost.

https://github.com/dahlia/fedify-redis

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org · Reply to Jaeyeol Lee (a.k.a. kodingwarrior) :vim:'s post

@kodingwarrior 한국에도 모임 같은 거 개최하면 좋겠어요 ㅎㅎ

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

now has the official account! Please follow @fedify!

hollo.social/@fedify/01905d6a-

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

Hello, ! It's the official fedi account of the Fedify, an server framework!

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

Found a memory leak (on ) in recent commits of —be careful when using the unstable versions.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

I wish there was a meetup in too…

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

development is often motivation to add features to , for example, most of the commits I added to Fedify today were for Hollo.

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@fosstodon.org

If you'd like to support the development of or , you can sponsor me on GitHub!

github.com/sponsors/dahlia

Hollo :hollo:'s avatar
Hollo :hollo:

@hollo@hollo.social

Introducing . Hollo is an -enabled single-user microblogging software. Although it's for a single user, it also supports creating and running multiple accounts for different topics.

It's headless, meaning you can use existing client apps instead, with its Mastodon-compatible APIs. It has most feature parity with Mastodon. Two big differences with Mastodon is that you can use in the content of your posts and you can quote another post.

Oh, and Hollo is built using and .

https://github.com/dahlia/hollo

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

Version 0.10.0 of , an server framework, has been released! Starting with this release, Fedify, previously distributed under AGPL 3.0, is now distributed under the MIT License to encourage wider adoption. Here are the major changes:

• In addition to RSA-PKCS#1-v1.5, Fedify now supports Ed25519 for signing and verifying the activities.
• FEP-521a: Multiple key pairs can now be registered for an actor.
• FEP-8b32: Implemented Object Integrity Proofs.
• Added Arrive and Question classes.

github.com/dahlia/fedify/relea

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

TIL when you upload a video file to Mastodon, it generates a preview thumbnail. The thumbnail isn't passed through to other servers in the ActivityPub payload (similar to preview cards).

Each receiving platform handles this situation differently. Some regenerate a thumbnail (processing again). Some ignore it and don't show one. Others create blank thumbnails to appease the Mastodon API.

A blurhash is passed, tho, and could be used as a placeholder.

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

@hollo is a testbed for the bleeding edge of . 😂

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

sends Create(Question) for the poll, even though the Question itself is an Activity. Does it see Question as a regular Object rather than an Activity?

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

I'm very excited that the team has chosen to implement . I've been working closely with the Ghost team, and it's been a lot of fun, and I can't wait to see the ActivityPub implementation at Ghost.

activitypub.ghost.org/day-4/

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Ghost will be using the open source Fedify server framework to manage the activitypub bits and pieces of their service.

activitypub.ghost.org/day-4/?r

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu · Reply to 洪 民憙 (Hong Minhee) 🤏🏼's post

Thanks to @silverpill, is finally FEP-8b32 compliant! Though it's not ready for general release yet, it's passing tests in the latest main branch. I'll test it with Mitra and other FEP-8b32-compliant implementations, and if it works well, it'll be included in 0.10.0.

You can try it out in version 0.10.0-dev.205+0cbca257.

jsr.io/@fedify/fedify@0.10.0-d

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

I just released 0.9.1, which fixed one small bug.

github.com/dahlia/fedify/relea

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

now supports sharing posts (reblogs)!

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

Bonfire, the modular Fediverse platform, is looking for five Elixir developers to act as test subjects to improve the developer onboarding experience. Participants can receive a €50 stipend for their one-hour session.

Please share with your elixir dev friends, and boost!

bonfirenetworks.org/posts/surv

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu · Reply to 洪 民憙 (Hong Minhee) 🤏🏼's post

Implementing Object Integrity Proofs (FEP-8b32) and my implementation is not passing the test vectors. I haven't found the reason for 24 hours… 😫

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu · Reply to 洪 民憙 (Hong Minhee) 🤏🏼's post

FEP-521a has been implemented in .

Actors now have the property, and the class has been added. For example, if you look at the the actor from the Fedify Example Blog (fedify-blog.deno.dev/users/fed), you can see that it has the assertionMethods property in addition to the publicKey property.

You can try it out in version 0.10.0-dev.196+55cc34d1.

jsr.io/@fedify/fedify@0.10.0-d

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu · Reply to 洪 民憙 (Hong Minhee) 🤏🏼's post

throws an error when a remote actor has multiple public keys, so I sent a patch to fix this bug.

This is my first patch for Misskey!

github.com/misskey-dev/misskey

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

As a first step towards adding Object Integrity Proofs (FEP-8b32) to , I've made it support keys. I've also enabled multiple keys to be associated with an actor. For example, if you look at the actor from the Fedify Example Blog (fedify-blog.deno.dev/users/fed), you'll see that it has two public keys, one for RSA and one for Ed25519.

You can try it out in version 0.10.0-dev.190+4dffb89a.

jsr.io/@fedify/fedify@0.10.0-d

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

Version 0.9.0 of , an server framework, has been released! Here are the main changes:

• Added Tombstone, Hashtag, and Emoji classes.
• Added normalizeActorHandle() function to normalize an actor handle. This is needed when the domain of the actor handle is an IDN, or when the domain contains capital letters.
• Added an option to the sendActivity() function, excludeBaseUris, to exclude specified servers from sending activities. This can be used when you don't want to send activities to your own server.
• Added Context.parseUri(), a method to parse actor, object, inbox, and collection URIs.
• The time window for HTTP Signatures verification is now configurable.
• The @fedify/fedify/httpsig module has been renamed to . This is in preparation for implementing additional object integrity proofs other than HTTP Signatures.
• Improved interoperability with .

github.com/dahlia/fedify/relea

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu · Reply to 洪 民憙 (Hong Minhee) 🤏🏼's post

Now has several more features:

• Following/unfollowing accounts
• Following/unfollowing hashtags
• Post visibility
• Post language
• Editing profile
• Mentions
• Likes
• Bookmarks
• Notifications
• Markers

洪 民憙 (Hong Minhee) 🤏🏼's avatar
洪 民憙 (Hong Minhee) 🤏🏼

@hongminhee@todon.eu

I'm rebuilding from scratch, and I've implemented some -compatible APIs to let me do the following actions with and now:

• Logging in
• Composing a post
• Writing a reply
• View posts
• Public timeline
• Home timeline

✌️

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

I really like these support tables on the FunFedi website. Seeing the support grid and example responses is very helpful.

I know a lot of devs are jumping from chat room to chat room, looking for someone to reply back in their timelines, etc. to get help when a specific platform isn't working quite right.

funfedi.dev/support_tables/gen

Jeff Sikes's avatar
Jeff Sikes

@box464@mastodon.social

If you're curious how ActivityPub works exactly (like me) this site does a great job of show and tell.

On the surface it looks like any other Mastodon instance, but on closer inspection, provides you insight into the ActivityPub back and forth going on behind the scenes!

Check out the great work by @crepels

activitypub.academy/

The Activity Log shows the ActivityPub objects that are passed back and forth when a follow request is sent from one instance to another.
ALT text detailsThe Activity Log shows the ActivityPub objects that are passed back and forth when a follow request is sent from one instance to another.