Skip to content

Latest commit

 

History

History

README.md

Astro integration sample

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.

Features

  • 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

How it works

  • astro.config.deno.ts registers fedifyIntegration() to configure Vite's SSR settings for Fedify compatibility, and uses @deno/astro-adapter to run on Deno.
  • astro.config.node.ts registers fedifyIntegration() and uses @astrojs/node for Node.js.
  • astro.config.bun.ts registers fedifyIntegration() and uses @astrojs/node standalone 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 Federation instance with:
    • Actor dispatcher at /users/{identifier} serving a Person object
    • Key pairs dispatcher for cryptographic signing
    • Inbox listeners for Follow and Undo activities
    • Note object dispatcher at /users/{identifier}/posts/{id}
    • Followers collection at /users/{identifier}/followers
  • src/middleware.ts composes an additional Astro middleware with fedifyMiddleware() using sequence().
  • src/pages/users/[identifier]/index.astro renders an HTML profile page. Fedify and Astro share the route and do content negotiation depending on the Accept header.
  • src/pages/users/[identifier]/posts/index.astro lists posts and handles new post creation via a form POST.
  • src/pages/users/[identifier]/posts/[id].astro renders 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.

Project structure

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

Running

Deno

To run the dev server with Deno:

deno task dev

This uses astro.config.deno.ts as the configuration file.

Node.js

To run the dev server with Node.js:

pnpm dev

This uses astro.config.node.ts as the configuration file.

Bun

To run the dev server with Bun:

bun run dev:bun

This uses astro.config.bun.ts as the configuration file.

To build and run the Bun server bundle:

bun run build:bun
bun run preview:bun

The Bun setup intentionally uses @astrojs/node 11. The previously used @nurodev/astro-bun adapter only declares compatibility with Astro 5.

Testing

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/demo

Or using the Fedify CLI:

fedify lookup @demo@localhost:4321

Example usage scenarios

1. basic federation testing

  1. Start the development server:

    deno task dev
    # or for Node.js
    pnpm dev
    # or for Bun
    bun run dev:bun
  2. Visit the home page at http://localhost:4321/ to see the demo account handle and follower list.

  3. Visit the profile page at http://localhost:4321/users/demo.

  4. Create a post at http://localhost:4321/users/demo/posts.

  5. The ActivityPub actor endpoint is available at:

    fedify lookup @demo@localhost:4321
    

2. following from activitypub.academy

ActivityPub.Academy is a platform for learning about the ActivityPub protocol and its implementation.

To test federation with ActivityPub.Academy:

  1. Deploy the application to a public server or use a tunneling service:

    # Using Fedify CLI to tunnel
    fedify tunnel 4321
  2. From your ActivityPub.Academy account, search for and follow:

    @demo@<your-tunnel-host>
    
  3. The application will automatically:

    • Receive the follow request
    • Send an Accept activity back
    • Store the follower relationship
    • Display the follower on the home page

Configuration

Federation configuration

The federation setup is configured in src/lib/federation.ts:

const federation = createFederation<void>({
  kv: new MemoryKvStore(), // In-memory storage for development
});

Key configuration options

  1. Storage Backend:

    • Development: MemoryKvStore() (data lost on restart)
    • Production: Consider using persistent storage solutions
  2. Actor Identifier:

    • Default: "demo"
    • Modify the IDENTIFIER constant to change the demo user
  3. Demo Actor Profile:

    • Name: “Fedify Demo”
    • Summary: “This is a Fedify Demo account.”
    • Icon: /demo-profile.png

Using as a template

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:

For Deno

rm astro.config.node.ts astro.config.bun.ts
mv astro.config.deno.ts astro.config.ts

Then 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"
  }
}

For Node.js

rm astro.config.deno.ts astro.config.bun.ts
mv astro.config.node.ts astro.config.ts

Then remove the --config flags from package.json scripts:

{
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview"
  }
}

For Bun

rm astro.config.deno.ts astro.config.node.ts
mv astro.config.bun.ts astro.config.ts

Then 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"
  }
}

Links