Index: src/views/partials/read-article.ejs
===================================================================
--- src/views/partials/read-article.ejs	(revision b67edbdfb84f7d125475d92c470edf68a7886ccf)
+++ src/views/partials/read-article.ejs	(revision b67edbdfb84f7d125475d92c470edf68a7886ccf)
@@ -0,0 +1,31 @@
+<%
+// Eén bericht in de leesstroom.
+//
+// Dit is het stuk dat de client AANVULT: bij de onderrand komt de oudere buur
+// eronder, bij de bovenrand de nieuwere erboven. Geen sprongen, geen
+// scrollpositie die stiekem verzet wordt -- de stroom groeit gewoon in de
+// richting waarin je leest, en de browser snapt naar de grenzen.
+//
+// Elk artikel draagt zijn eigen buren, dus de client hoeft niets te onthouden:
+// wat er nog te halen valt staat op het stuk dat er al is.
+var _b = (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '';
+var _newer = (typeof newerPost !== 'undefined' && newerPost) ? newerPost : null;
+var _older = (typeof olderPost !== 'undefined' && olderPost) ? olderPost : null;
+%>
+<article class="read-post"
+         data-slug="<%= post.slug %>"
+         data-newer="<%= _newer ? _newer.slug : '' %>"
+         data-older="<%= _older ? _older.slug : '' %>"
+         data-base="<%= _b %>"
+         data-title="<%= post.title || '' %>"
+         aria-label="<%= post.title || '' %>">
+  <header class="read-head">
+    <h1 class="read-title"><%= post.title || '' %></h1>
+    <% if (post.published_at) { %><p class="read-when"><%= formatDateTime(post.published_at) %></p><% } %>
+  </header>
+
+  <%- include('post-body', {
+        post: post, access: entry.access, teaser: entry.teaser,
+        content_html: entry.content_html, _base: _b,
+      }) %>
+</article>
