diff --git a/app/federation/example/page.mdx b/app/federation/example/page.mdx
new file mode 100644
index 0000000..0709a03
--- /dev/null
+++ b/app/federation/example/page.mdx
@@ -0,0 +1,174 @@
+export const metadata = {
+ title: 'Federation Example',
+ description:
+ 'A description of how a typical federation flow might look like',
+}
+
+# Example
+
+This page describes a typical federation flow between two servers, `a.social` and `b.social`, in several different contexts. {{ className: 'lead' }}
+
+
+ All examples, domains, names and timestamps are **fictional** and are used **for illustrative purposes only**.
+
+ Some details have been slightly simplified for clarity.
+
+
+## Sending a Note
+
+`@alice` on `a.social` creates a note with the following content:
+
+```markdown
+Hello, @joe@b.social! How are you doing today?
+```
+
+`@alice` has mentioned `@joe@b.social` in the note.
+
+### Resolving the Mention
+
+`a.social` resolves the mention by querying `b.social` for the user `joe` using WebFinger.
+
+```bash {{ title: "cURL example" }}
+curl https://b.social/.well-known/webfinger?resource=acct:joe@b.social -H "Accept: application/json"
+```
+
+`b.social` responds with the following JSON:
+
+```json
+{
+ "subject": "acct:joe@b.social",
+ "links": [
+ { // [!code focus:5]
+ "rel": "self",
+ "type": "application/json",
+ "href": "https://b.social/users/joe"
+ }
+ ]
+}
+```
+
+
+ In a real Versia implementation, usernames would **not** be included in user profile's URL, as they can be changed. Instead, the `id` could be used.
+
+ This is done for simplicity in this example.
+
+
+### Fetching the User
+
+`a.social` fetches the user profile of `joe` from `b.social` using the URL provided in the WebFinger response.
+
+```bash
+curl https://b.social/users/joe \
+ -H "Accept: application/json" \
+ -H "User-Agent: CoolServer/1.0 (https://coolserver.com)" \
+ # The request is signed by a.social's instance private key
+ -H "Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==" \
+ -H "Versia-Signed-By: https://a.social/users/alice" \
+ -H "Versia-Signed-At: 1729241687"
+```
+
+`b.social` responds with the following JSON:
+
+```json
+{
+ "id": "bde22zi3ca8762", // [!code focus:10]
+ "type": "User",
+ "uri": "https://b.social/users/joe",
+ "created_at": "2024-10-13T18:48:19Z",
+ "avatar": {
+ "image/webp": {
+ "content": "https://cdn.b.social/avatars/joe.webp",
+ "remote": true
+ }
+ },
+ "collections": {
+ "featured": "https://b.social/users/joe/featured",
+ "followers": "https://b.social/users/joe/followers",
+ "following": "https://b.social/users/joe/following",
+ "outbox": "https://b.social/users/joe/outbox"
+ }, // [!code focus:9]
+ "display_name": "Joe Swanson (Winter Arc :gigachad:)",
+ "inbox": "https://b.social/inbox",
+ "public_key": {
+ "actor": "https://b.social/users/joe",
+ "algorithm": "ed25519",
+ "key": "MCowBQYDK2VwAyEAOSCcfsde0Ya3vf/P6lzgK0pA8qCISqneaze3omLlQCQ="
+ },
+ "username": "joe",
+ "extensions": {
+ "pub.versia:custom_emojis": {
+ "emojis": [
+ {
+ "name": ":gigachad:",
+ "content": {
+ "image/png": {
+ "content": "https://cdn.b.social/emojis/gigachad.png",
+ "remote": true
+ }
+ }
+ }
+ ]
+ }
+ },
+}
+```
+
+`a.social` now has the user profile of `joe` and can display the note with the correct user information.
+
+### Serializing the Note
+
+Finally, `a.social` serializes the note to send it to `joe`.
+
+```json
+{
+ "id": "782addd9-c051-4eea-8ba4-23d561d0c5bb", // [!code focus:6]
+ "type": "Note",
+ "uri": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb",
+ "created_at": "2024-12-01T12:19:06Z",
+ "author": "https://a.social/users/alice",
+ "category": "microblog",
+ "collections": {
+ "replies": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb/replies",
+ "quotes": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb/quotes"
+ }, // [!code focus:11]
+ "content": {
+ "text/html": {
+ "content": "Hello, @joe@b.social! How are you doing today?",
+ "remote": false,
+ },
+ "text/plain": {
+ "content": "Hello, @joe@b.social! How are you doing today?",
+ "remote": false,
+ }
+ },
+ "group": "public",
+ "mentions": [ // [!code focus:3]
+ "https://b.social/users/joe"
+ ]
+}
+```
+
+It is now time for `a.social` to send the note to `joe`.
+
+### Sending the Note
+
+`a.social` sends the note to `joe`'s inbox at `b.social`.
+
+```bash
+curl -X POST https://b.social/inbox \
+ -H "Content-Type: application/json; charset=utf-8" \
+ -H "Accept: application/json" \
+ -H "User-Agent: CoolerServer/1.0 (https://coolerserver.com)" \
+ # The request is signed by Alice's private key
+ -H "Versia-Signature: 9BrfplAPVH6OEqlV5eX7MazaZAInSCPODZcBEvMliBi/OwfbCAsezlb0O9jUX9ZcbBA68ThA4WUgS9V+42rfAQ==" \
+ -H "Versia-Signed-By: https://a.social/users/alice" \
+ -H "Versia-Signed-At: 1733051946"
+```
+
+`b.social` responds with a `202 Accepted` status code.
+
+### Displaying the Note
+
+The software on `b.social` processes the note and shows it to `joe` using whatever interface it has.
+
+`joe` can now see the note from `@alice` on `a.social` and respond to it.
\ No newline at end of file
diff --git a/components/Navigation.tsx b/components/Navigation.tsx
index d66a944..06c3c10 100644
--- a/components/Navigation.tsx
+++ b/components/Navigation.tsx
@@ -268,6 +268,7 @@ export const navigation: NavGroup[] = [
{ title: "Validation", href: "/federation/validation" },
{ title: "Discovery", href: "/federation/discovery" },
{ title: "Delegation", href: "/federation/delegation" },
+ { title: "Example", href: "/federation/example" },
],
},
{
diff --git a/mdx/rehype.mjs b/mdx/rehype.mjs
index bba9407..e736adf 100644
--- a/mdx/rehype.mjs
+++ b/mdx/rehype.mjs
@@ -31,6 +31,7 @@ const highlighter = await createHighlighter({
"html",
"json5",
"jsonc",
+ "markdown",
"bash",
"php",
"python",