Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision fa33214eb34752fafee25fc95942f470701006f8)
+++ src/services/ActivityPubService.js	(revision 04aca127f687555898a105a2c443ff35b6a3c670)
@@ -2482,4 +2482,14 @@
         setMyReaction(site.slug, targetUri, kind, true);
         if (type === 'Announce' && note) { try { upsertBoostedNote(site.slug, note); } catch { /* non-fatal */ } }
+        // Een Like uit een app moet ook in ap_timeline.liked landen, want dat
+        // is wat de C2S-tijdlijn als shaer:liked teruggeeft. Zonder dit werd
+        // de reactie wel opgeslagen (setMyReaction, de webroute leest die),
+        // maar kreeg de app altijd liked:false terug: het hartje sprong bij de
+        // eerste herlaadbeurt uit, en un-liken kon niet meer -- de app bood
+        // alleen nog "Like" aan en stuurde bij elke tik een nieuwe Like.
+        // Anders dan bij een boost geen upsert: een like hoort een post niet
+        // in je tijdlijn te trekken, dus staat de post er niet in, dan is dit
+        // terecht een no-op.
+        if (type === 'Like') { try { markLiked(site.slug, objUri); } catch { /* non-fatal */ } }
         return { status: 202, url: objUri };
       }
@@ -2532,4 +2542,5 @@
           setMyReaction(site.slug, innerTarget, innerType === 'Announce' ? 'boost' : 'like', false);
           if (innerType === 'Announce') { try { unmarkBoosted(site.slug, objUri); } catch { /* non-fatal */ } }
+          if (innerType === 'Like') { try { unmarkLiked(site.slug, objUri); } catch { /* non-fatal */ } }
           return { status: 202, url: objUri };
         }
