Index: CHANGELOG.md
===================================================================
--- CHANGELOG.md	(revision f4b7b6a930558498ae023cb97614353f0e9a89ef)
+++ CHANGELOG.md	(revision 1e2e9e796a68983531a8d24e36c35e9319d25413)
@@ -15,4 +15,7 @@
 
 ### Gewijzigd
+- De Newer/Older-postnavigatie staat nu óók op de fan-gate (login-wall van een
+  fan-only post), zodat een bezoeker niet vastloopt maar verder kan bladeren.
+  Nav verhuisd naar een gedeeld partial (`partials/post-nav.ejs`).
 - Login gesplitst: de publieke loginpagina (`/auth/login`) toont voor bezoekers nu
   **alleen** Google-login (luisteraars/fans). De beheerders-login (gebruikersnaam +
Index: src/routes/posts.js
===================================================================
--- src/routes/posts.js	(revision f4b7b6a930558498ae023cb97614353f0e9a89ef)
+++ src/routes/posts.js	(revision 1e2e9e796a68983531a8d24e36c35e9319d25413)
@@ -394,4 +394,29 @@
 });
 
+// Newer/Older-buren over ALLE posts in feed-volgorde. Gedeeld door de volledige
+// post-render én de fan-gate (premium fan_only), zodat de navigatie overal gelijk
+// is. Solo: binnen de site (pinned eerst, dan datum). Hub: globaal op datum.
+function postNeighbors(site, post, isHub) {
+  const urlBaseFor = (p) => (isHub && p && p.site_slug) ? `/user/${p.site_slug}` : '';
+  const ordered = isHub
+    ? db.prepare(`
+        SELECT p.id, p.slug, p.title, s.slug AS site_slug
+        FROM posts p JOIN sites s ON s.id = p.site_id
+        WHERE p.status = 'published'
+        ORDER BY p.published_at DESC
+      `).all()
+    : db.prepare(`
+        SELECT id, slug, title FROM posts
+        WHERE site_id = ? AND status = 'published'
+        ORDER BY (pinned = 0) ASC, pinned ASC, published_at DESC
+      `).all(site.id);
+  const idx = ordered.findIndex((p) => p.id === post.id);
+  const newerPost = idx > 0 ? ordered[idx - 1] : null;
+  const olderPost = (idx >= 0 && idx < ordered.length - 1) ? ordered[idx + 1] : null;
+  if (newerPost) newerPost._urlBase = urlBaseFor(newerPost);
+  if (olderPost) olderPost._urlBase = urlBaseFor(olderPost);
+  return { newerPost, olderPost };
+}
+
 // ==================== VIEW POST (last route â€” catches /:slug) ====================
 router.get('/:slug', (req, res, next) => {
@@ -419,4 +444,7 @@
   // teaser mag elders wel als lokkertje verschijnen).
   if (post.fan_only && !(req.session && req.session.user)) {
+    // Zelfde Newer/Older-navigatie als op een gewone post, zodat de bezoeker op
+    // de fan-gate niet vastloopt maar verder kan bladeren.
+    const { newerPost, olderPost } = postNeighbors(site, post, res.locals.tenancy === 'hub');
     return renderPage(req, res, 'pages/fan-gate', {
       pageTitle: post.title || 'Alleen voor fans',
@@ -424,4 +452,6 @@
       fgTitle: post.title || '',
       fgNext: (res.locals.siteUrlBase || '') + '/' + post.slug,
+      newerPost,
+      olderPost,
     });
   }
@@ -545,26 +575,6 @@
   const urlBaseFor = (p) => (isHub && p && p.site_slug) ? `/user/${p.site_slug}` : '';
 
-  // Newer/Older over ALLE posts, in de canonieke feed-volgorde — niet alleen de
-  // pinned-stack. Solo: binnen de site, pinned eerst op rank, dan op datum
-  // (zelfde volgorde als de homepage-feed). Hub: globaal op datum over alle
-  // sites. De vorige positie in de lijst = "Newer" (← omhoog), de volgende =
-  // "Older" (→ omlaag). Pinned posts zitten zo gewoon in de doorlopende reeks.
-  const ordered = isHub
-    ? db.prepare(`
-        SELECT p.id, p.slug, p.title, s.slug AS site_slug
-        FROM posts p JOIN sites s ON s.id = p.site_id
-        WHERE p.status = 'published'
-        ORDER BY p.published_at DESC
-      `).all()
-    : db.prepare(`
-        SELECT id, slug, title FROM posts
-        WHERE site_id = ? AND status = 'published'
-        ORDER BY (pinned = 0) ASC, pinned ASC, published_at DESC
-      `).all(site.id);
-  const _idx = ordered.findIndex((p) => p.id === post.id);
-  const newerPost = _idx > 0 ? ordered[_idx - 1] : null;
-  const olderPost = (_idx >= 0 && _idx < ordered.length - 1) ? ordered[_idx + 1] : null;
-  if (newerPost) newerPost._urlBase = urlBaseFor(newerPost);
-  if (olderPost) olderPost._urlBase = urlBaseFor(olderPost);
+  // Newer/Older over ALLE posts (gedeelde helper — ook door de fan-gate gebruikt).
+  const { newerPost, olderPost } = postNeighbors(site, post, isHub);
 
   // ── Related posts: same-tag matching with recency fallback ─────
Index: src/views/pages/fan-gate.ejs
===================================================================
--- src/views/pages/fan-gate.ejs	(revision f4b7b6a930558498ae023cb97614353f0e9a89ef)
+++ src/views/pages/fan-gate.ejs	(revision 1e2e9e796a68983531a8d24e36c35e9319d25413)
@@ -1,2 +1,8 @@
+<div class="container">
+  <%# Zelfde post-navigatie (Newer/Older) als op een gewone post, zodat een
+      bezoeker op de fan-gate niet vastloopt maar verder kan bladeren. %>
+  <%- include('../partials/post-nav', { newerPost: (typeof newerPost !== 'undefined' ? newerPost : null), olderPost: (typeof olderPost !== 'undefined' ? olderPost : null) }) %>
+</div>
+
 <section class="fg">
   <div class="fg-card">
Index: src/views/pages/post.ejs
===================================================================
--- src/views/pages/post.ejs	(revision f4b7b6a930558498ae023cb97614353f0e9a89ef)
+++ src/views/pages/post.ejs	(revision 1e2e9e796a68983531a8d24e36c35e9319d25413)
@@ -7,35 +7,6 @@
 <article class="container post-page">
 
-  <%# Navigatie over ALLE posts — BOVEN de post (Newer links, Older rechts). %>
-  <% if (newerPost || olderPost) { %>
-    <nav class="post-nav post-nav--top">
-      <% if (newerPost) { %>
-        <a class="post-nav-prev" href="<%= newerPost._urlBase || '' %>/<%= newerPost.slug %>"<% if (!newerPost._urlBase) { %>
-           hx-get="/<%= newerPost.slug %>?partial=1" hx-target="#pcms-main"
-           hx-push-url="/<%= newerPost.slug %>" hx-indicator="#pcms-loading"<% } %>>
-          <span class="post-nav-label">← Newer</span>
-          <span class="post-nav-title"><%= newerPost.title %></span>
-        </a>
-      <% } else { %>
-        <div class="post-nav-prev is-empty" aria-hidden="true">
-          <span class="post-nav-label">← Newer</span>
-          <span class="post-nav-title">Nieuwste post</span>
-        </div>
-      <% } %>
-      <% if (olderPost) { %>
-        <a class="post-nav-next" href="<%= olderPost._urlBase || '' %>/<%= olderPost.slug %>"<% if (!olderPost._urlBase) { %>
-           hx-get="/<%= olderPost.slug %>?partial=1" hx-target="#pcms-main"
-           hx-push-url="/<%= olderPost.slug %>" hx-indicator="#pcms-loading"<% } %>>
-          <span class="post-nav-label">Older →</span>
-          <span class="post-nav-title"><%= olderPost.title %></span>
-        </a>
-      <% } else { %>
-        <div class="post-nav-next is-empty" aria-hidden="true">
-          <span class="post-nav-label">Older →</span>
-          <span class="post-nav-title">Oudste post</span>
-        </div>
-      <% } %>
-    </nav>
-  <% } %>
+  <%# Navigatie over ALLE posts — BOVEN de post (gedeeld partial). %>
+  <%- include('../partials/post-nav', { newerPost: newerPost, olderPost: olderPost }) %>
 
   <% if (post.cover_image_url) { %>
@@ -290,16 +261,4 @@
 .tag:hover { background: var(--accent); color: white; }
 .post-actions { display: flex; gap: 0.5rem; margin: 2rem 0; padding: 1rem; background: var(--paper-2); border-radius: 6px; flex-wrap: wrap; }
-.post-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--rule); }
-/* Boven de post: geen lijn/gap erboven, maar een scheidingslijn ERONDER (naar de content). */
-.post-nav--top { margin-top: 0; padding-top: 0; border-top: 0; margin-bottom: 2rem; padding-bottom: 2rem; border-bottom: 1px solid var(--rule); }
-.post-nav-prev, .post-nav-next { display: flex; flex-direction: column; padding: 1rem; background: var(--paper-2); border-radius: 6px; text-decoration: none; color: var(--ink); }
-/* Lege plek (geen nieuwere/oudere post): zelfde kaart, uitgegrijsd + niet klikbaar,
-   zodat elke post dezelfde twee-kaarten-structuur houdt. */
-.post-nav-prev.is-empty, .post-nav-next.is-empty { opacity: 0.4; cursor: default; }
-.post-nav-prev.is-empty .post-nav-title, .post-nav-next.is-empty .post-nav-title { font-weight: 400; font-style: italic; color: var(--ink-muted); }
-.post-nav-next { text-align: right; align-items: flex-end; }
-.post-nav-label { font-size: 0.8rem; color: var(--ink-muted); margin-bottom: 0.25rem; }
-.post-nav-title { font-weight: 500; }
-@media (max-width: 600px) { .post-nav { grid-template-columns: 1fr; } }
 
 /* ============================================================
Index: src/views/partials/post-nav.ejs
===================================================================
--- src/views/partials/post-nav.ejs	(revision 1e2e9e796a68983531a8d24e36c35e9319d25413)
+++ src/views/partials/post-nav.ejs	(revision 1e2e9e796a68983531a8d24e36c35e9319d25413)
@@ -0,0 +1,48 @@
+<%# Post-navigatie (Newer links / Older rechts) — gedeeld door post.ejs én
+    fan-gate.ejs. Verwacht newerPost + olderPost in scope. Ontbreekt een buur,
+    dan een uitgegrijsde placeholder zodat elke post dezelfde structuur houdt. %>
+<% if ((typeof newerPost !== 'undefined' && newerPost) || (typeof olderPost !== 'undefined' && olderPost)) { %>
+  <nav class="post-nav post-nav--top">
+    <% if (newerPost) { %>
+      <a class="post-nav-prev" href="<%= newerPost._urlBase || '' %>/<%= newerPost.slug %>"<% if (!newerPost._urlBase) { %>
+         hx-get="/<%= newerPost.slug %>?partial=1" hx-target="#pcms-main"
+         hx-push-url="/<%= newerPost.slug %>" hx-indicator="#pcms-loading"<% } %>>
+        <span class="post-nav-label">← Newer</span>
+        <span class="post-nav-title"><%= newerPost.title %></span>
+      </a>
+    <% } else { %>
+      <div class="post-nav-prev is-empty" aria-hidden="true">
+        <span class="post-nav-label">← Newer</span>
+        <span class="post-nav-title">Nieuwste post</span>
+      </div>
+    <% } %>
+    <% if (olderPost) { %>
+      <a class="post-nav-next" href="<%= olderPost._urlBase || '' %>/<%= olderPost.slug %>"<% if (!olderPost._urlBase) { %>
+         hx-get="/<%= olderPost.slug %>?partial=1" hx-target="#pcms-main"
+         hx-push-url="/<%= olderPost.slug %>" hx-indicator="#pcms-loading"<% } %>>
+        <span class="post-nav-label">Older →</span>
+        <span class="post-nav-title"><%= olderPost.title %></span>
+      </a>
+    <% } else { %>
+      <div class="post-nav-next is-empty" aria-hidden="true">
+        <span class="post-nav-label">Older →</span>
+        <span class="post-nav-title">Oudste post</span>
+      </div>
+    <% } %>
+  </nav>
+<% } %>
+
+<style>
+.post-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--rule); }
+/* Boven de post: geen lijn/gap erboven, maar een scheidingslijn ERONDER (naar de content). */
+.post-nav--top { margin-top: 0; padding-top: 0; border-top: 0; margin-bottom: 2rem; padding-bottom: 2rem; border-bottom: 1px solid var(--rule); }
+.post-nav-prev, .post-nav-next { display: flex; flex-direction: column; padding: 1rem; background: var(--paper-2); border-radius: 6px; text-decoration: none; color: var(--ink); }
+/* Lege plek (geen nieuwere/oudere post): zelfde kaart, uitgegrijsd + niet klikbaar,
+   zodat elke post dezelfde twee-kaarten-structuur houdt. */
+.post-nav-prev.is-empty, .post-nav-next.is-empty { opacity: 0.4; cursor: default; }
+.post-nav-prev.is-empty .post-nav-title, .post-nav-next.is-empty .post-nav-title { font-weight: 400; font-style: italic; color: var(--ink-muted); }
+.post-nav-next { text-align: right; align-items: flex-end; }
+.post-nav-label { font-size: 0.8rem; color: var(--ink-muted); margin-bottom: 0.25rem; }
+.post-nav-title { font-weight: 500; }
+@media (max-width: 600px) { .post-nav { grid-template-columns: 1fr; } }
+</style>
