feat: dynamic logo from synced assets + SVG favicon

Logo handler now checks Hub-synced assets first, falling back to
embedded SVG. Added SVG favicon to layout and catchall templates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 09:34:38 +01:00
parent 0c687ae280
commit 077640d9bb
5 changed files with 23 additions and 1 deletions
+8
View File
@@ -1,5 +1,13 @@
## Changelog
### v0.29.2 — Dynamic Logo & Favicon (2026-02-25)
#### Changed
- **Logo served from synced assets** (`internal/web/server.go`) — `serveLogoHandler` now checks the Hub-synced assets directory for `felhom-logo.svg` first, falling back to the embedded SVG constant if not found. This allows logo updates via Hub without a controller rebuild.
#### Added
- **SVG favicon** (`templates/layout.html`, `templates/catchall.html`) — Added `<link rel="icon" type="image/svg+xml">` pointing to `/static/felhom-logo.svg` so browsers display the Felhom logo as a tab icon.
### v0.29.1 — Fix Git Lock File Stale After Interrupted Sync (2026-02-24)
#### Fixed
+3 -1
View File
@@ -4,7 +4,7 @@
A single, lightweight Go container that replaces Portainer + scattered systemd scripts with a unified, Hungarian-language web dashboard for managing Docker Compose stacks, backups, storage, monitoring, and notifications on customer hardware.
**Current version: v0.28.1**
**Current version: v0.29.2**
---
@@ -1023,6 +1023,8 @@ App assets (logos, screenshots) are managed centrally by the Hub and downloaded
The `Resolve(filename)` method checks the synced cache first, then falls back to the baked-in directory. This ensures assets are always available even before the first sync.
The Felhom logo (`/static/felhom-logo.svg`) also uses this two-tier resolution: the logo handler checks synced assets first, then falls back to the embedded SVG constant. This allows logo updates via Hub without a controller rebuild. The logo is also used as an SVG favicon.
#### Configuration
```yaml
+10
View File
@@ -431,6 +431,16 @@ func (s *Server) serveChartJSHandler(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) serveLogoHandler(w http.ResponseWriter, r *http.Request) {
// Try synced asset first (allows logo updates via Hub without rebuild)
if s.assetsSyncer != nil {
path := s.assetsSyncer.Resolve("felhom-logo.svg")
if _, err := os.Stat(path); err == nil {
w.Header().Set("Cache-Control", "public, max-age=86400")
http.ServeFile(w, r, path)
return
}
}
// Fallback to embedded logo
w.Header().Set("Content-Type", "image/svg+xml")
w.Header().Set("Cache-Control", "public, max-age=86400")
fmt.Fprint(w, FelhomLogoSVG)
@@ -5,6 +5,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{if .AppName}}{{.AppName}} — {{end}}felhom.eu</title>
<link rel="icon" type="image/svg+xml" href="{{.ControllerURL}}/static/felhom-logo.svg">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0d1117;color:#e6edf3;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center}
@@ -5,6 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Title}} — Felhom.eu</title>
<link rel="icon" type="image/svg+xml" href="/static/felhom-logo.svg">
<link rel="stylesheet" href="/static/style.css">
<meta name="csrf-token" content="{{.CSRFToken}}">
<script>