diff --git a/.env.example b/.env.example index 6b9c726..f7058cc 100644 --- a/.env.example +++ b/.env.example @@ -55,13 +55,17 @@ DISCORD_CLIENT_SECRET= # The guild whose membership gates sign-in (Developer Mode -> right-click the # server -> Copy Server ID). DISCORD_GUILD_ID= +# Optional: human-readable name for that guild, shown on the login screen so a +# stranger knows which community owns this library and who to ask for an +# invite. When unset the page falls back to a generic "private community" +# label. +# DISCORD_GUILD_NAME= # Exact callback URL, e.g. https://bookmark.example.com/auth/discord/callback. # Discord matches it verbatim, so it must equal the registered redirect. DISCORD_REDIRECT_URI= # Optional: a role snowflake members must hold on top of guild membership. # Empty (the default) means membership alone suffices. # DISCORD_REQUIRED_ROLE= - # Subdomain Traefik routes to the browser UI (required by the prod override). # Left commented on purpose: an example value here would be a silent # wrong-hostname fallback, and Traefik would publish the UI router on a domain diff --git a/.impeccable/critique/2026-08-27T07-53-05Z__backend-internal-web-templates-admin-html.md b/.impeccable/critique/2026-08-27T07-53-05Z__backend-internal-web-templates-admin-html.md new file mode 100644 index 0000000..4dc5b40 --- /dev/null +++ b/.impeccable/critique/2026-08-27T07-53-05Z__backend-internal-web-templates-admin-html.md @@ -0,0 +1,113 @@ +--- +target: backend/internal/web (admin surface) +total_score: 22 +max_score: 40 +na_heuristics: +p0_count: 1 +p1_count: 2 +timestamp: 2026-08-27T07-53-05Z +slug: backend-internal-web-templates-admin-html +--- +Method: dual-agent (A: AssessDesign · B: AssessEvidence) + +## Design Health Score + +| # | Heuristic | Score | Key Issue | +|---|-----------|-------|-----------| +| 1 | Visibility of System Status | 2 | Domain status is excellent; *interaction* status is absent — no `hx-indicator`/`hx-disabled-elt` in any admin template (only `card.html:52,71,85,108,119` has them). | +| 2 | Match System / Real World | 3 | `Due`/`Checked`/`Gap` (`lanes.html:24`) are unlabeled integers and a raw Go duration (`admin_lanes.go:229-231`); `Never chk` (`overview.html:13`). | +| 3 | User Control and Freedom | 2 | Only Finish has Cancel + reversal (`series-detail.html:51-57`). Clear marks, Revoke, both Removes and both `Set` writes are one-way, and the old chapter survives only as a `placeholder` (`series-detail.html:19`). | +| 4 | Consistency and Standards | 2 | "Needs attention" is `--patina` on the Series list (`admin.css:285-287`) and `--danger` on Lanes/Sites (`admin.css:189-191`, `:409-413`); sibling controls are `` vs ` - @@ -88,8 +95,11 @@ label names the field and the latest sits after it as context. */}}
- {{/* max is a fat-finger guard, not a real ceiling — no series is near it. */}} -
diff --git a/backend/internal/web/templates/chrome.html b/backend/internal/web/templates/chrome.html index 5580bd7..9bd0683 100644 --- a/backend/internal/web/templates/chrome.html +++ b/backend/internal/web/templates/chrome.html @@ -14,8 +14,9 @@ - {{if .Cover}} - {{else}}{{end}} + {{/* Monogram always present under the image; see card.html. */}} + {{if .Cover}}{{end}} + {{if .HasNewChapter}} {{else if .Favorite}}{{end}} @@ -34,11 +35,11 @@
Read Fav - Chapter + Chapter {{if eq .Tab "archived"}} - Restore + Restore {{else}} - Archive + Archive {{end}} Delete
diff --git a/backend/internal/web/templates/lanes.html b/backend/internal/web/templates/lanes.html index 0bf79ac..91eafd3 100644 --- a/backend/internal/web/templates/lanes.html +++ b/backend/internal/web/templates/lanes.html @@ -10,7 +10,7 @@ this template only prints them. */}} {{define "lanes"}}
+ hx-get="/ui/admin/lanes" hx-trigger="every 30s" hx-swap="outerHTML" hx-sync="this:replace">

Poll Lanes

@@ -18,20 +18,23 @@ {{else}}Browser: {{if not .BrowserConfigured}}not configured{{else if .BrowserReachable}}reachable{{else}}unreachable{{end}}{{end}}

+

Healthy idle (paused, browser asleep, nothing eligible) needs no action — attention needs the owner.

{{if .Rows}}
SiteDueCheckedGap - Last passOutcomes · state + Last passOutcomes · status
{{range .Rows}}
{{.Site}} - {{.Due}} - {{.Checked}} - {{.Gap}} + {{/* data-label is the column word for the phone layout, which drops the + thead: three bare numbers in a row say nothing. */}} + {{.Due}} + {{.Checked}} + {{.Gap}} ran {{.Ran}} - {{if .HasChips}}{{range $i, $c := .Chips}}{{if $i}} · {{end}}{{$c.Name}} {{$c.Count}}{{end}}{{else}}none observed{{end}}{{if .StatePhrase}} · {{.StatePhrase}}{{end}} + {{if .HasChips}}{{range $i, $c := .Chips}}{{if $i}} · {{end}}{{$c.Name}} {{$c.Count}}{{end}}{{else}}none observed{{end}}{{if .StatePhrase}} · {{.StatePhrase}}{{end}} {{/* The pause control lives in the one slot the design leaves for it: a running Lane offers the three durations and Pause; a paused Lane offers Resume in the same place. Pause is not destruction — it @@ -39,11 +42,11 @@ confirm row or the danger accent. The form wraps the select so the offered duration travels with the press. */}} {{if .Paused}} -
+
{{else}} -
+ @@ -57,4 +60,4 @@

No data yet — no Lane has recorded a pass.

{{end}}
-{{end}} \ No newline at end of file +{{end}} diff --git a/backend/internal/web/templates/list.html b/backend/internal/web/templates/list.html index b0a9227..5db4b30 100644 --- a/backend/internal/web/templates/list.html +++ b/backend/internal/web/templates/list.html @@ -4,7 +4,7 @@ {{/* The client filter only hides cards, so without this the list area goes blank on a query that matches nothing. filter.js fills in the query and unhides it; it lives inside #list so a tab swap re-creates it. */}} -