docs/specs/2026-09-11-web-ux-sweep-design.md

ba0a7d33f3a65ce53aafb074fda1682cf1cecfdf
gitbay/docs/specs/2026-09-11-web-ux-sweep-design.md rendered · source · history · blame · raw

79 lines · 4160 bytes

 1# Web UI/UX sweep
 2
 3Closes #182. The findings posted on that issue after walking every route in
 4`internal/httpd/routes.go` on gitbay.org at v1.20.1, anonymous and logged
 5in, and the rules chosen to fix them.
 6
 7## Rules
 8
 9- **Confirmation.** A control that destroys data nothing else holds asks
10  the person to type the object's name into a text field beside the
11  button; the handler refuses with a flash line when the text differs.
12  No JavaScript: the instance CSP is `script-src 'none'`. Covered: release
13  delete (the tag), snippet delete (the id), snippet file remove (the file
14  name), team delete (the team name), label remove (the label), SSH key
15  remove (the 8 characters after `SHA256:` in the fingerprint; a label
16  can be empty), email remove (the address), PGP key remove (the first
17  8 characters of the fingerprint). Reversible state keeps a
18  plain button: close/reopen, merge, protect/unprotect, attach/detach,
19  resolve, cancel, make primary, org member remove.
20- **Refusal wording.** Control-command messages a web form can trigger
21  must not name a flag or a CLI command. The message is rewritten at the
22  source, in `internal/control`, since the CLI reads the same text; no
23  rewrite layer in the web.
24- **Login return-to.** `requireUser` stores the requested local path in a
25  short-lived cookie; the login page says where the person is going; the
26  emailed-link and `web login` paths both redirect there once and clear it.
27  Only a path starting with a single `/` is honoured.
28- **Dates.** One absolute format on every page: `2006-01-02 15:04 UTC`
29  through the existing `when` helper. Tree and blob listings keep their
30  relative time with the absolute one in a `title` attribute.
31- **Tags.** Version-aware order on the refs page, newest first; a tag that
32  does not parse as a version sorts after the ones that do, by name.
33- **Editor.** When the repository requires signed commits, or the ref
34  refuses direct pushes, the edit page explains that and shows no form.
35  A branch that does not exist is a 404; a path that does not exist on
36  a real branch is a new-file form that says so, since `commit-file`
37  creates it.
38- **Repository settings.** Every Save names its field.
39- **Empty states.** Sidebars use "none yet" for things and "nobody yet"
40  for people; lists keep their sentence and, where a command creates the
41  thing, name it.
42
43## Findings and their fixes
44
451. Destructive controls without confirmation: the rule above, applied to
46   `account.html`, `settings.html` (no change: unprotect and detach are
47   reversible), `owner.html` (team delete only), `labels.html`,
48   `releases.html`, `snippet.html`.
492. Refusals verbatim: audit and rewrite.
503. `account.html` says `gitbay auth token mint`; the command is
51   `auth token create`.
524. Login return-to.
535. Four date formats.
546. Refs page sorts tags as strings.
557. Editor offered where it cannot succeed.
568. Twelve unlabelled Save buttons on repository settings.
579. Labels page: colour column shown when no label has a colour; the
58   column and the per-row colour form appear only when a label has a
59   colour or the viewer can write.
6010. Empty-state wording.
6111. Issue close-event line reads "closed by commit X by Y"; becomes
62    "closed by Y in commit X" with the time inline.
6312. Issue rows repeat the state chip under a single-state filter; the
64    milestone reads like a label. The chip appears only under "all"; the
65    milestone renders as "in <milestone>".
6613. Merged MR page: "at" becomes "merged at"; a source branch that no
67    longer exists is marked "branch deleted".
6814. Global search shows a count and the query. No context line.
6915. Repository home shows both clone URLs, HTTPS and SSH.
7016. Landing page: "mint a browser session" becomes "log in from your
71    terminal". The account page's markup picker already sits beside its
72    label; that finding was wrong and nothing changes.
7317. Left alone: the anonymous "1 bookmark" stat, since the count is public
74    by design (the bookmarks page says so).
75
76## Out of scope
77
78A context line on global search results (a search backend change), the
79POST-only routes, `/settings/export`, archives, badges and Atom feeds.