[object Object]

← 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 →