A comprehensive example of building a federated server application using
Fedify with Astro via the @fedify/astro package. This sample
demonstrates how to create an ActivityPub-compatible federated social media
server that can interact with other federated platforms like Mastodon, Pleroma,
and other ActivityPub implementations. It supports Deno, Node.js, and
Bun runtimes.
The example uses Astro 7. The @fedify/astro package also supports Astro 5
and 6 through its dedicated compatibility matrix.
- ActivityPub Protocol Support: Full implementation of ActivityPub for federated social networking
- Actor System: User profile management with cryptographic key pairs
- Follow/Unfollow: Complete follow relationship handling with Accept/Undo activities
- Post System: Create and distribute posts to followers via the Create activity
- Inbox Processing: Real-time activity processing from federated instances
- Content Negotiation: Same routes serve HTML for browsers and ActivityPub JSON for federated clients
- Three Runtimes: Supports Deno, Node.js, and Bun via separate Astro configs
- TypeScript: Full type safety throughout the application
- astro.config.deno.ts registers
fedifyIntegration()to configure Vite's SSR settings for Fedify compatibility, and uses@deno/astro-adapterto run on Deno. - astro.config.node.ts registers
fedifyIntegration()and uses@astrojs/nodefor Node.js. - astro.config.bun.ts registers
fedifyIntegration()and uses@astrojs/nodestandalone output, which is built and run with Bun. - src/lib/store.ts defines in-memory stores for key pairs, follower relationships, and posts.
- src/lib/federation.ts sets up the full
Federationinstance with:- Actor dispatcher at
/users/{identifier}serving aPersonobject - Key pairs dispatcher for cryptographic signing
- Inbox listeners for
FollowandUndoactivities Noteobject dispatcher at/users/{identifier}/posts/{id}- Followers collection at
/users/{identifier}/followers
- Actor dispatcher at
- src/middleware.ts composes an additional Astro middleware with
fedifyMiddleware()usingsequence(). src/pages/users/[identifier]/index.astrorenders an HTML profile page. Fedify and Astro share the route and do content negotiation depending on theAcceptheader.src/pages/users/[identifier]/posts/index.astrolists posts and handles new post creation via a formPOST.src/pages/users/[identifier]/posts/[id].astrorenders an individual post detail page.
Note
When using Deno with Astro, you must use npm: specifiers (not jsr:) for
@fedify/fedify and @fedify/vocab in your deno.json due to Vite
compatibility limitations.
src/
├── middleware.ts # Fedify middleware entry point
├── lib/
│ ├── federation.ts # Main federation configuration
│ └── store.ts # In-memory data storage
├── layouts/
│ └── Layout.astro # Base layout with global styles
└── pages/
├── index.astro # Home page (handle & followers)
└── users/
└── [identifier]/
├── index.astro # User profile page
└── posts/
├── index.astro # Posts list & create form
└── [id].astro # Individual post detail
To run the dev server with Deno:
deno task devThis uses astro.config.deno.ts as the configuration file.
To run the dev server with Node.js:
pnpm devThis uses astro.config.node.ts as the configuration file.
To run the dev server with Bun:
bun run dev:bunThis uses astro.config.bun.ts as the configuration file.
To build and run the Bun server bundle:
bun run build:bun
bun run preview:bunThe Bun setup intentionally uses @astrojs/node 11. The previously used
@nurodev/astro-bun adapter only declares compatibility with Astro 5.
The application will be available at http://localhost:4321/.
To fetch the actor as ActivityPub JSON:
curl -H "Accept: application/activity+json" http://localhost:4321/users/demoOr using the Fedify CLI:
fedify lookup @demo@localhost:4321-
Start the development server:
deno task dev # or for Node.js pnpm dev # or for Bun bun run dev:bun
-
Visit the home page at http://localhost:4321/ to see the demo account handle and follower list.
-
Visit the profile page at http://localhost:4321/users/demo.
-
Create a post at http://localhost:4321/users/demo/posts.
-
The ActivityPub actor endpoint is available at:
fedify lookup @demo@localhost:4321
ActivityPub.Academy is a platform for learning about the ActivityPub protocol and its implementation.
To test federation with ActivityPub.Academy:
-
Deploy the application to a public server or use a tunneling service:
# Using Fedify CLI to tunnel fedify tunnel 4321 -
From your ActivityPub.Academy account, search for and follow:
@demo@<your-tunnel-host> -
The application will automatically:
- Receive the follow request
- Send an Accept activity back
- Store the follower relationship
- Display the follower on the home page
The federation setup is configured in src/lib/federation.ts:
const federation = createFederation<void>({
kv: new MemoryKvStore(), // In-memory storage for development
});-
Storage Backend:
- Development:
MemoryKvStore()(data lost on restart) - Production: Consider using persistent storage solutions
- Development:
-
Actor Identifier:
- Default:
"demo" - Modify the
IDENTIFIERconstant to change the demo user
- Default:
-
Demo Actor Profile:
- Name: “Fedify Demo”
- Summary: “This is a Fedify Demo account.”
- Icon: /demo-profile.png
If you are creating a new project based on this example, you only need the configuration file for your target runtime. Delete the unused ones and rename the one you keep to astro.config.ts:
rm astro.config.node.ts astro.config.bun.ts
mv astro.config.deno.ts astro.config.tsThen remove the --config flags from deno.json tasks:
{
"tasks": {
"dev": "deno run -A npm:astro dev",
"build": "deno run -A npm:astro build",
"preview": "deno run -A npm:astro preview"
}
}rm astro.config.deno.ts astro.config.bun.ts
mv astro.config.node.ts astro.config.tsThen remove the --config flags from package.json scripts:
{
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview"
}
}rm astro.config.deno.ts astro.config.node.ts
mv astro.config.bun.ts astro.config.tsThen update package.json scripts to use Bun's SSR entry point after build:
{
"scripts": {
"dev": "bunx --bun astro dev",
"build": "bunx --bun astro build",
"preview": "bun ./dist/server/entry.mjs"
}
}