move back to htmx
Swap hand-rolled fetch+DOMParser+replaceContents for HTMX attributes on the
forms and sections, return OOB HTML fragments from /apply, /propose, and
/mark-all-read instead of JSON/redirects, and render toasts server-side. The
earlier custom client was the interview cheatsheet's "essentially a hand-rolled
subset of HTMX" — replacing it cuts ~200 lines of duplicated infra.
- HTMX 2.0.4 from unpkg, defer-loaded
- Per-endpoint: /apply and /mark-all-read return a toast OOB + OOB controls
(and OOB subscriptions for /apply), with HX-Trigger: refreshQueue to drive
#queue-root re-fetch. /propose returns only the ask-root OOB since proposal
generation is read-only. /queue includes an OOB #queue-count titlebar so the
count and body swap together — avoids the "updating…" ghost next to a
populated queue.
- render/toast.ts renders toasts as HTML with a data-toast-dismiss attr; a
MutationObserver in client.ts wires auto-dismiss when HTMX inserts them.
- HTMX error path: the outer server catch returns an OOB error toast for
HX-Request:true instead of a plain-text 500, so failures still surface.
- Kept custom JS where HTMX doesn't apply: @ typeahead + mention nav,
selected-actor chips, dialog open/close, guidance save (inline feedback).
- Fixed a subtle regression the custom JS had hidden: #queue-count now
updates with every /queue swap, not just after custom loadQueue() calls.
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>