feat: optional one-way ActivityPub publisher #2

Merged
thesimonharms merged 1 commit from cursor/activitypub-publisher-b32a into main 2026-08-06 09:15:12 -04:00
thesimonharms commented 2026-08-06 09:14:41 -04:00 (Migrated from github.com)

Summary

Adds an opt-in one-way ActivityPub publisher so Rontal-powered blogs can be followed from Mastodon and other fediverse clients.

Federation is off by default. Enable it in config/rontal.ts:

fediverse: {
  enabled: true,
  username: 'blog',
  public_base_url: 'https://blog.example.com',
  post_permalink: 'https://blog.example.com/posts/{slug}', // optional
}

What this includes

  • WebFinger at /.well-known/webfinger
  • Actor (Service) at /ap/actor with auto-generated RSA keypair
  • Outbox of Create activities for published posts
  • Inbox accepting signed Follow / Undo(Follow) (other activities ignored)
  • Fan-out of signed Create / Update / Delete on publish / update / unpublish / delete
  • Migrations for fediverse_actor_keys and fediverse_followers
  • Docs + tests (40 passing)

Out of scope (by design)

Replies, likes, boosts, and other two-way social features — this is publish-only.

Open in Web Open in Cursor 
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Summary Adds an **opt-in** one-way ActivityPub publisher so Rontal-powered blogs can be followed from Mastodon and other fediverse clients. Federation is off by default. Enable it in `config/rontal.ts`: ```ts fediverse: { enabled: true, username: 'blog', public_base_url: 'https://blog.example.com', post_permalink: 'https://blog.example.com/posts/{slug}', // optional } ``` ## What this includes - **WebFinger** at `/.well-known/webfinger` - **Actor** (`Service`) at `/ap/actor` with auto-generated RSA keypair - **Outbox** of `Create` activities for published posts - **Inbox** accepting signed `Follow` / `Undo(Follow)` (other activities ignored) - **Fan-out** of signed `Create` / `Update` / `Delete` on publish / update / unpublish / delete - Migrations for `fediverse_actor_keys` and `fediverse_followers` - Docs + tests (40 passing) ## Out of scope (by design) Replies, likes, boosts, and other two-way social features — this is publish-only. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-019fcfb6-1751-7e0a-ae80-3fb63c14b32a?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-019fcfb6-1751-7e0a-ae80-3fb63c14b32a&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>
Sign in to join this conversation.
No description provided.