--- type: reference description: "The decision log for the homepage design." tags: - infrastructure - homepage timestamp: 2026-08-28 --- # Homepage Design Grilling The decision log for the homepage design. All questions are settled (2026-08-23). This page records the final decisions and the places where the operator's answer changed the initial recommendation. ## Final decisions | # | Decision | Value | |---|----------|-------| | Q1 | How the page learns up/down | Server-side checker writes `status.json`; the page reads only that file. (Documented future intent: 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, second operator-only password. | | 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. | | Q6 | Tourist `/how/` page | **Defer** — it is extra. | | Q7 | `status.json` | One file; each service carries a `category` field; each page filters. | | Q8 | `services.json` | One file with a `category` field. | | Q9 | Checker language | python3. | | Q10 | Probe method | **Per service** — `tcp` or `http`, set per entry. | | Q11 | Probe timeout | **5 s** per service. | | Q12 | LLM loading | Three states; a listening port is Up (health 503 = Up). | | Q13 | Checker location | `scripts/homepage-status.py` + `.service` + `.timer`, tracked in git. | | Q14 | Reach backends | `probe` = full `host:port` (`127.0.0.1:PORT` or `192.168.0.235:PORT`). | | Q15 | WIP | static `"wip": true`; the checker skips the probe. | | Q16 | Staleness | `generated_at` in `status.json`; the page warns when it is older than 10 min. | | Q17 | Writes | atomic (write a temp file, then rename). | | Q18 | Admin password | `CADDY_ADMIN_HASH` in the host `.env` (git-ignored), operator-only. | | Q19 | Per-path basicauth | `@admin path /admin/*` with a second `basicauth` block. | | Q20 | Descriptions | hand-written one-liners in `services.json`. | | Q21 | Open link | the Caddy site URL; status-only backends set `showLink: false`. | | Q22 | Docs link | **a per-service `/docs/` page. Do NOT link the existing reference docs (they may contain secrets).** | | Q23 | Layout | **TUI-style cards/panels** (a grid of panels), not a flat list. | | Q24 | Summary line | yes — a placeholder for now; refine later. | | Q25 | Terminus | bundle the font (woff2) + a monospace fallback. | | Q26 | Palette | as proposed (green `#33ff66`, red `#ff5555`, amber `#ffcc33`, cyan `#33ccff`, bg `#050805`). | | Q27 | Styling | **toggleable: default = full theme; a toggle strips to bare unstyled HTML (motherfuckingwebsite.com style).** | | Q28 | Cursor | **do not alter the user's cursor.** | | Q29 | Docs content | how a regular user uses the service; **no maintenance details.** | | Q30 | Docs path | **`/docs//`** (not `/usage/`). | | Q31 | Docs auth | **the same auth as the homepage section** (user docs = shared password, admin docs = admin password). | | Q32 | Docs workstream | a separate effort; built as each service goes active. | | Q33 | Deploy | **git-driven; master always reflects the deployed state.** | | Q34 | `/srv/homepage/` | `deploy.sh` creates it and copies the assets. | | Q35 | Timer | enabled at boot. | | Q36 | Checker tests | **full TDD.** | | Q37 | Page/config tests | **full TDD.** | | Q38 | Security test | **full TDD.** | | Q39 | Backend move | a config edit (`probe` host:port). | | Q40 | LAN timeout | **5 s.** | | Q41 | Auto-refresh | **no** — the page reads `status.json` once on load. | | Q42 | Mobile | responsive. | | Q43 | Footer timestamp | **last master deployment datetime** (not last-check). | Styling (settled): terminal TUI, Terminus (monospace fallback), green-on-black, 1995 phosphor palette. Default = full theme; a toggle strips to bare unstyled HTML. Do not alter the user's cursor. ## Where the operator changed the recommendation These are the deltas from the initial recommendations. Everything else was accepted as recommended. - **Q10** — the probe method is **per service** (`tcp` or `http`), not TCP-only. - **Q11 / Q40** — the probe timeout is **5 s** (not 3 s). - **Q22** — the docs link points to a **per-service `/docs/` page**, never the existing reference docs (they may contain secrets). - **Q23** — the layout is **TUI-style cards/panels**, not a flat list. - **Q27** — styling is **toggleable**: the full theme by default, with a toggle to bare unstyled HTML. - **Q28** — **do not alter the user's cursor** (no fake blinking cursor). - **Q29** — the docs are **user-facing only**; no maintenance details. - **Q30** — the docs path is **`/docs/`** (not `/usage/`). - **Q31** — the docs use **the same auth as the homepage section**. - **Q33** — **git-driven; master always reflects the deployed state.** - **Q36–Q38** — **full TDD.** - **Q41** — **no client-side auto-refresh.** - **Q43** — the footer shows the **last master deployment datetime** (not last-check). ## Build status — complete (2026-08-23) The build is done, slice by slice, full TDD (each slice red → green, committed and pushed). 116 tests pass. The render logic is verified with a Node DOM shim. ```mermaid flowchart LR A[write the checker tests] --> B[write the checker] B --> C[write services.json] C --> D[write the pages + theme + toggle] D --> E[extend deploy.sh + Caddyfile] E --> F[tests green] F --> G[deploy to Dankclaw] G --> H[verify in browser] ``` Slices: 1 the checker core (tcp/wip/atomic/generated_at), 2 the http probe, 3 the real `services.json` + schema, 4 the pages + theme + toggle, 5 the Caddyfile auth split, 6 the git-driven deploy (both hashes, `deployed.js`, the timer). **Remaining to go live:** the operator adds `CADDY_ADMIN_HASH` (the operator-only password, `caddy hash-password`) to the target `.env`, then runs `./scripts/deploy.sh dankclaw`. Until then the admin hash stays a placeholder. The per-service docs pages (Q22/Q29/Q30/Q31) are a separate workstream, built as each service goes active.