← back to build-pages
home: 7-day velocity sparkline (Unicode block-chars, scales to max bucket) + 1 smoke
b6fe68d3fc5e02381d28cf43a68e0c5b9fd34333 · 2026-05-13 19:13:57 -0700 · SteveStudio2
Files touched
M public/css/site.cssM server.jsM test/smoke.js
Diff
commit b6fe68d3fc5e02381d28cf43a68e0c5b9fd34333
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 19:13:57 2026 -0700
home: 7-day velocity sparkline (Unicode block-chars, scales to max bucket) + 1 smoke
---
public/css/site.css | 1 +
server.js | 15 ++++++++++++++-
test/smoke.js | 1 +
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/public/css/site.css b/public/css/site.css
index 33b782d..b038ebb 100644
--- a/public/css/site.css
+++ b/public/css/site.css
@@ -111,6 +111,7 @@ h2 { font-size: 20px; font-weight: 700; margin: 36px 0 14px; letter-spacing: -0.
.bp-body { margin: 20px 0; }
.bp-body pre { background: var(--code-bg); white-space: pre-wrap; }
.bp-diff { font-size: 12px; max-height: 70vh; overflow: auto; }
+.bp-spark { font-family: ui-monospace, Menlo, monospace; letter-spacing: 1px; color: var(--link); background: var(--code-bg); padding: 1px 6px; border-radius: 4px; }
.bp-load { font-family: ui-monospace, Menlo, monospace; padding: 1px 6px; border-radius: 4px; font-weight: 600; }
.bp-load-ok { background: rgba(31,122,48,0.15); color: #1f7a30; }
.bp-load-warn { background: rgba(196,140,30,0.18); color: #9b6f15; }
diff --git a/server.js b/server.js
index f7790c1..f967b50 100644
--- a/server.js
+++ b/server.js
@@ -331,14 +331,27 @@ app.get('/', async (req, res, next) => {
const now = Date.now();
const dayMs = 24 * 60 * 60 * 1000;
let last24 = 0, last7d = 0;
+ // Per-day buckets for the last 7 days (index 0 = oldest, 6 = today). Used
+ // to render a tiny Unicode sparkline so a glance at the home page shows
+ // the velocity shape, not just two scalars.
+ const dayBuckets = new Array(7).fill(0);
for (const e of entries) {
const b = _projectCache.get(e.slug); if (!b) continue;
for (const c of b.commits) {
const age = now - new Date(c.dateISO).getTime();
if (age < dayMs) last24++;
if (age < 7 * dayMs) last7d++;
+ if (age < 7 * dayMs && age >= 0) {
+ const dayIdx = 6 - Math.floor(age / dayMs);
+ if (dayIdx >= 0 && dayIdx < 7) dayBuckets[dayIdx]++;
+ }
}
}
+ // Render Unicode block sparkline. Empty buckets = ' ', full bar height
+ // scales to max non-zero day so the shape is always readable.
+ const blocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
+ const maxBucket = Math.max(...dayBuckets, 1);
+ const sparkline = dayBuckets.map(n => n === 0 ? ' ' : blocks[Math.min(7, Math.floor((n / maxBucket) * 7))]).join('');
const rows = entries.map(({ slug, p, count, latest, ideas }) => `<li class="bp-card">
<a href="/p/${esc(slug)}"><h2>${esc(p.name)}</h2></a>
<p>${esc(p.blurb)}</p>
@@ -383,7 +396,7 @@ 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>
- <p class="bp-meta">velocity: <strong>${last24}</strong> commits in the last 24h · <strong>${last7d}</strong> in the last 7 days · ${(() => {
+ <p class="bp-meta">velocity: <strong>${last24}</strong> commits in the last 24h · <strong>${last7d}</strong> in the last 7 days · 7-day shape <code class="bp-spark" title="${dayBuckets.join(' / ')}">${sparkline}</code> · ${(() => {
const [l1] = require('os').loadavg();
const cls = l1 < 8 ? 'bp-load-ok' : l1 < 20 ? 'bp-load-warn' : 'bp-load-hot';
return `host load <span class="bp-load ${cls}">${l1.toFixed(1)}</span> (1m)`;
diff --git a/test/smoke.js b/test/smoke.js
index da228f3..4074c32 100644
--- a/test/smoke.js
+++ b/test/smoke.js
@@ -98,6 +98,7 @@ function check(name, cond, hint = '') {
check('home: top skills rail', /Top skills \+ agents/.test(r.body));
check('home: velocity line', /velocity: <strong>\d+<\/strong>/.test(r.body));
check('home: load badge', /class="bp-load (bp-load-ok|bp-load-warn|bp-load-hot)"/.test(r.body));
+ check('home: 7-day sparkline', /class="bp-spark"/.test(r.body));
check('home: canonical', /rel="canonical"/.test(r.body));
check('home: og:title', /property="og:title"/.test(r.body));
check('home: WebSite JSON-LD', /"@type":"WebSite"/.test(r.body));
← b806ffd api/fleet/authors + Authors chip rail on /p/:slug — uses can
·
back to build-pages
·
p/:slug: per-project 7-day sparkline in meta line 59b1208 →