Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision af210025a9f53cf80906d139049d8febdf1539ab)
+++ src/services/ActivityPubService.js	(revision 1cc8c8501811c751b7d9a23efdb885cca2ddce66)
@@ -210,5 +210,29 @@
 
 // A single post as an AS2 Note (the object), and as a Create activity (for outbox/delivery).
-export function buildNote(base, site, post) {
+export function buildNote(base, site, post, opts = {}) {
+  // Replies are Notes too. buildNote is the single entry point for ALL Notes; a reply is
+  // (for now) the simple flavor: pre-baked content, no title/cover/image/audio/embed
+  // machinery, addressed to the parent actor + thread. This early branch keeps that output
+  // byte-identical to the old buildReplyNote. When rich replies land (images/audio/embeds),
+  // this branch collapses and replies flow through the full post pipeline below. `post` here
+  // is the ap_outbox reply row (id, in_reply_to, content, post_slug, created_at, to_actor).
+  if (opts.isReply) {
+    const meR = actorId(base, site.slug);
+    return {
+      id: noteId(base, post.id),
+      type: 'Note',
+      attributedTo: meR,
+      inReplyTo: post.in_reply_to || undefined,
+      content: post.content,
+      url: post.post_slug ? `${base}/${encodeURIComponent(post.post_slug)}` : undefined,
+      published: toISO(post.created_at),
+      to: post.to_actor ? [post.to_actor] : [PUBLIC],
+      cc: [PUBLIC, `${meR}/followers`],
+      tag: [
+        ...mentionTags(post.content),
+        ...hashtagTags(base, post.content),
+      ],
+    };
+  }
   const id = noteId(base, post.id);
   const aId = actorId(base, site.slug);
@@ -1572,20 +1596,6 @@
 
 export function buildReplyNote(base, site, row) {
-  const me = actorId(base, site.slug);
-  return {
-    id: noteId(base, row.id),
-    type: 'Note',
-    attributedTo: me,
-    inReplyTo: row.in_reply_to || undefined,
-    content: row.content,
-    url: row.post_slug ? `${base}/${encodeURIComponent(row.post_slug)}` : undefined,
-    published: toISO(row.created_at),
-    to: row.to_actor ? [row.to_actor] : [PUBLIC],
-    cc: [PUBLIC, `${me}/followers`],
-    tag: [
-      ...mentionTags(row.content),
-      ...hashtagTags(base, row.content),
-    ],
-  };
+  // Thin delegate: replies are built by buildNote (the single Note entry point) in reply mode.
+  return buildNote(base, site, row, { isReply: true });
 }
 
