Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 98688c68b4657b7d6e1b4341c8d501647e9a20c7)
+++ src/services/ActivityPubService.js	(revision 484adf8ccf46e039e63d59739649349e39fc0115)
@@ -662,8 +662,10 @@
         }
         const media = JSON.stringify(_atts);
+        // "Feature" = show in the Cirkel (local only). We do NOT auto-Announce
+        // incoming posts to the fediverse — that flooded followers (esp. on the
+        // initial backfill). Boosting to the fediverse is a deliberate, one-time
+        // "boost the latest 5" action at feature time (see boostLatestN).
         for (const s of subs) {
           tlStmts().ins.run(o.id, s.slug, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, o.url || null, o.published || null, media);
-          // "Feature an artist": auto-boost (re-Announce) their new posts to our own followers.
-          if (s.auto_boost) sendInteraction({ slug: s.slug }, 'boost', o.id, actorUri).catch(() => { /* best-effort */ });
         }
         console.log('[AP] timeline +', actorUri, 'x' + subs.length);
@@ -1181,5 +1183,5 @@
   catch (e) { console.warn('[AP] follow deliver failed:', e.message); }
   console.log('[AP] follow', site.slug, '→', actor.id);
-  return { ok: true, name: ai.name, handle: ai.handle };
+  return { ok: true, name: ai.name, handle: ai.handle, actor: actor.id };
 }
 
@@ -1231,4 +1233,29 @@
   console.log('[AP]', type, site.slug, '→', targetNoteId, 'delivered', delivered);
   return { ok: true, delivered };
+}
+
+// One-time "boost the latest N posts" of an account to the fediverse — the
+// deliberate, bounded alternative to auto-boosting every post. Opt-in at feature
+// time so featuring an artist never floods your followers with their whole backlog.
+export async function boostLatestN(site, actorUrl, n = 5) {
+  try {
+    const actor = await fetchActor(actorUrl).catch(() => null);
+    if (!actor || !actor.outbox) return { ok: false, boosted: 0 };
+    const getJson = async (u) => { try { const r = await fetch(u, { headers: { Accept: 'application/activity+json' } }); return r.ok ? await r.json() : null; } catch { return null; } };
+    let coll = await getJson(actor.outbox);
+    let items = (coll && coll.orderedItems) || [];
+    if (!items.length && coll && coll.first) {
+      const page = typeof coll.first === 'string' ? await getJson(coll.first) : coll.first;
+      items = (page && page.orderedItems) || [];
+    }
+    const noteIds = items
+      .filter((it) => it && it.type === 'Create' && it.object)
+      .map((it) => (typeof it.object === 'string' ? it.object : it.object.id))
+      .filter(Boolean)
+      .slice(0, n); // outbox is newest-first → the latest N
+    let boosted = 0;
+    for (const id of noteIds) { try { const r = await sendInteraction(site, 'boost', id, actorUrl); if (r && r.ok) boosted++; } catch { /* best-effort */ } }
+    return { ok: true, boosted };
+  } catch { return { ok: false, boosted: 0 }; }
 }
 
@@ -1319,5 +1346,5 @@
   listOutbox, deliverOutboxDelete,
   webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, getTimeline, sendInteraction,
-  autoBoostCount, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline,
+  autoBoostCount, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline, boostLatestN,
   getNotifications, listBlocks, isBlockedAny, blockTarget, unblock,
   deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker,
