[object Object]

← back to build-pages

ui: prev/next project nav on /p/:slug — wraps at registry ends + 1 smoke

0c0d61c455f103667753afe0fd20bd613d8492a6 · 2026-05-13 17:47:05 -0700 · SteveStudio2

Files touched

Diff

commit 0c0d61c455f103667753afe0fd20bd613d8492a6
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 13 17:47:05 2026 -0700

    ui: prev/next project nav on /p/:slug — wraps at registry ends + 1 smoke
---
 server.js     | 17 +++++++++++++++++
 test/smoke.js |  1 +
 2 files changed, 18 insertions(+)

diff --git a/server.js b/server.js
index 2fe46ca..8cd00ba 100644
--- a/server.js
+++ b/server.js
@@ -480,6 +480,12 @@ app.get('/p/:slug', async (req, res, next) => {
   if (!p) return res.status(404).send(shell('Not found', '<h1>404</h1><p>No such project.</p>'));
   try {
     const { commits, facets, files } = await getProjectBundle(req.params.slug, p);
+    // Prev/next links across the registry — lets you cycle through journals
+    // without bouncing back to the home page each time. Wraps at the ends.
+    const slugs = Object.keys(PROJECTS);
+    const idx = slugs.indexOf(req.params.slug);
+    const prevSlug = slugs[(idx - 1 + slugs.length) % slugs.length];
+    const nextSlug = slugs[(idx + 1) % slugs.length];
     const idxData = JSON.stringify(commits.map(c => ({
       h: c.shortHash, d: c.dateISO.slice(0, 10), s: c.subject, b: c.body.slice(0, 4000),
     })));
@@ -555,6 +561,17 @@ app.get('/p/:slug', async (req, res, next) => {
         <ul class="bp-files">${fileLis}</ul>
       </section>
 
+      <section class="bp-section">
+        <h2>Other build journals</h2>
+        <p class="bp-meta">
+          <a href="/p/${esc(prevSlug)}">← ${esc(PROJECTS[prevSlug].name)}</a>
+          &nbsp;·&nbsp;
+          <a href="/">all 4 projects</a>
+          &nbsp;·&nbsp;
+          <a href="/p/${esc(nextSlug)}">${esc(PROJECTS[nextSlug].name)} →</a>
+        </p>
+      </section>
+
       <section class="bp-section">
         <h2>Export</h2>
         <p class="bp-meta">
diff --git a/test/smoke.js b/test/smoke.js
index ca8cdfd..bbb3dea 100644
--- a/test/smoke.js
+++ b/test/smoke.js
@@ -172,6 +172,7 @@ function check(name, cond, hint = '') {
   check('feed: at least 1 entry',  /<entry>/.test(r.body));
   r = await fetch('/p/butlr');
   check('butlr: feed autodiscover',/rel="alternate" type="application\/atom\+xml"/.test(r.body));
+  check('butlr: prev/next nav',    /Other build journals/.test(r.body));
 
   // 11b. CSV export (per project)
   r = await fetch('/p/butlr/commits.csv');

← b6ddd07 api: /api/fleet/all one-shot aggregate (projects + velocity  ·  back to build-pages  ·  ui: commit-detail prev/next history nav — walk forward/backw a633cb5 →