Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision 960f0159a39a973d50321222d1610f881d16e6ae)
+++ src/routes/activitypub.js	(revision bac4bf3573c99662c112c44d1b1519f1159d5762)
@@ -28,4 +28,17 @@
 
 const router = express.Router();
+
+/**
+ * Welke pagina vraagt de lezer? (shaer-sk4)
+ *
+ * Hier stond `!!req.query.page` -- of de parameter er STAAT, niet welke. Daardoor
+ * gaf ?page=2 en ?page=99 allemaal pagina 1, en noemde het antwoord zichzelf ook
+ * nog pagina 1. Onleesbaar getal of geen parameter: dan de wortel.
+ */
+function paginaNr(req) {
+  if (req.query.page === undefined) return false;
+  const n = Math.floor(Number(req.query.page));
+  return Number.isFinite(n) && n > 0 ? n : 1;
+}
 // The whole fediverse layer can be turned off (solo "no federation" mode):
 // then /ap/*, WebFinger and NodeInfo are simply gone — the site is undiscoverable
@@ -182,5 +195,5 @@
   });
   if (audience === 'blocked') {
-    return AP.sendAP(res, AP.buildOutbox(baseUrl(req), site, [], [], { page: !!req.query.page }), 'private, no-store');
+    return AP.sendAP(res, AP.buildOutbox(baseUrl(req), site, [], [], { page: paginaNr(req) }), 'private, no-store');
   }
   const fanClause = audience === 'friend' ? '' : "AND (fan_only IS NULL OR fan_only = 0)";
@@ -192,5 +205,5 @@
   // De tracks gaan mee voor iedereen die de deur door mag; de blocked-tak
   // hierboven levert bewust een outbox ZONDER posts en zonder tracks.
-  const ob = AP.buildOutbox(baseUrl(req), site, posts, AP.siteOpenTracks(site.id), { page: !!req.query.page });
+  const ob = AP.buildOutbox(baseUrl(req), site, posts, AP.siteOpenTracks(site.id), { page: paginaNr(req) });
   if (audience === 'friend') {
     // The owner's app builds its feed from this leg, and every note here is
@@ -986,8 +999,8 @@
     // Default = bare references; enrich only when the client asks (FEP-9876).
     const items = wantsEnriched(req, res) ? uris.map((u) => AP.buildActorRef(site.slug, u)) : uris;
-    return AP.sendAP(res, AP.buildFollowers(baseUrl(req), site, items.length, items));
+    return AP.sendAP(res, AP.buildFollowers(baseUrl(req), site, items.length, items, { page: paginaNr(req) }));
   }
   const n = db.prepare('SELECT COUNT(*) n FROM ap_followers WHERE slug = ?').get(site.slug).n;
-  AP.sendAP(res, AP.buildFollowers(baseUrl(req), site, n));
+  AP.sendAP(res, AP.buildFollowers(baseUrl(req), site, n, null, { page: paginaNr(req) }));
 });
 
@@ -1005,9 +1018,9 @@
       items = enrich ? uris.map((u) => AP.buildActorRef(site.slug, u)) : uris;
     } catch { /* table may not exist */ }
-    return AP.sendAP(res, AP.buildFollowing(baseUrl(req), site, items.length, items));
+    return AP.sendAP(res, AP.buildFollowing(baseUrl(req), site, items.length, items, { page: paginaNr(req) }));
   }
   let n = 0;
   try { n = db.prepare("SELECT COUNT(*) n FROM ap_following WHERE slug = ? AND status = 'accepted'").get(site.slug).n; } catch { /* table may not exist */ }
-  AP.sendAP(res, AP.buildFollowing(baseUrl(req), site, n));
+  AP.sendAP(res, AP.buildFollowing(baseUrl(req), site, n, null, { page: paginaNr(req) }));
 });
 
