Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MD4VWGq6mGcd8Bg67qyx9k
5.9 KiB
Shared brief — UI polish pass (2026-09-04)
The operator asked for a design/bug-fix pass over the web dashboard v2 (Tailwind
redesign, merged to main at e719e03+). The work is split into three tasks
(01-toc.md, 02-rating.md, 03-shell.md) that run in parallel in separate git
worktrees. Read docs/plans/briefs/web-dashboard-v2/00-shared.md for the design
language (quiet morning paper: warm paper, near-black ink, one red accent,
hairline rules, real typographic hierarchy; reader pages serif, dashboard sans)
and the Tailwind v4 conventions. This brief overrides it where they disagree.
Ground rules
- Work only in the worktree named in your brief. Never touch the main checkout
at
/home/thallada/workspace/the-daily-epub. Do notgit commit(the sandbox cannot write.git/worktrees); leave the work in the tree and the orchestrator commits. If you can commit, one commit on the worktree branch is fine. - Styling lives in
src/web/tailwind.css(Tailwind v4,@applyin@layer components, semantic colour tokenspaper/paper-2/ink/ink-2/muted/rule/ rule-strong/accent/loved/good/down/warn) and in Tailwind utility classes in the askama templates undersrc/web/templates/. Rebuild the committed CSS after every change withnpm run css(writessrc/web/static/app.css; the binary embeds it withinclude_str!, so rebuild Rust after the CSS).npm run css:checkmust print no diff at the end. - CSP is
default-src 'self'; style-src 'self'; script-src 'self': no inline<style>/<script>, nostyle=""attributes, no CDNs. Setting CSS custom properties orelement.style.*fromapp.js(CSSOM) is allowed by CSP but prefer class/attribute toggles styled fromtailwind.css. - JS is plain
src/web/static/app.js(runs once at the end of<body>) and the tiny pre-paintsrc/web/static/theme.js. Keep every hook app.js relies on:form.rating,button[data-label],.active+aria-pressedon rating buttons,button.clear,form[data-confirm],details[id],table[data-filter],.table-filter,button[data-reset]/data-default,[data-refresh],[data-toc-panel],[data-toc-toggle],[data-toc-progress],[data-toc-scroll],[data-theme-toggle]. Keepid/name/action/aria-*attributes used by handlers or tests. Router tests assert on text and some class names; if a test breaks only because a cosmetic class changed, update the test. - Don't change routes, auth, migrations or
web::security_headers. - Prefer CSS transitions (interruptible) over keyframes; name exact transition
properties (never
transition: all); respect the existingprefers-reduced-motionrule. Touch targets ≥ 44 px on phones (extend with a pseudo-element if the visible control is smaller); ≥ 40 px in the dense dashboard. Tabular numerals for changing numbers. Hairline rules, not boxes, for structure. No decorative motion on frequent interactions. - Keep
cargo fmt,cargo clippy --all-targets -- -D warningsand the tests green. Iterate with narrow runs (cargo test --lib web::), onecargo testat the end. Sandbox note: inside the Codex sandboxbind()on 127.0.0.1 is forbidden, so these pre-existing tests fail there and must be ignored:curate::llm::tests::anthropic_*(4),extract::tests::relative_urls_resolve_against_the_url_we_landed_on,server::tests::*(5) andtests/m7_server.rs. Do not "fix" them. - This host has 4 cores / 7 GB and other agents build Rust at the same time; be
patient with
cargoand don't run several builds concurrently yourself. - Don't gold-plate and don't widen scope beyond your brief's numbered items plus the polish items it lists. Where the brief and the code disagree, follow the code and note the deviation.
- Finish by writing
docs/plans/briefs/ui-pass/handoff-<task>.md: what changed (file by file, briefly), design decisions, deviations, what you verified and how (commands, screenshots), anything left open.
Previewing
A seeded dev database exists in the main checkout at
/home/thallada/workspace/the-daily-epub/dev (two issues: No. 18 on 2026-09-01,
legacy; No. 19 on 2026-09-02, full snapshot; accounts admin/adminpassword123
and reader/readerpassword123). Copy it if you need your own:
cp -r /home/thallada/workspace/the-daily-epub/dev ./dev (git-ignored). Run your
worktree's server on your own port (given in your brief; 3499 is production,
3599 is the orchestrator's):
DAILY_EPUB_SERVER__HMAC_SECRET=$(head -c 48 /dev/urandom | base64) \
DAILY_EPUB_SERVER__BIND=127.0.0.1:<port> \
cargo run -- --config ./dev/config.toml serve
(the listen address is server.bind in ./dev/config.toml, overridable by the
env var above; your worktree's dev/config.toml is already set to your port. If
the sandbox forbids binding, rely on router tests + cargo test and say so in
the handoff).
Screenshots: node shoot.mjs <outdir> [--user admin|reader|none] [--theme light|dark] [--mobile] [--full] /path …
with BASE=http://127.0.0.1:<port>, from
/tmp/claude-1000/-home-thallada-workspace-the-daily-epub/553c7d77-d8f4-44f8-a379-73cedea23814/scratchpad/shoot/
(Playwright with a headless Chromium already installed under ~/.cache/ms-playwright).
If that directory is unreadable, the bare browser at
~/.cache/ms-playwright/chromium_headless_shell-1208/chrome-headless-shell-linux64/chrome-headless-shell --headless --no-sandbox --screenshot=out.png --window-size=1280,1400 URL
works for anonymous pages. Look at your screenshots (read the PNGs) before
calling a design change done, in light and dark, desktop and 390 px phone.
Useful dev URLs: / (latest issue, No. 19), /issues/2026-09-01 (archived
issue), /issues/2026-09-02/articles/<id> (chapter; pick ids from the TOC),
/issues/2026-09-02/world, /issues/2026-09-02/behind, /dashboard,
/dashboard/runs, /dashboard/runs/<id>, /dashboard/ratings,
/dashboard/settings, /dashboard/articles.