diff --git a/src/webui/internal/auth/login.go b/src/webui/internal/auth/login.go
index 7257bedb..8274814a 100644
--- a/src/webui/internal/auth/login.go
+++ b/src/webui/internal/auth/login.go
@@ -74,9 +74,12 @@ func (h *LoginHandler) DoLogin(w http.ResponseWriter, r *http.Request) {
// Probe optional features once at login and bake into the session.
caps := handlers.DetectCapabilities(ctx, h.RC)
- // The web console (ttyd) is config-gated; fold it into the same feature
- // map so templates gate on .Capabilities.Has "console".
- caps.Features()["console"] = handlers.DetectConsole(ctx, h.RC)
+ // The external web-app shortcuts (console/ttyd, netbrowse) are
+ // config-gated; fold them into the same feature map so templates gate
+ // on .Capabilities.Has "console" / "netbrowse".
+ console, netbrowse := handlers.DetectWebShortcuts(ctx, h.RC)
+ caps.Features()["console"] = console
+ caps.Features()["netbrowse"] = netbrowse
// Trigger any post-login hooks (e.g. schema sync) with full credentials.
if h.OnLogin != nil {
diff --git a/src/webui/internal/handlers/capabilities.go b/src/webui/internal/handlers/capabilities.go
index 87485aac..21cd497c 100644
--- a/src/webui/internal/handlers/capabilities.go
+++ b/src/webui/internal/handlers/capabilities.go
@@ -70,26 +70,31 @@ type yangLibrary struct {
} `json:"ietf-yang-library:yang-library"`
}
-// webConsoleConfig mirrors the slice of infix-services we need for the
-// console gate.
-type webConsoleConfig struct {
+// webConfig mirrors the slice of infix-services we need to gate the
+// external web-app shortcuts (console, netbrowse).
+type webConfig struct {
Web struct {
Console struct {
Enabled bool `json:"enabled"`
} `json:"console"`
+ Netbrowse struct {
+ Enabled bool `json:"enabled"`
+ } `json:"netbrowse"`
} `json:"infix-services:web"`
}
-// DetectConsole reports whether the web console (ttyd on :7681) is enabled
-// in config, so the UI can show or hide the terminal entry. Fails closed:
-// a read error hides the entry rather than offering a dead link.
-func DetectConsole(ctx context.Context, rc restconf.Fetcher) bool {
- var cfg webConsoleConfig
+// DetectWebShortcuts reports whether the web console (ttyd on :7681) and
+// the mDNS network browser (netbrowse at network.local) are enabled in
+// config, so the UI can show or hide their shortcuts. One read covers
+// both. Fails closed: a read error hides both rather than offering a
+// dead link.
+func DetectWebShortcuts(ctx context.Context, rc restconf.Fetcher) (console, netbrowse bool) {
+ var cfg webConfig
if err := rc.Get(ctx, "/data/infix-services:web", &cfg); err != nil {
- log.Printf("web/console config: %v (console entry hidden)", err)
- return false
+ log.Printf("web config: %v (console/netbrowse shortcuts hidden)", err)
+ return false, false
}
- return cfg.Web.Console.Enabled
+ return cfg.Web.Console.Enabled, cfg.Web.Netbrowse.Enabled
}
func DetectCapabilities(ctx context.Context, rc restconf.Fetcher) *Capabilities {
diff --git a/src/webui/static/css/style.css b/src/webui/static/css/style.css
index 42a63109..d8cec957 100644
--- a/src/webui/static/css/style.css
+++ b/src/webui/static/css/style.css
@@ -2133,8 +2133,8 @@ details[open] > .cfg-multi-summary {
border-color: var(--fg-muted);
}
-/* Web console (terminal) shortcut in the topbar */
-.topbar-console {
+/* External web-app shortcuts (console, network browser) in the topbar */
+.topbar-link {
display: flex;
align-items: center;
justify-content: center;
@@ -2144,7 +2144,7 @@ details[open] > .cfg-multi-summary {
text-decoration: none;
transition: color 0.15s, background 0.15s;
}
-.topbar-console:hover {
+.topbar-link:hover {
color: var(--fg);
background: var(--border);
}
diff --git a/src/webui/static/img/icons/README.md b/src/webui/static/img/icons/README.md
index 7f137fd7..299e7d30 100644
--- a/src/webui/static/img/icons/README.md
+++ b/src/webui/static/img/icons/README.md
@@ -29,6 +29,7 @@ untouched.
| logs.svg | scroll-text |
| mdns.svg | radio |
| nacm.svg | users |
+| netbrowse.svg | radar |
| ntp.svg | clock |
| routes.svg | git-compare-arrows |
| routing.svg | git-compare-arrows |
diff --git a/src/webui/static/img/icons/netbrowse.svg b/src/webui/static/img/icons/netbrowse.svg
new file mode 100644
index 00000000..b06537e3
--- /dev/null
+++ b/src/webui/static/img/icons/netbrowse.svg
@@ -0,0 +1 @@
+
diff --git a/src/webui/templates/layouts/base.html b/src/webui/templates/layouts/base.html
index 8e53cb38..a3bfa4f4 100644
--- a/src/webui/templates/layouts/base.html
+++ b/src/webui/templates/layouts/base.html
@@ -24,10 +24,18 @@