Migration guide from other JavaScript ActivityPub libraries#708
Migration guide from other JavaScript ActivityPub libraries#708dahlia merged 18 commits intofedify-dev:mainfrom
Conversation
Developers already running a federated service on another JavaScript ActivityPub library are a natural Fedify audience, but moving an existing service is non-trivial: actor keys, followers collections, and in-flight deliveries all need to survive the swap. This commit lays down the structure for a single migration guide that will cover the four most likely source stacks (activitypub-express, @activity-kit, hand-rolled Express code, and activitystrea.ms); the per-library sections will be filled in subsequent commits. Place the page in the Manual sidebar group rather than a new top-level group, following the revised direction in the issue. Cross-link from the Installation page and the root README so readers coming from another library land on the guide before starting a fresh project. Also register ActivityKit as a proper noun for Hongdown so the h2 heading survives sentence-case normalisation. fedify-dev#690 Assisted-by: Claude Code:claude-opus-4-7
Cover the activitypub-express path end-to-end: why someone might leave (forked http-signature blocking Bun and Deno, no shared inbox, JSON-LD brittleness, in-process delivery), a mental-model table from apex's explicit route wiring and EventEmitter pattern to Fedify's dispatchers and inbox listeners, and five before/after snippets — app bootstrap, actor dispatcher, key-pair continuity, inbox handler, outbound sending, and followers collection. Include a data-migration script that walks the apex Mongo collections and converts each local actor's PEM private key to JWK form that `importJwk` can consume, plus a cutover procedure that preserves actor IRIs and public keys so remote followers do not break. Close with a worked Follow/Accept example that fits in ~60 lines end-to-end. fedify-dev#690 Assisted-by: Claude Code:claude-opus-4-7
Cover @activity-kit/* end-to-end: why someone might leave (dormant
since 2023-11, document-store DbAdapter, AuthAdapter couples user
accounts to federation, no public verification helpers, page
renderers baked into the plugin config), a mapping table that walks
the four-adapter pattern to Fedify's dispatcher-and-queue model, and
four before/after snippets covering app bootstrap, actor records with
PEM keys, the Plugin `handleInboxSideEffect` hook, and outbound
`publishActivity` calls.
Include a data-migration script that stitches ActivityKit's split
storage back together (`saveString("privateKey", uid, pem)` keyed by
uid, public PEM on the actor entity) and converts both PEMs to JWK so
`importJwk` can load them. Close with a signup + Follow/Accept
example showing that auth and HTML page rendering move out of the
federation layer and into ordinary web-framework routes.
Also shorten the sidebar label to "Migration" so the item fits
cleanly next to the other manual entries.
fedify-dev#690
Assisted-by: Claude Code:claude-opus-4-7
Cover the large population of small bots and blog-to-fediverse bridges that descend from Darius Kazemi's express-activitypub reference. The move-over motivation is less about dormancy (the reference was updated in 2025) and more about correctness: inbound signatures are never verified, only `Follow` is handled, and the hand-rolled `signAndSend` helper duplicates a fragile copy of the HTTP Signatures spec. Lift the reference's actor handler, WebFinger handler, inbox POST, outbound signer, and account-creation route verbatim from commit 41f98af3, and pair each with the Fedify equivalent — showing that the Fedify version is close to the same size but drops the shared- inbox trust gap, adds `Undo(Follow)` coverage, and replaces the hand-rolled crypto with `ctx.sendActivity`. Present data migration as a pattern rather than a drop-in script, since every hand-rolled schema is bespoke, and include a better-sqlite3 example that walks the canonical `accounts` table. Emphasise the actor URI-scheme preservation that keeps existing remote followers working, and the need to cross-check followers that may have been added without signature verification. fedify-dev#690 Assisted-by: Claude Code:claude-opus-4-7
The migration guide was heavy on em dashes for parenthetical asides, which reads as LLM-style prose and clashes with the project's usual voice. Rewrite every occurrence to use a comma, semicolon, colon, or parentheses instead. Where the em dash was carrying a real strong pause, split the sentence or rephrase it. No behavioural change; prose-only rewrite across the apex, ActivityKit, and hand-rolled sections. fedify-dev#690 Assisted-by: Claude Code:claude-opus-4-7
Cover the vocabulary-only migration from activitystrea.ms to @fedify/vocab. Unlike the other three source libraries this one is actively maintained (v3.3.2, 2026-04-03 by Evan Prodromou / Social Web Foundation), so the motivation is not dormancy but type safety, immutability, and tooling alignment for codebases that already run on Fedify. Include a mental-model table mapping the fluent builder API to the immutable class constructors, plus three side-by-side before/after pairs: constructing a Create(Note) activity, serialising to JSON with toJsonLd, and parsing an incoming document with Activity.fromJsonLd. Call out the URL-instance, immutability, and Temporal.Instant differences that trip up direct ports. fedify-dev#690 Assisted-by: Claude Code:claude-opus-4-7
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new comprehensive migration guide and sidebar entry, updates VitePress sidebar and docs cross-links, tweaks a config expression, and registers "ActivityKit" as a proper noun in Changes
Sequence Diagram(s)(omitted — changes are documentation/config-only and do not introduce new multi-component runtime control flow) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@codex review |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/manual/migrate.md`:
- Around line 1725-1728: The sentence claiming "`activitystrea.ms` is *not*
dormant... (v3.3.2, 2026-04-03)" should be edited to remove the hardcoded
version/date and to correct the inaccurate release claim; locate the paragraph
containing the literal `activitystrea.ms` and replace the specific version/date
text with a neutral phrase such as "continues to receive releases" (optionally
followed by a link to the official releases page) so the doc no longer asserts a
stale version or date.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: af0fbab2-2afd-4eb9-9d2f-90f460d6d8d1
📒 Files selected for processing (5)
.hongdown.tomldocs/.vitepress/config.mtsdocs/install.mddocs/manual/migrate.mdpackages/fedify/README.md
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive migration guide (docs/manual/migrate.md) for users transitioning to Fedify from other JavaScript ActivityPub libraries, such as apex, ActivityKit, and hand-rolled Express implementations. The guide provides mental-model mappings, code examples, and data migration strategies, alongside updates to navigation and installation documentation for better discoverability. A typo was identified in a code example where the Note constructor incorrectly used the plural contents property instead of the singular content.
|
Codex Review: Didn't find any major issues. 🚀 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Pull request overview
Adds a new manual page that guides developers migrating to Fedify from other JavaScript ActivityPub libraries, and wires it into the docs navigation and entry points so it’s discoverable during onboarding.
Changes:
- Added a comprehensive migration guide at
docs/manual/migrate.mdcovering four source stacks. - Linked the guide from installation docs and package README(s), and added it to the Manual sidebar.
- Updated Hongdown proper nouns to preserve “ActivityKit” heading casing.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/fedify/README.md | Adds a “Migrating from other libraries” resource link to the docs site. |
| docs/manual/migrate.md | New migration guide content, including code/data migration notes and examples. |
| docs/install.md | Adds a TIP callout linking to the new migration guide. |
| docs/.vitepress/config.mts | Adds “Migration” to the Manual sidebar items (and minor formatting). |
| .hongdown.toml | Registers “ActivityKit” as a proper noun for heading normalization. |
Codecov Report✅ All modified and coverable lines are covered by tests. 🚀 New features to boost your workflow:
|
The link target `./send.md#sending-to-followers` does not resolve; the section in docs/manual/send.md is titled `"followers"`, which VitePress slugifies to `#followers`. Update the anchor accordingly, and change the visible label to match the section title. Addresses the review comments at: fedify-dev#708 (comment) fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
Naming a specific version and release date in prose will go stale. The point the sentence needs to make is that the upstream continues to publish releases, not which one was most recent when the guide was written; rephrase accordingly. Addresses the review comment at: fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/manual/migrate.md`:
- Around line 1487-1489: In the sentence containing "`The signup route does not
live inside `federation` any more;`" replace the two-word "any more" with the
single-word "anymore" so the line reads "The signup route does not live inside
`federation` anymore; it is just a normal POST handler..." to use the more
idiomatic form; update the text that references `federation` accordingly.
- Around line 511-514: Edit the sentence that currently reads "and the RSA
public key matches what those remote servers already have cached" to move the
adverb closer to the verb; change it to "and the RSA public key matches what
those remote servers have already cached" so the adverb "already" directly
modifies "have cached" for more natural flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9465f18a-2aea-4450-b327-c83a7dc33dad
📒 Files selected for processing (1)
docs/manual/migrate.md
The preceding bullet already writes it with the intercapped P (matching the project's Hongdown proper-nouns list), but the parenthetical on the same bullet still had the lowercase form. Align both occurrences. Addresses the review comment at: fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
|
@codex review |
|
/gemini review |
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive migration guide for users transitioning to Fedify from other JavaScript ActivityPub libraries, such as activitypub-express, ActivityKit, and hand-rolled Express implementations. The guide is integrated into the documentation via updates to the VitePress configuration, installation instructions, and the main README. Feedback focuses on aligning the new documentation with the repository's style guide, specifically regarding heading levels and the placement of reference-style links.
|
Pre-release has been published for this pull request: Packages
DocumentationThe docs for this pull request have been published: |
2chanhaeng
left a comment
There was a problem hiding this comment.
LGTM and have some suggestions!
The motivation prose undersold how quiet the source libraries actually are today. In the apex intro, note that its two named showcase projects (Immers Space and Guppe Groups) have themselves gone quiet: Guppe's repository is archived on GitHub and the service site now just advertises the hosted platform, so apex is effectively a one-person project. In the ActivityKit "when to migrate" bullet, tighten "over two years" to "several years" so the claim does not need yearly revisiting as the guide ages. Addresses the review comments at: fedify-dev#708 (comment) fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
The inline comment named only PostgresKvStore, which reads as if that were the only production option. Match the phrasing already used in the ActivityKit section so readers see that any of the production KvStore backends (Postgres, Redis, MySQL, SQLite, Deno KV, ...) is a valid substitution. Addresses the review comment at: fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
Hongdown was wrapping the cross-link onto its own line because it was inside a trailing parenthetical, producing an awkward "see\n[*link*])" shape. Drop the parenthetical wrapping and use a semicolon so the sentence reads naturally regardless of where the formatter wraps. Addresses the review comment at: fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
docs/manual/migrate.md (1)
635-637:⚠️ Potential issue | 🟠 MajorAvoid hardcoded ActivityKit version/date assertions.
Line 635–Line 637 hardcode
v0.4.57/v0.4.58and2023-11-01. This will stale and can become incorrect over time (same class of issue previously fixed in theactivitystrea.mssection). Please rephrase to a time-robust statement (e.g., “has seen little/no recent release activity”) and optionally link to the upstream releases/commits page instead of embedding exact dates/versions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/manual/migrate.md` around lines 635 - 637, Replace the hardcoded ActivityKit versions ("v0.4.57"/"v0.4.58") and date ("2023-11-01") in the sentence that ends with "dormant bucket for production planning" with a time-robust phrasing such as "has seen little or no recent release activity" (keep the "dormant bucket for production planning" context if desired) and optionally add a pointer to the upstream releases/commits page rather than embedding exact versions/dates so the statement cannot become stale; search for the literal strings "v0.4.57", "v0.4.58" or "2023-11-01" in the migrate.md section to locate and update the sentence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/manual/migrate.md`:
- Around line 252-266: The example declares getJwksByUsername as always
returning a JWKS object but later checks jwks == null in the
setKeyPairsDispatcher block; make the types consistent by updating
getJwksByUsername's return type to allow null (e.g., Promise<{ rsa: {
privateKey: JsonWebKey; publicKey: JsonWebKey } } | null>) and adjust the
placeholder implementation to return null when appropriate so the null-check in
setKeyPairsDispatcher remains valid; locate getJwksByUsername and the jwks usage
in setKeyPairsDispatcher to apply this change.
---
Duplicate comments:
In `@docs/manual/migrate.md`:
- Around line 635-637: Replace the hardcoded ActivityKit versions
("v0.4.57"/"v0.4.58") and date ("2023-11-01") in the sentence that ends with
"dormant bucket for production planning" with a time-robust phrasing such as
"has seen little or no recent release activity" (keep the "dormant bucket for
production planning" context if desired) and optionally add a pointer to the
upstream releases/commits page rather than embedding exact versions/dates so the
statement cannot become stale; search for the literal strings "v0.4.57",
"v0.4.58" or "2023-11-01" in the migrate.md section to locate and update the
sentence.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7c93711a-7380-4e57-b965-6737c586d784
📒 Files selected for processing (1)
docs/manual/migrate.md
Slightly less jargony framing for the same signal, matching the in-thread suggestion. Addresses the review comment at: fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
The hidden Twoslash boilerplate declared getJwksByUsername as always returning a JWKS object, but the visible setKeyPairsDispatcher body branches on `jwks == null`. Mark the return type as `| null` so the type annotation matches the runtime contract readers are meant to implement (their own getJwksByUsername will naturally return null for unknown identifiers). Addresses the review comment at: fedify-dev#708 (comment) Assisted-by: Claude Code:claude-opus-4-7
Closes #690.
Read it at https://6a0da8df.fedify.pages.dev/manual/migrate.
Summary
Developers already running a federated service on another JavaScript ActivityPub library are a natural Fedify audience, but moving an existing service is non-trivial: actor keys, followed/followers collections, and queued outbound deliveries all need to survive the swap, and the mental model of each source library differs from Fedify's builder-and-dispatcher pattern.
This PR adds a single migration guide at docs/manual/migrate.md that walks through the transition from the four most likely source stacks, each with its own mental-model table, before/after code snippets, data-migration notes, common pitfalls, and a worked example:
activitypub-express): the Express + MongoDB middleware that powers Immers Space and Guppe Groups today. Covers key-pair carryover out of_meta.privateKeyPEM blobs, followers carryover out of thestreamscollection, and the patched-http-signaturesituation that blocks Bun and complicates Deno.@activity-kit/*): the dormant TypeScript framework by Michael Puckett. Covers the plugin-based inbox hooks, the document-storeDbAdapterinterface, and the separation of theAuthAdapterand HTML page renderers out of the federation layer.express-activitypubreference and its descendants (rss-to-activitypub, bespoke bots). Covers the absent inbound signature verification, theFollow-only coverage, the hand-rolledsignAndSendhelper, and how to preserve the/u/:nameURI scheme so existing followers keep resolving.activitystrea.ms): a pure vocabulary-only swap to@fedify/vocab, with side-by-side construction, serialisation, and parsing snippets.Deliverables (per the issue comment that collapsed the originally proposed four pages into a single page)
h2sections (#apex,#activity-kit,#hand-rolled,#activity-streams).@fedify/createsection) and from the root README.md (the If you want to know more… list).ActivityKitas a proper noun in .hongdown.toml so the heading "From@activity-kit/*(ActivityKit)" survives sentence-case normalisation.Scope notes
Expressproper noun inside the anchor id; the shorter anchor avoids that and reads as well.activitystrea.mssection explicitly calls out that the upstream is not dormant (Evan Prodromou released v3.3.2 on 2026-04-03); the original issue description said otherwise, but the motivation for migrating is type safety and tooling alignment, not maintenance.Out of scope (per the issue)
@semapps/activitypub,@evanp/activitypub-bot, etc.).Verification
mise run fmtruns clean after every commit in the series.mise docs:buildsucceeds; every Twoslash block in the after snippets type-checks against the real Fedify package exports.