Files
pad/web
xarmian 817bb0a5ce fix(web): widen the name bound off my own over-correction; assert bdi at every binding (TASK-2759)
Codex round 11.

P2 — the width bound was an over-correction, and it landed on people. The
activity page marks any actor_name `named`, so the 16ch rule I added for
hostile AGENT names was clipping ordinary human ones; the episode feed's 20ch
did the same. One value now, 24ch, which fits an ordinary full name
("Alexandra Whitfield" is 19) while still bounding the pathological case.
The number is written down as a judgement, not dressed up as a measurement,
next to what it does NOT cover: `title` is unreachable by touch, so a
clipped name is effectively unreadable on a phone, and a real disclosure
affordance rather than a wider bound is the actual fix.

P2 — only the audit cell asserted the <bdi> element; the other four bindings
checked text and classes, so swapping bdi back to span passed all of them.
Each now asserts the tag with a bidi-carrying name.

P2 on the casing tests, declined with the reason already in the code: they
assert the `named` class and not the CSS rule, because Svelte component
styles are not injected under this vitest setup (0 style elements, so
getComputedStyle resolves nothing). Covering the rule itself needs an e2e
with a real browser. The boundary is stated in the test comment rather than
implied away — a source-text assertion about the stylesheet would be an
instrument with an adversary, not coverage.

Claude-Session: https://claude.ai/code/session_01Cpr3teiHHsgcTmg2xhHA86
2026-08-24 17:43:52 +00:00
..
2026-03-26 01:52:36 +00:00
2026-03-26 01:52:36 +00:00
2026-03-26 01:52:36 +00:00
2026-03-26 01:52:36 +00:00

Pad Web UI

SvelteKit 2 + Svelte 5 frontend for Pad, compiled to static files and embedded into the Go binary.

Development

npm install
npm run dev          # Dev server at localhost:5173 (proxies API to localhost:7777)
npm run build        # Production build to build/
npm run check        # Type checking with svelte-check

When developing, run the Go backend separately with make dev from the project root.

Building for Production

Do not build in isolation. Always use make build from the project root — this builds the web frontend, then compiles the Go binary with the build output embedded via //go:embed.

Stack

  • Svelte 5 with runes ($state, $derived, $effect)
  • SvelteKit 2 with adapter-static (SPA mode)
  • Tiptap block editor with markdown round-trip
  • svelte-dnd-action for drag-and-drop in board/list views
  • SSE for real-time updates
  • TypeScript throughout

Structure

src/
  routes/                    SvelteKit pages
    +layout.svelte           App shell (sidebar + main)
    +page.svelte             Landing/redirect
    [workspace]/
      +page.svelte           Dashboard (collections, phases, activity)
      +layout.svelte         SSE connection per workspace
      [collection]/
        +page.svelte         Collection view (board/list)
      [collection]/[item]/
        +page.svelte         Item detail + editor
      conventions/            Purpose-built conventions page
      playbooks/              Purpose-built playbooks page
      settings/               Workspace settings
  lib/
    api/client.ts            HTTP API client
    components/
      layout/                Sidebar, navigation
      editor/                Tiptap editor, raw markdown editor
      fields/                FieldEditor, relation picker
      items/                 ItemCard, ItemDetail
      collections/           BoardView, ListView
      common/                StatusBadge, badges, modals
      search/                CommandPalette
    stores/                  Svelte 5 reactive stores
      workspace.svelte.ts    Workspace state
      collections.svelte.ts  Collection + item state
      ui.svelte.ts           Sidebar, mobile state
    types/index.ts           TypeScript types and constants
  app.css                    Global styles and design tokens