← back to Macstudio1 Dashboard
feat: self-healing version check — dashboard auto-reloads on new build
729b4e14d315cd0300d18b1cc06cb2749fe5bc5d · 2026-05-08 00:04:06 -0700 · SteveStudio2
Server hashes public/index.html on boot + on file change (fs.watch).
Front-end polls /api/version every 5s; when the hash changes from
its loaded version, shows a brass-colored "New build deployed —
reloading..." banner and force-reloads after 2s.
Removes the constant "browser cached the old page" friction. Now
when I deploy a feature, the dashboard self-refreshes within 5 seconds
and Steve sees the new sections immediately without manual reload.
API:
GET /api/version {version: <sha1[0:10]>, ts}
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M public/index.htmlM server.js
Diff
commit 729b4e14d315cd0300d18b1cc06cb2749fe5bc5d
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Fri May 8 00:04:06 2026 -0700
feat: self-healing version check — dashboard auto-reloads on new build
Server hashes public/index.html on boot + on file change (fs.watch).
Front-end polls /api/version every 5s; when the hash changes from
its loaded version, shows a brass-colored "New build deployed —
reloading..." banner and force-reloads after 2s.
Removes the constant "browser cached the old page" friction. Now
when I deploy a feature, the dashboard self-refreshes within 5 seconds
and Steve sees the new sections immediately without manual reload.
API:
GET /api/version {version: <sha1[0:10]>, ts}
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
public/index.html | 24 ++++++++++++++++++++++++
server.js | 15 +++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/public/index.html b/public/index.html
index 5bb3cf8..5e9c9b1 100644
--- a/public/index.html
+++ b/public/index.html
@@ -980,6 +980,30 @@ async function tickLog() {
}
tickLog();
setInterval(tickLog, 3000);
+
+// ─── Self-healing version watch — auto-reload if server has new HTML ────
+let LOADED_VERSION = null;
+async function checkVersion() {
+ try {
+ const r = await fetch('/api/version').then(r => r.json());
+ if (LOADED_VERSION === null) {
+ LOADED_VERSION = r.version;
+ console.log('[dashboard] loaded version', LOADED_VERSION);
+ return;
+ }
+ if (r.version && r.version !== LOADED_VERSION) {
+ console.log('[dashboard] new version', r.version, '— reloading in 2s');
+ // Brief flash so Steve sees a deploy happened
+ const banner = document.createElement('div');
+ banner.textContent = 'New build deployed · reloading…';
+ banner.style.cssText = 'position:fixed;top:0;left:0;right:0;z-index:9999;background:#d4b683;color:#0a0a0c;font-family:JetBrains Mono,monospace;font-weight:600;font-size:13px;letter-spacing:.18em;text-align:center;padding:14px;box-shadow:0 4px 12px rgba(0,0,0,0.6);text-transform:uppercase';
+ document.body.appendChild(banner);
+ setTimeout(() => { location.reload(true); }, 2000);
+ }
+ } catch (e) { /* network blip */ }
+}
+checkVersion();
+setInterval(checkVersion, 5000);
</script>
</body>
diff --git a/server.js b/server.js
index a268dfb..7cc2fe6 100644
--- a/server.js
+++ b/server.js
@@ -288,6 +288,21 @@ app.get('/api/ollama/log', async (req, res) => {
}
});
+// Server-side build version — hash of public/index.html. Polling clients
+// compare to their loaded copy and force-reload when it changes.
+const crypto = require('node:crypto');
+let _buildVersion = '';
+function computeBuildVersion() {
+ try {
+ const html = fs.readFileSync(path.join(__dirname, 'public', 'index.html'), 'utf8');
+ _buildVersion = crypto.createHash('sha1').update(html).digest('hex').slice(0, 10);
+ } catch { _buildVersion = 'unknown'; }
+ return _buildVersion;
+}
+computeBuildVersion();
+fs.watch(path.join(__dirname, 'public'), { recursive: true }, () => computeBuildVersion());
+app.get('/api/version', (_req, res) => res.json({ version: _buildVersion, ts: Date.now() }));
+
app.get('/api/health', (_req, res) => res.json({ ok: true, ts: Date.now() }));
app.listen(PORT, '0.0.0.0', () => {
← 29b1797 chore: build version stamp + scroll hint at top of dashboard
·
back to Macstudio1 Dashboard
·
feat: viewer counter on dashboard odometer — see if browser 19f97af →