Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
aa1f5f0
Start the content sharing tutorial
dahlia Apr 25, 2026
52c93a6
Add the "A minimal app shell" chapter
dahlia Apr 25, 2026
876a139
Add the "Setting up the database" chapter
dahlia Apr 25, 2026
27cb387
Add the "Account creation" chapter
dahlia Apr 25, 2026
3b07dbc
Add the "Profile page" chapter
dahlia Apr 25, 2026
3dad830
Add the "Actor dispatcher" chapter
dahlia Apr 25, 2026
3eaa93f
Drop spaced em dashes from the actor dispatcher chapter
dahlia Apr 25, 2026
2169a9d
Add the "Cryptographic key pairs" chapter
dahlia Apr 25, 2026
84e324d
Add the "First federation test" chapter
dahlia Apr 25, 2026
25c2fd4
Polish chapter 9 style and instance-agnostic guidance
dahlia Apr 25, 2026
e625800
Add the "Handling follows" chapter
dahlia Apr 25, 2026
6c209d3
Sync tutorial with the Fedify 2.2.0-dev.949 init template
dahlia Apr 25, 2026
7499b89
Soften the Pixelfed claim in chapter 10 and link forward
dahlia Apr 25, 2026
b453b3c
Teach `firstKnock` and call out Pixelfed compat in chapter 10
dahlia Apr 25, 2026
930d587
Reflect the working Pixelfed Accept payload in chapter 10
dahlia Apr 25, 2026
04f20d4
Drop bogus chapter-10 references
dahlia Apr 25, 2026
eb68666
Add the "Handling unfollows" chapter
dahlia Apr 25, 2026
370f182
Add the "Followers list and collection" chapter
dahlia Apr 25, 2026
3905181
Escape brackets in nested code-block file paths
dahlia Apr 25, 2026
d2133b2
Add the "Image post schema" chapter
dahlia Apr 25, 2026
89b517d
Upgrade Hongdown to 0.3.10
dahlia Apr 25, 2026
f4b78dc
Use a definition list for chapter 13's column descriptions
dahlia Apr 25, 2026
0311315
Add the "Composing and uploading" chapter
dahlia Apr 25, 2026
6c19f7f
Add the "Note object dispatcher" chapter
dahlia Apr 25, 2026
9a9ff03
Add the "Profile feed" chapter
dahlia Apr 25, 2026
efa6423
Add the "Post detail page" chapter
dahlia Apr 25, 2026
f904492
Add the "Distributing new posts to followers" chapter
dahlia Apr 25, 2026
0eb032d
Add the "Following remote accounts" chapter
dahlia Apr 25, 2026
277787f
Add the "Following list" chapter
dahlia Apr 25, 2026
027bd39
Add the "Home timeline" chapter
dahlia Apr 25, 2026
a3e9963
Add the "Likes and Undo(Like)" chapter
dahlia Apr 25, 2026
3563b5a
Add the "Comments" and "Where next" chapters
dahlia Apr 25, 2026
7a1cde9
Replace Mastodon-side screenshots with Pixelfed-side proof shots
dahlia Apr 25, 2026
4e48cb7
Update terminal code blocks in content-sharing tutorial
dahlia Apr 26, 2026
0b580ed
Backtick ActivityPub vocab terms in chapter headings
dahlia Apr 26, 2026
fcbf7b3
Use backslash-escaped brackets in tutorial file-path prose
dahlia Apr 26, 2026
10175f8
Tighten the closing chapter's outbound links
dahlia Apr 26, 2026
7da8606
Spell Node.js consistently in chapter 15 prose
dahlia Apr 26, 2026
8407861
Apply twoslash to Drizzle+Fedify code blocks
dahlia Apr 26, 2026
ca6a1e5
Apply twoslash to chained .on() handler blocks via cut notation
dahlia Apr 26, 2026
dfe58a7
Apply twoslash to schema.ts code blocks
dahlia Apr 26, 2026
a32707c
Use typescript highlighting for bare-script .vue snippets
dahlia Apr 26, 2026
c569b11
Carry Pixelfed federation tests through chapters 19-22
dahlia Apr 26, 2026
1a93cbd
Demonstrate alice -> Pixelfed comment in chapter 23
dahlia Apr 26, 2026
9e628d9
Close remaining Pixelfed coverage gaps in chapters 12, 20, 22
dahlia Apr 26, 2026
2c78d9f
Escape route params in tutorial code titles
dahlia Apr 26, 2026
1da08cb
Backtick CLI commands and vocab types instead of italicising them
dahlia Apr 26, 2026
01c2f35
Refer to chapters by italicised title and link to anchors
dahlia Apr 26, 2026
a264709
Fix markdown-it-jsr-ref syntax
dahlia Apr 26, 2026
e42c26a
Drop instance.~Type.member jsr-ref hybrids
dahlia Apr 26, 2026
f9e8db5
Distinguish HTTP Accept header from Accept activity
dahlia Apr 26, 2026
89a4238
Wrap db.run(sql\`...\`) span in double backticks
dahlia Apr 26, 2026
ca175a8
Show SQLite query results as tables
dahlia Apr 26, 2026
193b4ab
Italicise file path in chapter 13 deflist
dahlia Apr 26, 2026
b36eec0
Switch British spellings to US
dahlia Apr 26, 2026
e2a4b45
Mark added lines in refactored code blocks with diff highlights
dahlia Apr 26, 2026
6de5d4b
Address E2E rehearsal findings on schema, federation export, HMR
dahlia Apr 26, 2026
c3cf498
Mirror Accept matcher fallback in chapter 19
dahlia Apr 26, 2026
61d2556
Address Codex review polish on the content-sharing tutorial
dahlia Apr 26, 2026
2e55ca4
Address Codex second-pass review on the content-sharing tutorial
dahlia Apr 26, 2026
59bfa31
Mirror hardened stripHtml and Undo(Like) matcher in the tutorial
dahlia Apr 26, 2026
efa6662
Switch the tutorial sanitizer to sanitize-html
dahlia Apr 27, 2026
f4a2817
Mirror sanitize-html allow-list tightening in the tutorial
dahlia Apr 27, 2026
ab76882
Surface captionText in chapter 21 and harden extractText
dahlia Apr 27, 2026
183698d
Make /api/likes POST idempotent in chapter 22
dahlia Apr 27, 2026
31c0fc6
Route better-sqlite3 and drizzle-orm through the pnpm catalog
dahlia Apr 27, 2026
a54d18e
Fix the chapter 21 cross-link to Likes and Undo(Like)
dahlia Apr 27, 2026
517c244
Add unocss to the chapter 3 install command
dahlia Apr 27, 2026
6efc0a9
Prepend Undo(Like) instead of restructuring Undo(Follow)
dahlia Apr 27, 2026
a572608
Make chapter 22/23 Vue snippets self-contained
dahlia Apr 27, 2026
1e1bb86
Call out new imports in prose around cut twoslash blocks
dahlia Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .agents/skills/add-vocab/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ fediverse. Specifically, verify:
async/sync interface contract
- The `functional` flag is correct — marking a multi-valued property as
functional silently drops values
- Every property `range` entry is accurate — wrong range types produce incorrect
TypeScript types
- Every property `range` entry is accurate — wrong range types produce
incorrect TypeScript types
- The spec document (FEP or W3C spec) has been read in full, not just skimmed

Do not rely solely on automated checks (`mise run check`)—they verify only
Expand Down Expand Up @@ -86,8 +86,8 @@ $schema: ../../vocab-tools/schema.yaml
**Entity vs. value type (`entity` flag):**

- `entity: true` — property accessors are `async` and can fetch remote objects
- `entity: false` — property accessors are synchronous; used for embedded value
objects (e.g. `Endpoints`, `Source`, `Hashtag`)
- `entity: false` — property accessors are synchronous; used for embedded
value objects (e.g. `Endpoints`, `Source`, `Hashtag`)

### `defaultContext` format

Expand Down Expand Up @@ -117,8 +117,8 @@ defaultContext:
Embedded context entries are YAML mappings where:

- String value `"prefix:term"` or `"https://..."` defines a simple term alias
- Object value with `"@id"` and optionally `"@type": "@id"` defines a term that
should be treated as an IRI (linked resource)
- Object value with `"@id"` and optionally `"@type": "@id"` defines a term
that should be treated as an IRI (linked resource)

### Ensuring complete compaction coverage

Expand All @@ -128,9 +128,9 @@ document produced by `toJsonLd()`**, including:
1. **The type's own `compactName`** — if the type has a `compactName`, the
context must map that name to the type's URI.

2. **All own property `compactName`s** — every property defined directly on this
type must have its `compactName` (or full URI fallback) resolvable via the
context.
2. **All own property `compactName`s** — every property defined directly on
this type must have its `compactName` (or full URI fallback) resolvable via
the context.

3. **Inherited properties** — properties from parent types are usually covered
by the parent's context URL (e.g., `https://www.w3.org/ns/activitystreams`
Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/create-example-app-with-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ Follow the specifications in [ARCHITECTURE.md](./ARCHITECTURE.md) and
- Implement all routes listed in the “Routing” section of
[ARCHITECTURE.md](./ARCHITECTURE.md), using `RequestContext` as described
in the “Server-side data access” section.
- Render HTML pages according to [DESIGN.md](./DESIGN.md). Serve static assets
from the `public/` directory (copy from
- Render HTML pages according to [DESIGN.md](./DESIGN.md). Serve static
assets from the `public/` directory (copy from
[example/public/](./example/public/)).
- Implement the SSE endpoint per the “Server-sent events” section of
[ARCHITECTURE.md](./ARCHITECTURE.md).
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ A detailed step-by-step guide is available across three skills:

### Creating database adapters

1. For core KV/MQ interfaces: implement in *packages/fedify/src/federation/kv.ts*
and *packages/fedify/src/federation/mq.ts*
1. For core KV/MQ interfaces: implement in
*packages/fedify/src/federation/kv.ts* and
*packages/fedify/src/federation/mq.ts*
2. For specific database adapters: create dedicated packages
(*packages/sqlite/*, *packages/postgres/*, *packages/mysql/*,
*packages/redis/*, *packages/amqp/*)
Expand Down
31 changes: 23 additions & 8 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,17 @@ To be released.
redistribution that threadiverse software (Lemmy, Mbin, NodeBB) uses to fan
activity out to every subscriber. [[#704], [#710]]

- Added [*Creating an image sharing service* tutorial], a Pixelfed-style
image-sharing companion to the microblog walk-through. Built on Nuxt 4
and the new `@fedify/nuxt` integration, the tutorial covers actor
dispatchers, key pairs, follow/unfollow flows, image-bearing
`Create(Note)` fan-out and reception, an outbound `Like`/`Undo(Like)`
heart toggle, and threaded comments through `inReplyTo`. The
[companion example repository] keeps one commit per chapter at the
bottom of its log, with a few rehearsal-driven follow-ups landed on top,
and the federation flows are demonstrated against both Mastodon and
Pixelfed. [[#693]]

- Added a custom collections cookbook example for bookmark-like data,
demonstrating cursor pagination, URI-template filtering, collection
counters, actor stream links, and requester-aware collections using
Expand All @@ -253,7 +264,10 @@ To be released.
[Bun]: https://bun.sh/
[*Building a threadiverse community platform*]: https://fedify.dev/tutorial/threadiverse
[*Creating your own federated microblog*]: https://fedify.dev/tutorial/microblog
[*Creating an image sharing service* tutorial]: https://fedify.dev/tutorial/content-sharing
[companion example repository]: https://github.com/fedify-dev/content-sharing
[#691]: https://github.com/fedify-dev/fedify/issues/691
[#693]: https://github.com/fedify-dev/fedify/issues/693
[#694]: https://github.com/fedify-dev/fedify/issues/694
[#695]: https://github.com/fedify-dev/fedify/pull/695
[#704]: https://github.com/fedify-dev/fedify/issues/704
Expand Down Expand Up @@ -1061,8 +1075,8 @@ Released on February 22, 2026.
to the standardized `Intl.Locale` class for representing language tags.
[[#280], [#392] by Jang Hanarae]

- The `LanguageString.language` property is now `LanguageString.locale` and
is of type `Intl.Locale` instead of `LanguageTag`.
- The `LanguageString.language` property is now `LanguageString.locale`
and is of type `Intl.Locale` instead of `LanguageTag`.
- The `LanguageString` constructor now accepts either an `Intl.Locale`
object or a string for the language parameter.
- The `Link.language` property is now of type `Intl.Locale` instead
Expand Down Expand Up @@ -1782,8 +1796,8 @@ Released on December 24, 2025.

### @fedify/nestjs

- Allowed Express 5 in the `express` peer dependency range to support NestJS 11.
[[#492], [#493] by Cho Hasang]
- Allowed Express 5 in the `express` peer dependency range to support NestJS
11. [[#492], [#493] by Cho Hasang]

[#492]: https://github.com/fedify-dev/fedify/issues/492
[#493]: https://github.com/fedify-dev/fedify/pull/493
Expand Down Expand Up @@ -4083,8 +4097,9 @@ Released on November 30, 2024.

- The `Router` now provide the matched route's URI template besides the name.

- The return type of `Router.route()` method became `RouterRouteResult | null`
(was `{ name: string; values: Record<string, string> } | null`).
- The return type of `Router.route()` method became
`RouterRouteResult | null` (was
`{ name: string; values: Record<string, string> } | null`).
- Added `RouterRouteResult` interface.

- Added `getTypeId()` function.
Expand Down Expand Up @@ -5733,8 +5748,8 @@ Released on September 26, 2024.

- Added options for PostgreSQL drivers to `fedify init` command.

- Added `postgres` value to the `-k`/`--kv-store` option of the `fedify init`
command.
- Added `postgres` value to the `-k`/`--kv-store` option of the
`fedify init` command.
- Added `postgres` value to the `-q`/`--message-queue` option of
the `fedify init` command.

Expand Down
9 changes: 5 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ Because this project supports both Deno and Node.js/Bun, dependencies must
be added to *both* configuration files:

- *deno.json*: Add to the `imports` field (for Deno).
- *package.json*: Add to `dependencies` or `devDependencies` (for Node.js/Bun).
- *package.json*: Add to `dependencies` or `devDependencies` (for
Node.js/Bun).

For workspace packages, use the pnpm catalog (*pnpm-workspace.yaml*) to manage
versions centrally. In *package.json*, reference catalog versions with
Expand Down Expand Up @@ -371,10 +372,10 @@ The repository is organized as a monorepo with the following packages:
creating new Fedify projects. Wraps @fedify/init.
- *packages/amqp/*: AMQP/RabbitMQ driver (@fedify/amqp) for Fedify.
- *packages/astro/*: Astro integration (@fedify/astro) for Fedify.
- *packages/cfworkers/*: Cloudflare Workers integration (@fedify/cfworkers) for
Fedify.
- *packages/debugger/*: Embedded ActivityPub debug dashboard (@fedify/debugger)
- *packages/cfworkers/*: Cloudflare Workers integration (@fedify/cfworkers)
for Fedify.
- *packages/debugger/*: Embedded ActivityPub debug dashboard
(@fedify/debugger) for Fedify.
- *packages/denokv/*: Deno KV integration (@fedify/denokv) for Fedify.
- *packages/elysia/*: Elysia integration (@fedify/elysia) for Fedify.
- *packages/express/*: Express integration (@fedify/express) for Fedify.
Expand Down
4 changes: 4 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ const TUTORIAL = {
},
{ text: "Learning the basics", link: "/tutorial/basics.md" },
{ text: "Creating a microblog", link: "/tutorial/microblog.md" },
{
text: "Creating an image sharing service",
link: "/tutorial/content-sharing.md",
},
{ text: "Building a federated blog", link: "/tutorial/astro-blog.md" },
{
text: "Building a threadiverse community",
Expand Down
3 changes: 2 additions & 1 deletion docs/manual/collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -1567,7 +1567,8 @@ Custom collections support the same callback methods as built-in collections:

- **`.setCounter()`**: Sets a callback that returns the total number of items
in the collection
- **`.setFirstCursor()`**: Sets the cursor for the first page of the collection
- **`.setFirstCursor()`**: Sets the cursor for the first page of the
collection
- **`.setLastCursor()`**: Sets the cursor for the last page of the collection
- **`.authorize()`**: Sets an authorization predicate to control access to
the collection
Expand Down
16 changes: 8 additions & 8 deletions docs/manual/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -740,10 +740,10 @@ systemd
(`systemctl start fedify@web.service fedify@worker.service`).

Kubernetes
: Two `Deployment`s. Only the web `Deployment` gets a `Service` and `Ingress`.
Scale workers on queue depth (via a custom metric adapter reading from
your MQ backend) rather than CPU—a queue that's falling behind is not
necessarily CPU-bound.
: Two `Deployment`s. Only the web `Deployment` gets a `Service` and
`Ingress`. Scale workers on queue depth (via a custom metric adapter
reading from your MQ backend) rather than CPU—a queue that's falling behind
is not necessarily CPU-bound.

> [!WARNING]
> Do not place worker nodes behind a load balancer or expose them on a
Expand Down Expand Up @@ -1214,10 +1214,10 @@ Block abusive instances early
your own rather than importing them wholesale.

Keep the system clock in sync
: HTTP signatures are valid only within `~FederationOptions.signatureTimeWindow`
(one hour by default). Run NTP on every web and worker node. Clock
drift is the second-most-common “it worked in staging” production
issue after reverse-proxy misconfiguration.
: HTTP signatures are valid only within
`~FederationOptions.signatureTimeWindow` (one hour by default). Run NTP on
every web and worker node. Clock drift is the second-most-common “it
worked in staging” production issue after reverse-proxy misconfiguration.

[Pelago]: https://pelago.1sland.social/blocklist
[FIRES]: https://fires.fedimod.org/
Expand Down
4 changes: 2 additions & 2 deletions docs/manual/mq.md
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,8 @@ Best for
: Production use in Cloudflare Workers environments.

Pros
: Persistent, reliable, scalable, easy to set up, native retry with exponential
backoff and dead-letter queues.
: Persistent, reliable, scalable, easy to set up, native retry with
exponential backoff and dead-letter queues.

Cons
: Only available in Cloudflare Workers runtime.
Expand Down
3 changes: 2 additions & 1 deletion docs/manual/relay.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ Configuration options
keys.

`origin` (required)
: The origin URL where the relay is hosted (e.g., `"https://relay.example.com"`).
: The origin URL where the relay is hosted (e.g.,
`"https://relay.example.com"`).

`name`
: Display name for the relay actor. Defaults to `"ActivityPub Relay"`.
Expand Down
6 changes: 4 additions & 2 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
"@fedify/next": "workspace:^",
"@fedify/postgres": "workspace:^",
"@fedify/redis": "workspace:^",
"@fedify/relay": "workspace:^",
"@fedify/sqlite": "workspace:^",
"@fedify/sveltekit": "workspace:^",
"@fedify/testing": "workspace:^",
"@fedify/vocab": "workspace:^",
"@fedify/vocab-runtime": "workspace:^",
"@fedify/relay": "workspace:^",
"@hackmd/markdown-it-task-lists": "^2.1.4",
"@hono/node-server": "^1.13.7",
"@js-temporal/polyfill": "catalog:",
Expand All @@ -39,14 +39,16 @@
"@shikijs/vitepress-twoslash": "^1.24.4",
"@teidesu/deno-types": "^2.1.4",
"@types/amqplib": "catalog:",
"@types/better-sqlite3": "^7.6.12",
"@types/better-sqlite3": "catalog:",
"@types/bun": "^1.1.14",
"@types/express": "catalog:",
"@types/koa": "catalog:",
"@types/node": "catalog:",
"amqplib": "catalog:",
"better-sqlite3": "catalog:",
"dayjs": "^1.11.13",
"debug": "^4.4.1",
"drizzle-orm": "catalog:",
"express": "catalog:",
"fastify": "catalog:",
"h3": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions docs/tutorial/astro-blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2680,8 +2680,8 @@ Let's walk through the three new handlers:

1. Fetch the activity's `object` and verify it's a `Note`.
2. Check `note.replyTargetId` (the `inReplyTo` URL) and parse it with
`ctx.parseUri`. If it matches our `Article` dispatcher pattern, we
get back `{ type: "object", class: Article, values: { slug: "…" } }`.
`ctx.parseUri`. If it matches our `Article` dispatcher pattern, we
get back `{ type: "object", class: Article, values: { slug: "…" } }`.
3. Fetch the author actor to get their display name.
4. Store the comment with `addComment`.

Expand All @@ -2690,7 +2690,7 @@ Let's walk through the three new handlers:

1. Verify the note exists in our database.
2. Verify the actor matches the stored `authorUrl` (no one else can
edit someone else's comment).
edit someone else's comment).
3. Update the name and content.

`Delete`
Expand Down
Loading
Loading