From cc635f2f73e5fac3f7999f27eb352d6c00c18386 Mon Sep 17 00:00:00 2001 From: Razvan Dimescu Date: Thu, 16 Apr 2026 06:15:48 +0300 Subject: [PATCH 1/2] feat(dashboard): show version in header, restructure footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #108. - Add `version` field to /stats (from CARGO_PKG_VERSION). - Show `v0.13.1` next to the Numa wordmark in the dashboard header. - Restructure the footer into two semantic rows: Row 1 (paths): Config · Data · Logs (platform-detected) Row 2 (runtime): Upstream · DNSSEC · SRTT · GitHub - Drop Mode from the footer (redundant with Upstream label). - Show only the matching-platform log path instead of both macOS and Linux unconditionally. --- site/dashboard.html | 19 ++++++++++++------- src/api.rs | 2 ++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/site/dashboard.html b/site/dashboard.html index 77018fc..de286ab 100644 --- a/site/dashboard.html +++ b/site/dashboard.html @@ -561,6 +561,7 @@ body {
+
DNS that governs itself
@@ -1136,16 +1137,20 @@ async function refresh() { document.getElementById('totalQueries').textContent = formatNumber(q.total); document.getElementById('uptime').textContent = formatUptime(stats.uptime_secs); document.getElementById('uptimeSub').textContent = formatUptimeSub(stats.uptime_secs); + document.getElementById('headerVersion').textContent = stats.version ? 'v' + stats.version : ''; document.getElementById('footerUpstream').textContent = stats.upstream || ''; document.getElementById('footerConfig').textContent = stats.config_path || ''; document.getElementById('footerData').textContent = stats.data_dir || ''; - const modeEl = document.getElementById('footerMode'); - modeEl.textContent = stats.mode || '—'; - modeEl.style.color = stats.mode === 'recursive' ? 'var(--emerald)' : 'var(--amber)'; document.getElementById('footerDnssec').textContent = stats.dnssec ? 'on' : 'off'; document.getElementById('footerDnssec').style.color = stats.dnssec ? 'var(--emerald)' : 'var(--text-dim)'; document.getElementById('footerSrtt').textContent = stats.srtt ? 'on' : 'off'; document.getElementById('footerSrtt').style.color = stats.srtt ? 'var(--emerald)' : 'var(--text-dim)'; + if (!document.getElementById('footerLogs').textContent) { + const isMac = stats.data_dir && stats.data_dir.includes('/usr/local/'); + document.getElementById('footerLogs').textContent = isMac + ? '/usr/local/var/log/numa.log' + : 'journalctl -u numa -f'; + } // LAN status indicator const lanEl = document.getElementById('lanToggle'); @@ -1504,14 +1509,14 @@ refresh(); setInterval(refresh, 2000); -
+
Config: · Data: - · Upstream: - · Mode: + · Logs: +
+ Upstream: · DNSSEC: · SRTT: - · Logs: macOS: /usr/local/var/log/numa.log · Linux: journalctl -u numa -f · GitHub
diff --git a/src/api.rs b/src/api.rs index 17c4614..f8b2702 100644 --- a/src/api.rs +++ b/src/api.rs @@ -160,6 +160,7 @@ struct QueryLogResponse { #[derive(Serialize)] struct StatsResponse { + version: &'static str, uptime_secs: u64, upstream: String, mode: &'static str, // "recursive" or "forward" — never "auto" at runtime @@ -539,6 +540,7 @@ async fn stats(State(ctx): State>) -> Json { }; Json(StatsResponse { + version: env!("CARGO_PKG_VERSION"), uptime_secs: snap.uptime_secs, upstream, mode: ctx.upstream_mode.as_str(), From 1c5e703330bab7ca1a822246f346f79677d52863 Mon Sep 17 00:00:00 2001 From: Razvan Dimescu Date: Thu, 16 Apr 2026 06:39:29 +0300 Subject: [PATCH 2/2] =?UTF-8?q?fix(dashboard):=20collapse=20header=20on=20?= =?UTF-8?q?mobile=20(=E2=89=A4700px)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hide tagline, version tag, and Phone Setup on narrow viewports so the header stays single-row: logo + status dot + blocking toggle. Reduces logo font-size from 1.8rem to 1.4rem on mobile. --- site/dashboard.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/dashboard.html b/site/dashboard.html index de286ab..85b6984 100644 --- a/site/dashboard.html +++ b/site/dashboard.html @@ -552,7 +552,11 @@ body { @media (max-width: 700px) { .stats-row { grid-template-columns: repeat(2, 1fr); } .dashboard { padding: 1rem; } - .header { padding: 1rem; } + .header { padding: 0.8rem 1rem; } + .logo { font-size: 1.4rem; } + .tagline { display: none; } + #headerVersion { display: none; } + #phoneSetup { display: none; } }