[object Object]

← back to build-pages

ui: /about page explaining build-pages + sitemap + footer link + 3 smoke

e4c31da91892f071b2b1a270495dce70a51f328a · 2026-05-13 19:29:06 -0700 · SteveStudio2

Files touched

Diff

commit e4c31da91892f071b2b1a270495dce70a51f328a
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 13 19:29:06 2026 -0700

    ui: /about page explaining build-pages + sitemap + footer link + 3 smoke
---
 server.js     | 38 +++++++++++++++++++++++++++++++++++++-
 test/smoke.js |  6 ++++++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/server.js b/server.js
index 862731a..76b1477 100644
--- a/server.js
+++ b/server.js
@@ -211,6 +211,8 @@ function shell(title, body, headExtra = '', meta = {}) {
   <footer class="bp-ftr">
     <span>git is the source of truth — this page is rendered live from <code>git log</code>.</span>
     <span class="bp-ftr-sep">·</span>
+    <a href="/about">about</a>
+    <span class="bp-ftr-sep">·</span>
     <a href="/api">JSON API</a>
     <span class="bp-ftr-sep">·</span>
     <a href="/sitemap.xml">sitemap</a>
@@ -264,7 +266,10 @@ app.get('/sitemap.xml', async (_req, res, next) => {
   try {
     const base = 'https://projects.agentabrams.com';
     const today = new Date().toISOString().slice(0, 10);
-    const urls = [`<url><loc>${base}/</loc><lastmod>${today}</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url>`];
+    const urls = [
+      `<url><loc>${base}/</loc><lastmod>${today}</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url>`,
+      `<url><loc>${base}/about</loc><lastmod>${today}</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url>`,
+    ];
     for (const slug of Object.keys(PROJECTS)) {
       const bundle = await getProjectBundle(slug, PROJECTS[slug]).catch(() => null);
       const lastmod = (bundle && bundle.commits[0]) ? bundle.commits[0].dateISO.slice(0, 10) : today;
@@ -1198,6 +1203,37 @@ app.get('/api/projects/:slug', async (req, res, next) => {
   } catch (e) { next(e); }
 });
 
+// /about — short explainer for visitors arriving at projects.agentabrams.com.
+app.get('/about', (_req, res) => {
+  res.send(shell('About — build-pages', `
+    <h1>About</h1>
+    <p class="bp-lede">build-pages is a live build journal for every project in Steve Abrams' workshop.</p>
+
+    <p>Every project here is a real git repo. The pages you're reading are rendered live from <code>git log</code>
+    on each refresh — no static export step, no CI build job. New commits appear within seconds of
+    landing locally.</p>
+
+    <h2>What you'll find</h2>
+    <ul>
+      <li><strong>Every commit</strong> — full subject, body, author, date, files touched, diff</li>
+      <li><strong>Search</strong> — across one project (<code>/p/&lt;slug&gt;?q=…</code>) or the whole fleet (<code>/?q=…</code>)</li>
+      <li><strong>Design rationale</strong> — long commit bodies (≥120 chars) are surfaced as "ideas"</li>
+      <li><strong>Sub-agents + skills used</strong> — auto-extracted from commit messages</li>
+      <li><strong>Authors + velocity</strong> — daily commit shape, who pushed what, rolling 24h / 7d counts</li>
+      <li><strong>Exports</strong> — every project ships .csv, .atom, JSON detail at <a href="/api">/api</a></li>
+    </ul>
+
+    <h2>Pattern</h2>
+    <p>git is the source of truth. The site reads a per-repo bundle keyed on HEAD SHA — when HEAD moves,
+    the cache invalidates and the next request rebuilds it. Cold render ~80ms, warm hit ~17ms.</p>
+
+    <p class="bp-meta"><a href="/">← back to all projects</a></p>
+  `, '', {
+    canonical: 'https://projects.agentabrams.com/about',
+    desc: 'build-pages — a live, git-rendered build journal for every project Steve ships.',
+  }));
+});
+
 // Branded 404 — every other site in the fleet has one, parity matters.
 app.use((req, res) => {
   res.status(404).send(shell('Not found — build-pages', `
diff --git a/test/smoke.js b/test/smoke.js
index 7fc052b..f0f4677 100644
--- a/test/smoke.js
+++ b/test/smoke.js
@@ -154,6 +154,12 @@ function check(name, cond, hint = '') {
   r = await fetch('/p/nope-not-a-project');
   check('unknown project: 404',    r.status === 404);
 
+  // 7b. /about page
+  r = await fetch('/about');
+  check('about: 200',              r.status === 200);
+  check('about: build-pages title',/About — build-pages/.test(r.body));
+  check('about: explainer copy',   /live build journal/.test(r.body));
+
   // 8. robots.txt — public crawlable + sitemap referenced
   r = await fetch('/robots.txt');
   check('robots: 200',             r.status === 200);

← e8b65d2 api: /api/fleet/buckets — daily commit buckets with ISO labe  ·  back to build-pages  ·  ui: /privacy + /terms boilerplate (no-tracking + as-is) — si 3af9a44 →