Homepage: record all 38 settled decisions (grilling complete)
- Homepage Design Grilling.md: final decision table (Q1-Q43) + the deltas where the operator changed the recommendation (per-service probe method, 5s timeout, TUI panels, toggleable styling, no cursor alteration, no auto-refresh, /docs/ path, user-facing docs, git-driven deploy, full TDD, last-deploy footer). - Homepage.md: updated to the settled design (per-service probe, 5s, TUI panels, styling toggle, no auto-refresh, /docs/ workstream, git-driven deploy, TDD). - pi log.md: 2026-08-23 entry recording the settled design and build order. Build order is unblocked. No homepage code built yet.
This commit is contained in:
@@ -1,167 +1,85 @@
|
||||
# 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.
|
||||
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.
|
||||
|
||||
## Decided
|
||||
## Final decisions
|
||||
|
||||
| # | 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). |
|
||||
| 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/<svc>/`** (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 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`).
|
||||
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.
|
||||
|
||||
## Open questions
|
||||
## Where the operator changed the recommendation
|
||||
|
||||
Each question carries a recommendation. Answer them in the morning report.
|
||||
These are the deltas from the initial recommendations. Everything else was accepted as recommended.
|
||||
|
||||
### A. Architecture and structure
|
||||
- **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).
|
||||
|
||||
**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:
|
||||
## Build order (unblocked)
|
||||
|
||||
```mermaid
|
||||
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]
|
||||
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]
|
||||
```
|
||||
|
||||
The per-service docs pages (Q22/Q29/Q30/Q31) are a separate workstream, built as each service goes active.
|
||||
|
||||
@@ -14,7 +14,7 @@ Do not treat the missing page as an outage. The Caddy site block and the redirec
|
||||
|
||||
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.
|
||||
|
||||
The site has two pages. The root lists user-facing services only, with no host labels. An `/admin/` subpage lists the admin and infrastructure services behind a separate password for the operator. Gitea is a user service. Hermes is an admin service. A "how it is built" page for visitors is optional and undecided.
|
||||
The site has two pages. The root lists user-facing services only, with no host labels. An `/admin/` subpage lists the admin and infrastructure services behind a separate password for the operator. Gitea is a user service. Hermes is an admin service. A "how it is built" page for visitors is deferred (Q6).
|
||||
|
||||
The client-side probe design is blocked in this topology. The page origin is `https://dankclaw.franksdank.cloud`. The service URLs are `http://<name>.franksdank.cloud`. That is cross-origin, mixed content, and auth-gated (HTTP 401). All three fail a browser `fetch`.
|
||||
|
||||
@@ -22,14 +22,14 @@ Intended direction: move to client-side probing. Serve every service as a same-o
|
||||
|
||||
## Structure
|
||||
|
||||
The site has three pages. The root page lists the user services. The `/admin/` page lists the admin and infrastructure services. The `/how/` page (optional) shows the architecture to visitors.
|
||||
The site has two pages. The root page lists the user services. The `/admin/` page lists the admin and infrastructure services. The optional `/how/` page is deferred (Q6).
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph site["dankclaw.franksdank.cloud (Caddy)"]
|
||||
ROOT["/ user services<br/>(shared password)"]
|
||||
ADMIN["/admin/ admin services<br/>(operator password)"]
|
||||
HOW["/how/ how it is built<br/>(optional)"]
|
||||
HOW["/how/ how it is built<br/>(deferred)"]
|
||||
STATUS["/status.json"]
|
||||
end
|
||||
TIMER["systemd timer<br/>every 3 minutes"]
|
||||
@@ -62,14 +62,14 @@ stateDiagram-v2
|
||||
|
||||
## Checker
|
||||
|
||||
The checker runs on Dankclaw as a systemd timer. Every run probes each backend directly, then writes `status.json`. It probes the backend `host:port`, not the Caddy site. A Caddy `502` or `401` cannot tell up from down.
|
||||
The checker runs on Dankclaw as a systemd timer. Every run probes each backend directly, then writes `status.json`. It probes the backend `host:port`, not the Caddy site. A Caddy `502` or `401` cannot tell up from down. The probe method is per service (`tcp` or `http`). The timeout is 5 s. The page reads `status.json` once on load. It does not auto-refresh.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[timer fires] --> B[read service config]
|
||||
B --> C{for each service}
|
||||
C -->|wip| D[mark WIP]
|
||||
C -->|probe| E[TCP connect to host:port]
|
||||
C -->|probe| E[probe: tcp or http]
|
||||
E -->|connected| F[mark Up]
|
||||
E -->|refused / timeout| G[mark Down]
|
||||
D --> H[write status.json]
|
||||
@@ -91,15 +91,23 @@ flowchart TD
|
||||
shared/homepage/
|
||||
├── index.html # root page (user services)
|
||||
├── admin.html # admin + infrastructure services
|
||||
├── how.html # optional architecture page
|
||||
├── style.css # terminal TUI theme
|
||||
├── app.js # loads status.json, renders the badges
|
||||
├── how.html # deferred (Q6)
|
||||
├── style.css # full theme; a toggle strips to bare HTML
|
||||
├── app.js # loads status.json once, renders the panels
|
||||
├── services.json # service config (user + admin)
|
||||
└── fonts/ # Terminus (woff2) for @font-face
|
||||
```
|
||||
|
||||
`status.json` is generated at runtime in `/srv/homepage/`. It is not committed.
|
||||
|
||||
## Rendering
|
||||
|
||||
The page renders a **grid of TUI-style panels** — one panel per service. Each panel shows the state badge, the name, the description, and the `Open` and `Docs` links. A summary line at the top counts the states. The footer shows the last master deployment datetime (Q43).
|
||||
|
||||
The page reads `status.json` **once on load**. It does not auto-refresh (Q41).
|
||||
|
||||
Styling is **toggleable** (Q27). The default is the full terminal theme. A toggle strips the page to bare, unstyled HTML (motherfuckingwebsite.com style). The page does not alter the user's cursor (Q28).
|
||||
|
||||
## Auth
|
||||
|
||||
Caddy wraps the site with HTTP basic auth. The root page uses the shared password. The `/admin/` page uses a second, operator-only password. The hashes come from the host `.env` (git-ignored). Do not commit the hash or the password.
|
||||
@@ -126,8 +134,9 @@ dankclaw.franksdank.cloud {
|
||||
"category": "user",
|
||||
"description": "Privacy-respecting metasearch engine.",
|
||||
"url": "http://search.franksdank.cloud",
|
||||
"docs": "/usage/searxng/",
|
||||
"docs": "/docs/searxng/",
|
||||
"probe": "127.0.0.1:8081",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
}
|
||||
@@ -135,13 +144,24 @@ dankclaw.franksdank.cloud {
|
||||
|
||||
- `category` — `user` or `admin`. Selects the page.
|
||||
- `url` — the "Open" link (the Caddy site).
|
||||
- `docs` — the per-service usage page.
|
||||
- `docs` — the per-service docs page (`/docs/<svc>/`).
|
||||
- `probe` — the backend `host:port` the checker probes.
|
||||
- `method` — `tcp` or `http`. The probe type for this service (Q10).
|
||||
- `wip` — when true, the badge shows WIP and the checker skips the probe.
|
||||
- `showLink` — when false, the card shows status only (no "Open" link).
|
||||
- `showLink` — when false, the panel shows status only (no "Open" link).
|
||||
|
||||
## Deployment and testing
|
||||
|
||||
The deploy is **git-driven**. Master always reflects the currently deployed state (Q33). `deploy.sh` copies the assets to `/srv/homepage/`, installs the checker timer, renders the Caddyfile (both hashes), and reloads Caddy. It stamps the deployment datetime the footer shows (Q43).
|
||||
|
||||
The build is **full TDD** (Q36–Q38). Tests exist before the code: the checker (a fake up port, a down port, a WIP service, and the JSON schema), the pages and config (the `services.json` schema, `caddy validate`, the `status.json` reference), and the security check (two distinct basicauth hashes).
|
||||
|
||||
## Per-service docs (separate workstream)
|
||||
|
||||
Each service gets a docs page at `/docs/<svc>/` (Q30). The content is a **how-to for a regular user** — no maintenance details (Q29). The pages are password-protected by the same auth as the homepage section they belong to (Q31). They are built as each service goes active (Q32). The `docs` link on a service points to its page. The existing reference docs in `docs/` are not linked from the homepage. They may contain secrets (Q22).
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Homepage Design Grilling]] — the decision log and open questions
|
||||
- [[Homepage Design Grilling]] — the decision log
|
||||
- [[Caddy]] — the proxy that serves it
|
||||
- [[Dankclaw Stack]], [[Dankserver Stack]] — the services it lists
|
||||
|
||||
Reference in New Issue
Block a user