- Homepage.md: rewritten to the settled design (single site, user + /admin/ pages, server-side status.json via a 3-min systemd-timer checker, terminal TUI theme). Added mermaid diagrams: site structure, status states, checker flow. Recorded the classification (user vs admin; *arr excluded; LLM admin; backends status-only) and the documented future shift to client-side probing. - Homepage Design Grilling.md (new): the decision log — settled Q1-Q5 plus 38 open questions (Q6-Q43) across 10 categories, each with a recommendation. - docs/index.md: link the grilling page (satisfies the index-links-every-page test). - report/homepage-grilling-2026-08-22.html: self-contained terminal-TUI progress report (settled decisions, verified stack baseline, overnight processing, work threads, the open questions, and how to continue). Baseline recorded: Dankclaw fully up (10/10); the Dankserver media stack is down (only Calibre-Web + the LLM are up; no .env on the target) — a separate thread. No homepage code built yet; the design is pending the operator's answers to Q6-Q43.
9.3 KiB
Homepage Design Grilling
The decision log for the homepage design. It records what is settled and the open questions that remain. Answer the open questions in the morning report; the design is built only after they are settled.
Decided
| # | Decision | Value |
|---|---|---|
| Q1 | How the page learns up/down | Server-side checker writes status.json; the page reads only that file. (Eventual target: client-side probing.) |
| Q2 | How the checker runs | systemd timer, rewrites status.json every 3 minutes. |
| Q3 | Page model | Single site on Dankclaw. Root = user services (no host labels). /admin/ = admin services, separate password. Optional /how/ tourist page. |
| Q4 | (superseded by Q3 restructure) | — |
| Q5 | Service split | User: SearXNG, ComfyUI, OpenWebUI, Gitea, Calibre-Web, RomM, Copyparty, Plex, Jellyfin. Admin: Hermes, Grafana, Prometheus, Loki, Caddy, dnsmasq, Gluetun, LLM fleet, low-level backends (status-only). The *arr stack is excluded (separate effort, not started). |
Styling is settled in principle: terminal TUI, Terminus (monospace fallback), green-on-black, 1995 phosphor palette (green #33ff66, red #ff5555, amber #ffcc33, cyan #33ccff, bg #050805).
Open questions
Each question carries a recommendation. Answer them in the morning report.
A. Architecture and structure
Q6 — The optional /how/ "tourist" page: build now or defer?
Recommendation: defer to a later effort. When built, make it public (no auth) so a visitor can see the architecture. It can render the mermaid diagrams from this repo.
Q7 — One status.json or two (user-status.json + admin-status.json)?
Recommendation: one status.json. Each service carries a category field. Each page filters client-side. One file, one checker output, one source of truth.
Q8 — One services.json or split by page?
Recommendation: one services.json with all services and a category field. The checker reads one file. Simpler to maintain.
B. The checker
Q9 — What language for the checker script?
Recommendation: python3 (available on Dankclaw, no dependencies, emits valid JSON cleanly). A bash + nc variant works too, but JSON by hand is error-prone.
Q10 — Probe method: TCP connect or HTTP GET?
Recommendation: TCP connect to host:port. Uniform, works for non-HTTP backends, and "port listening = up" matches the verified ground truth.
Q11 — Probe timeout per service? Recommendation: 3 seconds. A dead port refuses fast; a black-holed one times out at 3 s. With ~25 services the worst-case run is well under the 3-minute interval.
Q12 — LLM "loading" state (health returns 503 during model load)?
Recommendation: keep three states. A listening port shows Up. Optionally probe /health and treat 503 as Up (the process is alive). A dedicated "loading" state is a later refinement.
Q13 — Where does the checker live in the repo?
Recommendation: scripts/homepage-status.py plus scripts/homepage-status.service and scripts/homepage-status.timer, all tracked in git like the other units.
Q14 — How does the checker reach the Dankserver backends?
Recommendation: the probe field carries a full host:port. Dankclaw services use 127.0.0.1:PORT. Dankserver services use 192.168.0.235:PORT. The checker (on Dankclaw) connects to each over the LAN. Verified reachable.
C. The status model
Q15 — How is a service marked WIP?
Recommendation: a static "wip": true field. The checker skips the probe and the page shows WIP. Drop the old self-referential "Homepage" entry (a page does not list itself).
Q16 — Staleness: what if the timer fails and status.json is old?
Recommendation: write a generated_at timestamp into status.json. The page shows a "status may be stale" warning when it is older than 10 minutes.
Q17 — Atomic writes?
Recommendation: the checker writes to a temp file, then renames over status.json. A crash never leaves a half-written file. The last good status survives.
D. Auth
Q18 — The admin password: a second .env variable?
Recommendation: yes. CADDY_ADMIN_HASH in the host .env (git-ignored), rendered into the Caddyfile at deploy, operator-only. The root page keeps CADDY_BASICAUTH_HASH.
Q19 — Per-path basicauth in Caddy v2?
Recommendation: a @admin path /admin/* matcher with a second basicauth @admin block. Confirm the exact syntax against the Caddy docs during implementation.
E. The pages and content
Q20 — Where do the one-line descriptions come from?
Recommendation: hand-written one-liners in services.json, drafted from the existing reference docs.
Q21 — The "Open" link target: the Caddy site or the direct backend?
Recommendation: the Caddy site URL (what a user actually opens). Status-only backends set showLink: false (no Open link).
Q22 — The "docs" link: usage page or the existing reference doc?
Recommendation: link to the existing reference doc (docs/.../X.md) as a placeholder. Swap to the per-service usage page when that workstream is built.
Q23 — Page layout: cards or a terminal-style list?
Recommendation: a terminal-style list (one service per line, like systemctl list-units). Columns: STATUS | NAME | description | (open) (docs). Fits the TUI aesthetic better than cards.
Q24 — A summary line at the top?
Recommendation: yes. One line, e.g. UP 9 DOWN 2 WIP 1, per page.
F. Styling
Q25 — Terminus: bundle the font or use a fallback?
Recommendation: bundle Terminus (woff2) via @font-face, with a monospace fallback stack. Confirm the license (Terminus is freely distributable) and drop the files in fonts/.
Q26 — Confirm the palette?
Recommendation: as proposed (green #33ff66, red #ff5555, amber #ffcc33, cyan #33ccff, bg #050805). Tune for contrast and readability.
Q27 — CRT effects (scanlines + glow)?
Recommendation: subtle scanlines + a soft green text-shadow. Make it toggleable (a ?crt=0 param) for those who find it much.
Q28 — Blinking cursor / animation?
Recommendation: a subtle CSS-only blinking block cursor on the header. Respect prefers-reduced-motion.
G. The usage-docs workstream
Q29 — Scope of the per-service usage pages?
Recommendation: concise how-to guides (what it is, how to open it, the common tasks). Distinct from the deep reference docs in docs/.
Q30 — Where do the usage pages live?
Recommendation: served from the homepage site, same origin, at /usage/<svc>/. Source in the repo under shared/homepage/usage/<svc>/. Same origin keeps the "docs" link working.
Q31 — Are the usage pages password-protected? Recommendation: yes. User usage pages behind the shared password, admin usage pages behind the operator password. Consistent with the pages they extend.
Q32 — Is the usage-docs workstream a separate effort? Recommendation: yes, after the core homepage is live. For now the "docs" link points to the existing reference doc (Q22).
H. Deployment and operations
Q33 — How is the homepage deployed?
Recommendation: extend deploy.sh (Dankclaw path): copy shared/homepage/ to /srv/homepage/, install the timer + service, render the Caddyfile (both hashes), reload Caddy.
Q34 — Who creates /srv/homepage/?
Recommendation: deploy.sh creates it and copies the assets. The checker writes status.json there at runtime.
Q35 — Is the timer enabled at boot? Recommendation: yes. A systemd timer + service, enabled, so it survives reboots and runs every 3 minutes.
I. Testing
Q36 — Tests for the checker?
Recommendation: yes. A bats test runs the checker against a fake up port, a fake down port, and a WIP service, then validates the status.json schema. TDD, per repo rules.
Q37 — Tests for the pages and config?
Recommendation: yes. Validate the services.json schema (required fields, valid categories), run caddy validate on the Caddyfile, and check the pages reference status.json.
Q38 — A security test for the two passwords?
Recommendation: yes. Assert the Caddyfile carries two distinct basicauth hashes (root vs /admin/).
J. Edge cases and robustness
*Q39 — A backend moves hosts (e.g. the arr stack to a new box)?
Recommendation: no code change. The probe field is a full host:port. A move is a config edit.
Q40 — A slow LAN hop to a Dankserver backend? Recommendation: the 3 s timeout handles it. A slow-but-alive backend connects (Up); a dead one times out (Down).
Q41 — Client-side auto-refresh?
Recommendation: the page polls status.json every 60 s (the file updates every 3 min; 60 s is responsive without hammering).
Q42 — Mobile responsiveness? Recommendation: yes. Stack the columns and shrink the font on narrow screens.
Q43 — A "last checked" timestamp on the page?
Recommendation: yes. The footer shows last checked HH:MM:SS from generated_at.
How to continue
Answer the open questions (Q6–Q43) in the morning report. Group the answers by category. Once settled, the build order is:
flowchart LR
A[settle Q6-Q43] --> B[write services.json + checker]
B --> C[write the pages + theme]
C --> D[extend deploy.sh + Caddyfile]
D --> E[tests green]
E --> F[deploy to Dankclaw]
F --> G[verify in browser]