Skip to main content

Fedify

Fedify is a comprehensive TypeScript framework for building federated server applications powered by ActivityPub.

Overview

PropertyValue
LanguageTypeScript
RuntimesDeno, Node.js, Bun
LicenseMIT
Websitefedify.dev
Repositorygithub.com/dahlia/fedify
npm@fedify/fedify
StatusActive, Production Ready

Key Features

Protocol Support

  • ActivityPub — Full server-to-server and client-to-server implementation
  • WebFinger — Built-in discovery
  • NodeInfo — Server metadata
  • HTTP Signatures — Request signing and verification
  • Linked Data Signatures — Document signing
  • Object Integrity Proofs — FEP-8b32 support

Developer Experience

  • Type-safe vocabulary — Full TypeScript types for Activity Vocabulary
  • Vendor extensions — Support for Mastodon, Misskey, and other extensions
  • Multiple runtimes — Deno, Node.js, and Bun
  • Framework adapters — Express, Fastify, Hono, Koa, SvelteKit
  • CLI toolchain — Development and testing utilities

Infrastructure

  • Database adapters — PostgreSQL, SQLite
  • Caching — Redis integration
  • Message queues — AMQP support for async delivery
  • Cloud deployment — Cloudflare Workers support
  • Observability — OpenTelemetry integration

Installation

Deno

import { createFederation } from "jsr:@fedify/fedify";

Node.js / Bun

npm install @fedify/fedify
import { createFederation } from "@fedify/fedify";

Quick Start

Basic Federation Setup

import { createFederation, Person, MemoryKvStore } from "@fedify/fedify";

const federation = createFederation({
kv: new MemoryKvStore(),
});

// Define actor dispatcher
federation.setActorDispatcher("/users/{handle}", async (ctx, handle) => {
// Fetch user from your database
const user = await db.getUserByHandle(handle);
if (!user) return null;

return new Person({
id: ctx.getActorUri(handle),
preferredUsername: handle,
name: user.displayName,
inbox: ctx.getInboxUri(handle),
outbox: ctx.getOutboxUri(handle),
followers: ctx.getFollowersUri(handle),
following: ctx.getFollowingUri(handle),
});
});

Handling Inbox Activities

federation.setInboxListeners("/users/{handle}/inbox")
.on(Follow, async (ctx, follow) => {
const follower = follow.actorId;
const followed = ctx.getActorUri(ctx.handle);

// Store follow relationship
await db.addFollower(ctx.handle, follower);

// Send Accept activity
await ctx.sendActivity(
{ handle: ctx.handle },
follower,
new Accept({ actor: followed, object: follow }),
);
})
.on(Undo, async (ctx, undo) => {
if (undo.object instanceof Follow) {
await db.removeFollower(ctx.handle, undo.actorId);
}
});

Sending Activities

import { Create, Note } from "@fedify/fedify";

// Create a post
const note = new Note({
id: ctx.getObjectUri(Note, { id: postId }),
attributedTo: ctx.getActorUri(handle),
content: "Hello, Fediverse!",
published: Temporal.Now.instant(),
to: new URL("https://www.w3.org/ns/activitystreams#Public"),
});

// Send to followers
await ctx.sendActivity(
{ handle },
"followers",
new Create({ actor: ctx.getActorUri(handle), object: note }),
);

Framework Integration

Express

import express from "express";
import { integrateFederation } from "@fedify/express";

const app = express();
integrateFederation(app, federation);

Hono

import { Hono } from "hono";
import { federation as fedifyMiddleware } from "@fedify/hono";

const app = new Hono();
app.use(fedifyMiddleware(federation));

Fastify

import Fastify from "fastify";
import { integrateFederation } from "@fedify/fastify";

const app = Fastify();
await integrateFederation(app, federation);

Database Integration

PostgreSQL

import { PostgresKvStore } from "@fedify/postgres";
import postgres from "postgres";

const sql = postgres("postgres://localhost/myapp");
const kv = new PostgresKvStore(sql);

const federation = createFederation({ kv });

Redis (Caching)

import { RedisKvStore } from "@fedify/redis";
import Redis from "ioredis";

const redis = new Redis();
const kv = new RedisKvStore(redis);

Activity Vocabulary

Fedify provides type-safe classes for the full Activity Vocabulary:

Core Types

import {
// Actors
Person, Group, Organization, Application, Service,
// Objects
Note, Article, Image, Video, Audio, Document,
// Activities
Create, Update, Delete,
Follow, Accept, Reject,
Like, Announce, Undo,
// Collections
Collection, OrderedCollection,
CollectionPage, OrderedCollectionPage,
} from "@fedify/fedify";

Vendor Extensions

import {
// Mastodon extensions
Emoji, PropertyValue, IdentityProof,
// Misskey extensions
MisskeyEmoji,
} from "@fedify/fedify";

Testing

Fedify includes testing utilities:

import { createFederatedServer } from "@fedify/fedify/testing";

// Spin up a test server
const server = await createFederatedServer(federation);

// Make test requests
const response = await server.handle(
new Request("https://example.com/users/alice"),
);

CLI Tools

# Install CLI
npm install -g @fedify/cli

# Lookup an actor
fedify lookup @user@example.com

# Validate an activity
fedify validate activity.json

# Start development server with live reload
fedify dev

Comparison with Other Libraries

FeatureFedifyactivitypub-expressmicrofed
TypeScript✅ Native
RuntimeDeno/Node/BunNode onlyNode only
FrameworkMultipleExpress onlyNone
LD Signatures
Object Integrity✅ FEP-8b32
Type-safe vocab
ComplexityHigherMediumLow

When to Use Fedify

Good for:

  • Production applications requiring full AP compliance
  • TypeScript projects wanting type safety
  • Apps needing multiple framework options
  • Projects requiring advanced signatures (LD Signatures, Object Integrity)

Consider alternatives if:

  • Building a minimal single-user server → Fedbox
  • Need simpler Express integration → activitypub-express
  • Want zero dependencies → microfed

Resources

See Also