← back to Macstudio1 Dashboard
feat: tach history strip — 60s CPU + RAM sparklines above the gauges
92ad6cbde96b7a3ab8bc9ece1e23473c0c4cea5f · 2026-05-07 23:41:30 -0700 · SteveStudio2
Two slim SVG sparklines under a chrome-bezel "TACH" header, charting
the last 60 seconds of CPU% (red) and RAM% (turquoise). Filled
area + outline + dot at the leading edge, on a dot-grid graph-paper
background. Updates each gauge tick (~1.2s).
Pure client-side ring buffer (HIST_LEN=60), no API change, no
server load. Adds visual rhythm so editors can see throughput
patterns instead of just instantaneous needles.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit 92ad6cbde96b7a3ab8bc9ece1e23473c0c4cea5f
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Thu May 7 23:41:30 2026 -0700
feat: tach history strip — 60s CPU + RAM sparklines above the gauges
Two slim SVG sparklines under a chrome-bezel "TACH" header, charting
the last 60 seconds of CPU% (red) and RAM% (turquoise). Filled
area + outline + dot at the leading edge, on a dot-grid graph-paper
background. Updates each gauge tick (~1.2s).
Pure client-side ring buffer (HIST_LEN=60), no API change, no
server load. Adds visual rhythm so editors can see throughput
patterns instead of just instantaneous needles.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
public/index.html | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/public/index.html b/public/index.html
index f907eb3..39bbadb 100644
--- a/public/index.html
+++ b/public/index.html
@@ -409,6 +409,56 @@ header.masthead {
letter-spacing: 0.16em;
}
+/* Tach history strip — under chrome bezel, tachometer aesthetic */
+.hist {
+ margin-bottom: 24px;
+ background: linear-gradient(180deg, #0e1314 0%, #181f20 100%);
+ border: 4px solid var(--chrome-2);
+ border-radius: 6px;
+ padding: 12px 18px;
+ box-shadow: inset 0 0 0 2px var(--chrome-1), inset 0 0 14px rgba(0,0,0,0.6), 0 4px 8px rgba(0,0,0,0.35);
+}
+.hist-title {
+ text-align: center;
+ font-family: 'Special Elite', monospace;
+ font-size: 10px;
+ letter-spacing: 0.32em;
+ color: var(--gold);
+ margin-bottom: 8px;
+ text-transform: uppercase;
+}
+.hist-row {
+ display: grid;
+ grid-template-columns: 60px 1fr 60px;
+ align-items: center;
+ gap: 12px;
+ padding: 4px 0;
+}
+.hist-label {
+ font-family: 'Bowlby One SC', sans-serif;
+ font-size: 13px;
+ letter-spacing: 0.18em;
+ color: var(--cream);
+ text-transform: uppercase;
+}
+.hist-now {
+ font-family: 'JetBrains Mono', monospace;
+ font-variant-numeric: tabular-nums;
+ font-weight: 600;
+ color: var(--metal-glow);
+ text-align: right;
+ font-size: 14px;
+}
+.hist-svg {
+ width: 100%;
+ height: 38px;
+ background:
+ repeating-linear-gradient(0deg, rgba(212,182,131,0.08) 0px, rgba(212,182,131,0.08) 1px, transparent 1px, transparent 19px),
+ repeating-linear-gradient(90deg, rgba(212,182,131,0.06) 0px, rgba(212,182,131,0.06) 1px, transparent 1px, transparent 30px);
+ border: 1px solid var(--chrome-3);
+ border-radius: 2px;
+}
+
/* Engine bay process table — chrome trim, leather background, brass header */
.proc-table {
margin-top: 32px;
@@ -555,6 +605,21 @@ footer a { color: var(--gold); text-decoration: none; }
<main class="dash">
+ <!-- Tachometer-style history strip — last 60 ticks of CPU% + RAM% -->
+ <div class="hist">
+ <div class="hist-title">— TACH · last 60 seconds —</div>
+ <div class="hist-row">
+ <span class="hist-label">CPU</span>
+ <svg id="hist-cpu" class="hist-svg" viewBox="0 0 360 60" preserveAspectRatio="none"></svg>
+ <span class="hist-now" id="hist-cpu-now">0%</span>
+ </div>
+ <div class="hist-row">
+ <span class="hist-label">RAM</span>
+ <svg id="hist-ram" class="hist-svg" viewBox="0 0 360 60" preserveAspectRatio="none"></svg>
+ <span class="hist-now" id="hist-ram-now">0%</span>
+ </div>
+ </div>
+
<!-- LLM panel — Now Broadcasting + per-model rows + ollama proc stats -->
<div class="radio">
<div class="radio-band">— LLM bay · now broadcasting —</div>
@@ -695,6 +760,24 @@ function fmtUptime(secs) {
let CALL_COUNT = 0;
let LAST_MODEL = null;
+const HIST_LEN = 60;
+const histCpu = new Array(HIST_LEN).fill(0);
+const histRam = new Array(HIST_LEN).fill(0);
+
+function paintHist(svgId, data, color) {
+ const svg = document.getElementById(svgId);
+ if (!svg) return;
+ const W = 360, H = 60;
+ const max = 100;
+ const stepX = W / (HIST_LEN - 1);
+ const points = data.map((v, i) => `${(i * stepX).toFixed(1)},${(H - (v / max) * H).toFixed(1)}`).join(' ');
+ const polyArea = `M0,${H} L${points.split(' ').join(' L')} L${W},${H} Z`;
+ svg.innerHTML = `
+ <path d="${polyArea}" fill="${color}" fill-opacity="0.22"/>
+ <polyline points="${points}" fill="none" stroke="${color}" stroke-width="1.6"/>
+ <circle cx="${(HIST_LEN - 1) * stepX}" cy="${H - (data[data.length-1] / max) * H}" r="2.5" fill="${color}"/>
+ `;
+}
async function tick() {
try {
@@ -704,6 +787,14 @@ async function tick() {
setGauge('cpu', r.cpu.total || 0, Math.round(r.cpu.total || 0));
setGauge('ram', r.memory.used_pct || 0, Math.round(r.memory.used_pct || 0));
+ // Push to history ring buffers + paint
+ histCpu.shift(); histCpu.push(r.cpu.total || 0);
+ histRam.shift(); histRam.push(r.memory.used_pct || 0);
+ paintHist('hist-cpu', histCpu, '#c8243a');
+ paintHist('hist-ram', histRam, '#4abdc5');
+ document.getElementById('hist-cpu-now').textContent = (r.cpu.total || 0).toFixed(1) + '%';
+ document.getElementById('hist-ram-now').textContent = (r.memory.used_pct || 0).toFixed(1) + '%';
+
// VRAM = sum of size_vram_bytes across loaded models
const vramBytes = (r.ollama.models || []).reduce((s, m) => s + (m.size_vram_bytes || 0), 0);
const vramGB = vramBytes / (1024 ** 3);
← 78fa648 feat: ticker-tape Ollama HTTP log feed below the gauges
·
back to Macstudio1 Dashboard
·
chore: build version stamp + scroll hint at top of dashboard 29b1797 →