Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision 4838760bea2c166af5f7ad6643fc744e663c83fc)
+++ src/routes/activitypub.js	(revision d1075a16677d12c60b0d792c821a5baea451185d)
@@ -179,5 +179,5 @@
   const fanClause = audience === 'friend' ? '' : "AND (fan_only IS NULL OR fan_only = 0)";
   const posts = db.prepare(
-    `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, c2s_attachments, published_at, created_at
+    `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, c2s_attachments, quote_json, embed_json, published_at, created_at
      FROM posts WHERE site_id = ? AND status = 'published' ${fanClause}
      ORDER BY COALESCE(published_at, created_at) DESC LIMIT 20`
Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 4838760bea2c166af5f7ad6643fc744e663c83fc)
+++ src/services/ActivityPubService.js	(revision d1075a16677d12c60b0d792c821a5baea451185d)
@@ -2949,6 +2949,13 @@
   // IS the notification.
   const quoteInboxes = [];
+  // EERST BAKKEN, dan pas linken zoeken (shaer-k3f, gevonden op het toestel):
+  // firstExternalUrl leest <a href>-ankers, en de web-editor bakt die er bij
+  // het opslaan al in -- maar een post uit de APP is platte tekst waarin de
+  // URL nog geen anker is. Zonder deze bak zag het C2S-pad dus nooit een link
+  // en kreeg een app-post nooit een kaart, terwijl de preview hem net wel
+  // beloofd had.
+  const gebakken = bakePostContent(post2.content || '');
   if (post2.quote_uri === undefined || post2.quote_uri === null) {
-    const q = await resolveOwnQuote(post2.content || '');
+    const q = await resolveOwnQuote(gebakken);
     if (q) {
       try { db.prepare('UPDATE posts SET quote_uri = ?, quote_actor = ? WHERE id = ?').run(q.uri, q.actor || null, post.id); } catch { /* ignore */ }
@@ -2968,5 +2975,5 @@
         if (qj) { db.prepare('UPDATE posts SET quote_json = ? WHERE id = ?').run(qj, post.id); post2 = { ...post2, quote_json: qj }; }
       } else {
-        const ej = await resolveExternalEmbed(post2.content || '');
+        const ej = await resolveExternalEmbed(gebakken);
         if (ej) { db.prepare('UPDATE posts SET embed_json = ? WHERE id = ?').run(ej, post.id); post2 = { ...post2, embed_json: ej }; }
       }
Index: test/own-card.test.js
===================================================================
--- test/own-card.test.js	(revision 4838760bea2c166af5f7ad6643fc744e663c83fc)
+++ test/own-card.test.js	(revision d1075a16677d12c60b0d792c821a5baea451185d)
@@ -46,6 +46,9 @@
 
 test('een externe link in een eigen post wordt een embed-snapshot op de post', async () => {
+  // PLATTE tekst, geen anker: zo komt een post uit de app binnen (het
+  // C2S-pad bakt niet voor het opslaan). Op het toestel bleef precies dit
+  // geval een kale link terwijl de web-editor wel een kaart kreeg.
   db.prepare("INSERT INTO posts (id, site_id, author_id, slug, title, content, status) VALUES ('p1','s1','u1','p1','', ?, 'published')")
-    .run(`<p>Kijk: <a href="${EXTERN}">${EXTERN}</a></p>`);
+    .run(`<p>Kijk: ${EXTERN}</p>`);
   const post = db.prepare("SELECT * FROM posts WHERE id = 'p1'").get();
   await AP.deliverCreate(site, post);
