Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision a9da2c04639cc50ea277110a4eac16c934999834)
+++ src/routes/activitypub.js	(revision 67f71503172e1c48fc93ee0e7ea1fbc6f67e587e)
@@ -110,5 +110,15 @@
      ORDER BY COALESCE(published_at, created_at) DESC LIMIT 20`
   ).all(site.id);
-  AP.sendAP(res, AP.buildOutbox(baseUrl(req), site, posts), audience === 'friend' ? 'private, no-store' : undefined);
+  const ob = AP.buildOutbox(baseUrl(req), site, posts);
+  if (audience === 'friend') {
+    // The owner's app builds its feed from this leg, and every note here is
+    // by the site itself: give it the same `shaer:author` byline the timeline
+    // entries carry, so your own cards get a header too (avatar + name).
+    const me = AP.selfAuthor(baseUrl(req), site);
+    for (const it of ob.orderedItems) {
+      if (it && it.object && typeof it.object === 'object') it.object['shaer:author'] = me;
+    }
+  }
+  AP.sendAP(res, ob, audience === 'friend' ? 'private, no-store' : undefined);
 });
 
