Files
serverAppConfigs/docs/Infrastructure/Homepage Design Grilling.md
T
Frank cdae928f37 Homepage: settle design (grilling Q1-Q5), log open questions Q6-Q43, progress report
- 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.
2026-08-23 02:59:48 -07:00

9.3 KiB
Raw Blame History

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]