← back to build-pages
ui: fleet-wide search input on home (wired to /api/search, 150ms debounce) + 1 smoke
9494934edecadffa195efc5b4ed349d0aefb6893 · 2026-05-13 13:45:51 -0700 · SteveStudio2
Files touched
M server.jsM test/smoke.js
Diff
commit 9494934edecadffa195efc5b4ed349d0aefb6893
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 13:45:51 2026 -0700
ui: fleet-wide search input on home (wired to /api/search, 150ms debounce) + 1 smoke
---
server.js | 32 ++++++++++++++++++++++++++++++++
test/smoke.js | 1 +
2 files changed, 33 insertions(+)
diff --git a/server.js b/server.js
index d436ffa..ea3272b 100644
--- a/server.js
+++ b/server.js
@@ -310,10 +310,42 @@ app.get('/', async (_req, res, next) => {
<h1>build journals</h1>
<p class="bp-lede">Every build, every commit, every line. Click into a project to see how it actually got made.</p>
<p class="bp-meta">${entries.length} projects · ${totalCommits} commits · ${totalIdeas} design-rationale ideas surfaced</p>
+
+ <section class="bp-section">
+ <h2>Search the whole fleet</h2>
+ <input id="fleet-q" class="bp-q" type="search" placeholder="search every commit across every project…" autocomplete="off">
+ <p id="fleet-tally" class="bp-meta">type ≥ 2 characters to search</p>
+ <ol id="fleet-hits" class="bp-commits"></ol>
+ </section>
+
+ <h2>Projects</h2>
<ul class="bp-cards">${rows}</ul>
`, `
<script type="application/ld+json">${JSON.stringify(jsonld)}</script>
<script type="application/ld+json">${JSON.stringify(itemList)}</script>
+ <script>
+ const fq = document.getElementById('fleet-q');
+ const ft = document.getElementById('fleet-tally');
+ const fh = document.getElementById('fleet-hits');
+ let pending = null;
+ async function doFleetSearch() {
+ const q = fq.value.trim();
+ if (q.length < 2) { ft.textContent = 'type ≥ 2 characters to search'; fh.innerHTML = ''; return; }
+ ft.textContent = 'searching…';
+ const r = await fetch('/api/search?q=' + encodeURIComponent(q) + '&limit=50');
+ const data = await r.json();
+ ft.textContent = data.total + ' hits across the fleet';
+ fh.innerHTML = data.results.map(h => \`<li>
+ <a href="/p/\${h.slug}/c/\${h.hash}"><code>\${h.hash}</code></a>
+ <span class="bp-d">\${h.date}</span>
+ <span class="bp-s"><strong>\${h.project}</strong> — \${h.subject.replace(/</g,'<')}</span>
+ </li>\`).join('');
+ }
+ fq.addEventListener('input', () => {
+ if (pending) clearTimeout(pending);
+ pending = setTimeout(doFleetSearch, 150);
+ });
+ </script>
`));
} catch (e) { next(e); }
});
diff --git a/test/smoke.js b/test/smoke.js
index 897bb83..5935c4a 100644
--- a/test/smoke.js
+++ b/test/smoke.js
@@ -81,6 +81,7 @@ function check(name, cond, hint = '') {
check('home: og:title', /property="og:title"/.test(r.body));
check('home: WebSite JSON-LD', /"@type":"WebSite"/.test(r.body));
check('home: ItemList JSON-LD', /"@type":"ItemList"/.test(r.body));
+ check('home: fleet search input',/id="fleet-q"/.test(r.body));
// 6. butlr project page renders + has commit count
r = await fetch('/p/butlr');
← eb2ab40 api: /api/search?q= — cross-project commit search (min 2 cha
·
back to build-pages
·
api/search: round-robin merge + by_project breakdown (no sin aafba88 →