← back to Ventura Corridor
feat(fleet): Mac1+Mac2 dashboard bridge on corridor homepage strip
4a0ab3d47b48c849e484188f2f5ca156a81b4240 · 2026-05-08 00:10:40 -0700 · SteveStudio2
Live status of both Mac dashboards now shows on the always-visible /
strip alongside news + ideas counters. Format:
FLEET · Mac Studio 1 · qwen3:14b ⚓ · cpu 38% · ram 57%
· Mac Studio 2 · gemma3:12b · cpu 12% · ram 41%
Each is clickable -> opens the corresponding 57 Bel Air / Eldorado
dashboard. Soft-fails per machine — if Mac1 is unreachable, Mac2 still
renders (and shows red OFFLINE link).
Routes:
GET /api/fleet {macs:[{label,cpu,ram_pct,ollama_models[],
installed_count,ollama_proc,power_mode,
ok,url|error}], ts}
Proxies http://100.94.103.98:9930/api/status (Mac1)
+ http://localhost:9931/api/status (Mac2). 10s cache.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M public/index.htmlM src/server/index.ts
Diff
commit 4a0ab3d47b48c849e484188f2f5ca156a81b4240
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Fri May 8 00:10:40 2026 -0700
feat(fleet): Mac1+Mac2 dashboard bridge on corridor homepage strip
Live status of both Mac dashboards now shows on the always-visible /
strip alongside news + ideas counters. Format:
FLEET · Mac Studio 1 · qwen3:14b ⚓ · cpu 38% · ram 57%
· Mac Studio 2 · gemma3:12b · cpu 12% · ram 41%
Each is clickable -> opens the corresponding 57 Bel Air / Eldorado
dashboard. Soft-fails per machine — if Mac1 is unreachable, Mac2 still
renders (and shows red OFFLINE link).
Routes:
GET /api/fleet {macs:[{label,cpu,ram_pct,ollama_models[],
installed_count,ollama_proc,power_mode,
ok,url|error}], ts}
Proxies http://100.94.103.98:9930/api/status (Mac1)
+ http://localhost:9931/api/status (Mac2). 10s cache.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
public/index.html | 22 ++++++++++++++++++++++
src/server/index.ts | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/public/index.html b/public/index.html
index 2f4b9d6..aceafd0 100644
--- a/public/index.html
+++ b/public/index.html
@@ -124,6 +124,12 @@
<span><a href="http://127.0.0.1:9920/" target="_blank" rel="noopener" style="color:inherit;text-decoration:none;border-bottom:1px dotted var(--metal)">Ideas accepted</a></span><b id="b-ideas">—</b>
</div>
<div class="b-divider"></div>
+ <div class="b-fleet" id="b-fleet" style="font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--ink-mute);text-transform:uppercase;display:flex;gap:18px;align-items:center;flex-wrap:wrap">
+ <span style="color:var(--metal)">Fleet</span>
+ <span id="fleet-mac1">Mac1 ·</span>
+ <span id="fleet-mac2">Mac2 ·</span>
+ </div>
+ <div class="b-divider"></div>
<div class="b-tier">
<div class="t A"><b id="b-A">—</b><span>A · 80+</span></div>
<div class="t B"><b id="b-B">—</b><span>B · 60+</span></div>
@@ -428,6 +434,22 @@ async function loadBuildStatus() {
setNews('b-news-biz', c.news_biz);
setNews('b-news-7d', c.news_fresh_7d);
setNews('b-ideas', c.ideas_accepted);
+ // Fleet: pull Mac1/Mac2 state from /api/fleet (10s cache server-side)
+ try {
+ const fleet = await fetch('/api/fleet').then(r => r.json());
+ const fmtMac = (m, port) => {
+ if (!m || !m.ok) return `<a href="http://${port}" target="_blank" style="color:#c47b7b;border-bottom:1px dotted #c47b7b;text-decoration:none">${m?.label || port} · offline</a>`;
+ const model = m.ollama_models[0];
+ const modelStr = model ? `${model.name} ${model.pinned ? '⚓' : ''}` : 'idle';
+ const cpu = m.cpu.toFixed(0), ram = m.ram_pct.toFixed(0);
+ const dashUrl = port === '100.94.103.98:9930' ? 'http://100.94.103.98:9930' : 'http://localhost:9931';
+ return `<a href="${dashUrl}" target="_blank" style="color:inherit;text-decoration:none"><span style="color:var(--metal)">${m.label}</span> · <span style="color:var(--ink)">${escapeHtml ? escapeHtml(modelStr) : modelStr}</span> · cpu <b style="color:var(--metal-glow)">${cpu}%</b> · ram <b style="color:var(--metal-glow)">${ram}%</b></a>`;
+ };
+ const m1El = document.getElementById('fleet-mac1');
+ const m2El = document.getElementById('fleet-mac2');
+ if (m1El) m1El.innerHTML = fmtMac(fleet.macs[0], '100.94.103.98:9930');
+ if (m2El) m2El.innerHTML = fmtMac(fleet.macs[1], 'localhost:9931');
+ } catch(e) { /* fleet bridge unavailable */ }
set('b-A', c.tier_a);
set('b-B', c.tier_b);
set('b-C', c.tier_c);
diff --git a/src/server/index.ts b/src/server/index.ts
index c1cd119..2f64a2f 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -5179,6 +5179,40 @@ app.get('/api/ideas/stats', async (_req, res) => {
}
});
+// Fleet status — proxy both Mac dashboards so corridor can show "what
+// is Mac1/Mac2 doing right now" inline. Soft-fails per machine, so a
+// dead dashboard doesn't 500 the whole page.
+app.get('/api/fleet', async (_req, res) => {
+ const fetchOne = async (url: string, label: string) => {
+ try {
+ const r = await fetch(url, { signal: AbortSignal.timeout(2500) });
+ if (!r.ok) return { ok: false, label, status: r.status };
+ const j: any = await r.json();
+ return {
+ ok: true, label,
+ cpu: j.cpu?.total ?? 0,
+ ram_pct: j.memory?.used_pct ?? 0,
+ ollama_models: (j.ollama?.models || []).map((m: any) => ({
+ name: m.name, vram_gb: +(((m.size_vram_bytes || 0) / (1024 ** 3)).toFixed(2)),
+ pinned: m.expires_at ? (new Date(m.expires_at).getTime() - Date.now()) > (180 * 86400 * 1000) : false
+ })),
+ installed_count: j.ollama?.installed_count || 0,
+ ollama_proc: (j.ollama_procs || [])[0] || null,
+ power_mode: j.power_mode || 'auto',
+ url: url.replace('/api/status', '')
+ };
+ } catch (e: any) {
+ return { ok: false, label, error: String(e?.message || e) };
+ }
+ };
+ const [mac1, mac2] = await Promise.all([
+ fetchOne('http://100.94.103.98:9930/api/status', 'Mac Studio 1'),
+ fetchOne('http://localhost:9931/api/status', 'Mac Studio 2')
+ ]);
+ res.set('Cache-Control', 'public, max-age=10');
+ res.json({ macs: [mac1, mac2], ts: Date.now() });
+});
+
app.get('/api/ideas/recent', async (_req, res) => {
try {
const fs = await import('node:fs/promises');
← 4927f54 feat(news): "Hot only" toggle on /news.html filter bar
·
back to Ventura Corridor
·
feat(coverage): rejected-ideas drawer below the idea-loop fe 7d1fe85 →