From 22a7331100714fa6b6f67a1c3c0d60fc3f737eb0 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 8 Oct 2026 03:37:13 -0700 Subject: [PATCH] homepage: icon swaps, clickable tiles, down pulse, header nav, compaction callout - Icons: Copyparty -> improvised amber folder, Marreta -> crumbling wall (bricks + red crack), Calibre-Web -> book, OpenWebUI -> official logo.png from openwebui.com, Seerr -> official seerr.dev os_logo_filled.svg. - Tiles with an open link are clickable whole (.panel.clickable: hover lift + glow; inner link clicks pass through). - Any DOWN panel (app tile or model card) gets a red gradient wash and a slow pulsing glow (.panel.down, .mi-card:has(.badge.down)). - docs / admin / account-settings buttons moved from the footer to the header (nav.top-links); footer keeps the deployment stamp. - Zealot compaction advice promoted from the Use paragraph to a bordered glowing model.compaction callout (.mi-comp); component seam pinned to the new field. --- .../Infrastructure/Homepage.md | 13 ++++++++ shared/homepage/app.js | 9 +++++- shared/homepage/img/apps/mono-cp.svg | 2 +- shared/homepage/img/apps/mono-cw.svg | 2 +- shared/homepage/img/apps/mono-mr.svg | 2 +- shared/homepage/img/apps/openwebui.png | Bin 0 -> 11348 bytes shared/homepage/img/apps/seerr.svg | 16 ++++++++++ shared/homepage/index.html | 12 ++++---- shared/homepage/services.json | 9 +++--- shared/homepage/style.css | 28 ++++++++++++++++-- tests/homepage_config.bats | 3 +- 11 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 shared/homepage/img/apps/openwebui.png create mode 100644 shared/homepage/img/apps/seerr.svg diff --git a/serverAppConfigs-docs/Infrastructure/Homepage.md b/serverAppConfigs-docs/Infrastructure/Homepage.md index c58e8d6..b86d52d 100644 --- a/serverAppConfigs-docs/Infrastructure/Homepage.md +++ b/serverAppConfigs-docs/Infrastructure/Homepage.md @@ -115,6 +115,19 @@ at the model headings, and a note that a future switchover renames the ids themselves (OpenWebUI picker + raw API + models.yml all move together — not done yet). +**Icons v2, clickable tiles, header nav (2026-10-08, third wave):** five +icons replaced on request — Copyparty gets an improvised amber folder, +Marreta a crumbling wall (bricks + red crack), Calibre-Web a book, +OpenWebUI its official logo (`openwebui.com/logo.png`), Seerr the official +`seerr.dev/os_logo_filled.svg`. Tiles with an open link are now clickable +whole (`.panel.clickable`, hover lift + glow; clicks on inner links pass +through). Any panel whose live state is DOWN gets a red gradient wash + +slow pulsing glow (`.panel.down`, and `.mi-card:has(.badge.down)` for +model cards). docs/admin/account-settings moved from the footer to the +header (`nav.top-links`). The zealot compaction advice moved out of the +Use paragraph into a bordered glowing `model.compaction` callout +(`.mi-comp`), pinned by the component seam test. + ## Design decision — 2026-08-22 The live up/down check runs server-side. A checker on Dankclaw probes each backend and writes a same-origin `status.json`. The page fetches only that file and renders the badges. The browser never calls a backend directly. The checker runs as a systemd timer every 3 minutes. diff --git a/shared/homepage/app.js b/shared/homepage/app.js index 3f46793..eac9e18 100644 --- a/shared/homepage/app.js +++ b/shared/homepage/app.js @@ -90,7 +90,7 @@ function miCard(svc, state) { if (m.spec) parts.push('
' + esc(m.spec) + '
'); if (m.inputs && m.inputs.length) parts.push('
Inputs: ' + esc(m.inputs.join(' · ')) + '
'); if (m.use) parts.push('
Use: ' + esc(m.use) + '
'); - if (m.voice) parts.push(voiceBtn(m.voice.text, m.voice.sfx)); + if (m.compaction) parts.push('
⚡ ' + esc(m.compaction) + '
'); if (m.supervision) parts.push('
' + esc(m.supervision) + '
'); if (m.permission) parts.push('
⚠ ' + esc(m.permission) + '
'); if (m.warn) parts.push('
' + @@ -137,6 +137,12 @@ function renderPanel(svc, state) { '
' + '
' + descHTML(svc) + '
' + warn + ''; + if (svc.showLink && svc.url) { + panel.classList.add('clickable'); + panel.addEventListener('click', function (ev) { + if (!ev.target.closest('a')) window.location.href = svc.url; + }); + } return panel; } @@ -220,6 +226,7 @@ function main() { applyBare(); fillDeployed(); gateAdminLink(); + Promise.all([load('services.json'), load('status.json')]) .then(function (pair) { renderPanels(pair[0], pair[1]); }) .catch(function (e) { diff --git a/shared/homepage/img/apps/mono-cp.svg b/shared/homepage/img/apps/mono-cp.svg index c41ed65..fbc6fa4 100644 --- a/shared/homepage/img/apps/mono-cp.svg +++ b/shared/homepage/img/apps/mono-cp.svg @@ -1 +1 @@ -CP \ No newline at end of file + \ No newline at end of file diff --git a/shared/homepage/img/apps/mono-cw.svg b/shared/homepage/img/apps/mono-cw.svg index d160cd0..0143ad6 100644 --- a/shared/homepage/img/apps/mono-cw.svg +++ b/shared/homepage/img/apps/mono-cw.svg @@ -1 +1 @@ -CW \ No newline at end of file + \ No newline at end of file diff --git a/shared/homepage/img/apps/mono-mr.svg b/shared/homepage/img/apps/mono-mr.svg index 67eef21..5df9715 100644 --- a/shared/homepage/img/apps/mono-mr.svg +++ b/shared/homepage/img/apps/mono-mr.svg @@ -1 +1 @@ -MR \ No newline at end of file + \ No newline at end of file diff --git a/shared/homepage/img/apps/openwebui.png b/shared/homepage/img/apps/openwebui.png new file mode 100644 index 0000000000000000000000000000000000000000..135908d8cfb6f9055d13851aab238f43393f6c98 GIT binary patch literal 11348 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 literal 0 HcmV?d00001 diff --git a/shared/homepage/img/apps/seerr.svg b/shared/homepage/img/apps/seerr.svg new file mode 100644 index 0000000..e3b105e --- /dev/null +++ b/shared/homepage/img/apps/seerr.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/shared/homepage/index.html b/shared/homepage/index.html index 54e60a5..24cfefd 100644 --- a/shared/homepage/index.html +++ b/shared/homepage/index.html @@ -13,17 +13,17 @@
frank@home:~$ services - bare +
diff --git a/shared/homepage/services.json b/shared/homepage/services.json index 254c249..992a61e 100644 --- a/shared/homepage/services.json +++ b/shared/homepage/services.json @@ -24,7 +24,7 @@ "method": "http", "wip": false, "showLink": true, - "art": "/img/apps/mono-ow.svg" + "art": "/img/apps/openwebui.png" }, { "name": "Gitea", @@ -115,7 +115,7 @@ "method": "http", "wip": "down", "showLink": false, - "art": "/img/apps/mono-sr.svg" + "art": "/img/apps/seerr.svg" }, { "name": "Marreta", @@ -303,7 +303,7 @@ "text", "image" ], - "use": "Code editor autocomplete, agentic search, RAG, research subagents, translation, roleplay, and summarization. If your agent harness lets you set a compaction model, set this one: a compaction job on the bigger models blocks them for far longer.", + "use": "Code editor autocomplete, agentic search, RAG, research subagents, translation, roleplay, and summarization.", "voice": { "text": "I LONG FOR COMBAT!", "sfx": [ @@ -311,7 +311,8 @@ ] }, "supervision": "Requires tight human supervision.", - "warn": "Uncensored model: output can include adult content, content that describes harmful, hateful, or illegal acts, content concerning “sensitive offensive cybersecurity topics”, and other output that may carry severe legal risk. Take this warning seriously — don’t ruin this server for everybody." + "warn": "Uncensored model: output can include adult content, content that describes harmful, hateful, or illegal acts, content concerning “sensitive offensive cybersecurity topics”, and other output that may carry severe legal risk. Take this warning seriously — don’t ruin this server for everybody.", + "compaction": "If your agent harness lets you set a compaction model, set this one: a compaction job on the bigger models blocks them for far longer." }, "url": "", "docs": "/docs#models", diff --git a/shared/homepage/style.css b/shared/homepage/style.css index 3cff933..16ae435 100644 --- a/shared/homepage/style.css +++ b/shared/homepage/style.css @@ -71,6 +71,26 @@ body::before { } .panel { border: 1px solid var(--border); background: var(--panel); padding: 12px 14px; border-radius: 2px; } +.panel.clickable { cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s; } +.panel.clickable:hover { + border-color: var(--link); + box-shadow: 0 0 14px color-mix(in srgb, var(--link) 35%, transparent); + transform: translateY(-2px); +} +.panel.down { + background: linear-gradient(180deg, + color-mix(in srgb, var(--down) 12%, var(--panel)), var(--panel)); + animation: down-pulse 3.2s ease-in-out infinite; +} +@keyframes down-pulse { + 50% { border-color: color-mix(in srgb, var(--down) 70%, var(--border)); + box-shadow: 0 0 16px color-mix(in srgb, var(--down) 40%, transparent); } +} +.mi-card:has(.badge.down) { + background: linear-gradient(180deg, + color-mix(in srgb, var(--down) 12%, var(--panel)), var(--panel)); + animation: down-pulse 3.2s ease-in-out infinite; +} .panel-head { display: flex; align-items: center; gap: 8px; } .panel-head .name { flex: 1; } .app-art { @@ -108,6 +128,8 @@ body::before { justify-content: space-between; } .foot a { color: var(--link); text-decoration: none; } +.top-links { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } +.top .foot-btn { color: var(--link); text-decoration: none; } .foot-links { display: flex; gap: 10px; flex-wrap: wrap; } .foot-btn { border: 1px solid var(--link); @@ -235,9 +257,9 @@ html[data-bare="1"] .mi-card { border-color: #000; box-shadow: none; background: html[data-bare="1"] .mi-art { display: none; } html[data-bare="1"] .mi-name { color: #000; text-shadow: none; } html[data-bare="1"] .mi-voice { color: #000; text-decoration: underline; } -html[data-bare="1"] .mi-role, html[data-bare="1"] .mi-spec, html[data-bare="1"] .mi-use, +html[data-bare="1"] .mi-role, html[data-bare="1"] .mi-spec, html[data-bare="1"] .mi-use, html[data-bare="1"] .mi-comp, html[data-bare="1"] .mi-inputs, html[data-bare="1"] .mi-equiv, html[data-bare="1"] .mi-super, html[data-bare="1"] .mi-warn { color: #000; } html[data-bare="1"] .app-art { display: none; } -html[data-bare="1"] .svc-warn, html[data-bare="1"] .mi-perm { color: #000; border: none; text-shadow: none; padding: 0; } -html[data-bare="1"] .mi-perm { border: 1px solid #000; } +html[data-bare="1"] .svc-warn, html[data-bare="1"] .mi-perm, html[data-bare="1"] .mi-comp { color: #000; border: none; text-shadow: none; padding: 0; } +html[data-bare="1"] .mi-perm, html[data-bare="1"] .mi-comp { border: 1px solid #000; } diff --git a/tests/homepage_config.bats b/tests/homepage_config.bats index 9513fb7..ac8df88 100644 --- a/tests/homepage_config.bats +++ b/tests/homepage_config.bats @@ -94,7 +94,8 @@ for s in fleet: for f in m["sfx"] + m.get("voice", {}).get("sfx", []): assert os.path.isfile(os.path.join(root, "sfx", f)), f"{s['name']} voice {f} missing" zealot = next(s for s in fleet if s["name"] == "frank-zealot") -assert "compaction" in zealot["model"]["use"].lower(), "zealot must be recommended as compaction model" +assert "compaction" in zealot["model"].get("compaction", ""), "zealot must be recommended as compaction model" +assert zealot["model"].get("compaction", "") != "", "compaction advice must be its own visible field" assert "supervision" in zealot["model"]["supervision"].lower() for s in fleet: m = s["model"]