# ClankerSaddle web UI — structural layout critique This is an opinions document about **structure**, not looks: the theme, colours and typography stay as they are. "Structure" here means page hierarchy (what leads a page, what folds away), information order, navigation between pages, where forms live, and density. Every claim below was read out of the templates in `src/pages/` on the goal branch (after the SSE and HTML-escaping fixes landed), so the wireframes describe the app as it ships today. ## How the app is built (why the recommendations look the way they do) - Every page is a Statum template compiled by `statum-mkpstm`: `stm-text` / `stm-if` / `stm-for` / `stm-attribute` / `stm-markdown` bind server state, `stm-action` submits sealed actions, and the page refreshes in place. The shared chrome lives in `main.html`: a header nav (Dashboard, Projects, Tasks, Goals, Saddles, Rules, Users, then the user cluster), one `
`, a footer. - The whole app renders inside a **single 64rem column** (`body { max-width: 64rem }` in `app.css`). There are exactly two layout primitives beyond that: `.cards` (an auto-fill card grid) and `.grid-2` (the task page's 50/50 status/mandate grid, stacking below 40rem). No page uses a persistent two-column layout, a sticky sub-nav, or a sidebar. - `task_log.html` is the only page whose body is built by client JavaScript (`createElement`/`textContent`, filters, search, paging, SSE). Everything else is server-rendered bindings. - `details`/`summary` is the app's only progressive-disclosure device, and it is doing a lot of work it was not meant for (see the "expander fatigue" section). Two capabilities notes used throughout: - `stm-attribute` can set **any** attribute (`stm-attribute.href`, `.class`, `.value`, `.data-*` already appear), so a section can be collapsed by binding `hidden` or a `data-collapsed` class to state, without client JS. - Client JS is not exotic: `task_log.html`, `tasks.html` (`window.taskRowVisible` + `window.setTaskFilter`) and `goal_detail.html` (`window.goalSetFilter`) already run page scripts that cooperate with statum's render cycle. A "sticky sub-nav that highlights the section in view" is a `scroll` listener plus one class toggle — the pattern already exists on this codebase. ## The five structural themes 1. **Attention is buried under equal-weight sections.** The detail pages are one long scroll of cards that all look equally important. The one thing a human must do (answer a block, review a plan) sits in card 2 or 3 of 11, between the status card and the plan history. Nothing in the page's *shape* says "act here". 2. **Reference material competes with action.** Rules, capabilities, sessions, briefs, plan revision history — genuinely useful, read maybe once — render at the same weight and in the same column as the action surface, so a page visit for "approve the plan" scrolls past everything else. 3. **Expander fatigue.** Every create and edit surface hides behind a `
` expander: New task, New goal, New project, New rule, New user, New capability, Register saddle, Edit task, Link a project, SSH key, Git identity, Edit rule, answered blocks, plan revisions, progress history. Disclosure is the right instinct for *history*; it is the wrong instinct for *primary actions*, where it inverts affordance (the most important button on the page is the least visible control). 4. **No "where am I".** No breadcrumbs anywhere. "Back" is a manual anchor each page draws by hand ("← Goals", "All tasks", "All projects"), inconsistently placed (goal page: above the `h2`; task page: a context line under the `h2` carrying project + enqueue chain). Cross-links exist (task→project, task→goal, goal→project) but the reverse links (project→its goals, task→its sessions' logs) are partial, so navigation is a one-way tree. 5. **Density mismatch.** A five-word status line and a 400-word completion report both get a full-width card in the same column; the tasks table carries eight columns of which three are reference (goal, project, capabilities) that most visits do not need. --- ## Page-by-page ### 1. Home / dashboard (`home.html`) **What it's for.** The "is anything on fire / does anything need me" page: push bell, queue and saddle metrics, pinned needs-a-human blocks, active tasks with latest progress, saddle cards, recent activity. **Structural problem.** The page opens with a full-width card whose entire content is one button pair ("Enable notifications — be told when an agent asks a question…"). Then two metric cards (Queue, Saddles). Only *then* comes the section the page exists for: "Needs a human". On a fresh install the attention content is below the fold; on a busy day the pinned cards — the actionable items — are squeezed between metrics above and two more full sections below (Saddles, Activity), so comparing a block against the task it came from means scrolling past a saddle grid. **Recommendations.** - **A. Move "Needs a human" to the top** (S, low risk). Keep the bell but demote it: it is a settings action, not news. It can become a compact strip beside the metric cards, or move to the header's user cluster entirely (arguably where a notification preference belongs). - **B. Put the metrics in a right-hand rail next to the attention column** (M, low risk). One `.grid-2`-style row: left 2/3 pinned blocks + active tasks, right 1/3 Queue/Saddles metrics, the bell strip, and "Saddles" as a compact status list rather than cards. - **C. Fold Activity under a collapsed expander with a "new since your last visit" count** (S, low risk), or cap it at ~8 rows with "view all" — it is the page's only pure-read section. ``` BEFORE (linear) AFTER (attention-first + rail) +----------------------------+ +----------------------------+ | [Enable notifications ...] | | NEEDS A HUMAN (3) | +----------------------------+ | [block] [block] [block] | | [Queue] [Saddles] | | ACTIVE TASKS | +----------------------------+ | ...table... | | NEEDS A HUMAN (3) | +------------+---------------+ | [block] [block] [block] | | Queue | bell (compact)| +----------------------------+ | Saddles | saddle list | | ACTIVE TASKS | +------------+---------------+ | ...table... | | ACTIVITY (collapsed, 3 new)| +----------------------------+ +----------------------------+ | SADDLES (cards) | +----------------------------+ | ACTIVITY (full table) | +----------------------------+ ``` **statum notes.** A and C need nothing new. B needs one CSS grid row plus the existing card markup; `stm-if` already gates the pinned section on `dashboard.pinned.length`. ### 2. Tasks list (`tasks.html`) **What it's for.** The queue: find a task, judge the queue's shape, create a task. **Structural problems.** - The **create form** is the page's only primary action and it is a collapsed expander above the table. New users' first act is to hunt for the form. - **Eight columns** (`#`, Title, Status, Mode, Goal, Priority, Project, Capabilities), three of which (Goal, Project, Capabilities) are reference attributes. On the 64rem column this is dense, and Priority is usually "5" noise. - The three filters (Status, Project, Goal) are bare `