Files
pad/web
xarmian 4b2fbe55df refactor(attachments): separate view identity from request generation per final review
Final full-diff review of PLAN-2392 phases 1/1b found four issues the
per-task reviews structurally could not see.

P2 — the strip fenced its delete mutation on the LOAD generation, which a
Retry also bumps. A delete failure landing during a same-item Retry was
therefore mistaken for an A→B item switch and silently swallowed: no
rollback, no toast, no 404 broadcast. Split the single counter in two —
`loadGeneration` (per request, bumped by every effect run including
Retry) still fences load responses; a new `viewGeneration` (bumped only
when the view actually changes, plus onDestroy) fences mutations. The
effect cleanup deliberately bumps only the request generation, since it
also runs before a Retry's re-run.

View identity is the (workspace, item) pair, not the item: `wsSlug` is
reactive and the strip survives a workspace change, so an item-only key
would read that change as a same-item Retry. `viewKey()` now backs the
retry marker, the painted-error owner, and the mutation fence alike.

Exposed by the new test: the rollback splice was not idempotent. A
reload that restored the row while the delete was in flight made it
duplicate the id and the keyed each block threw. The rollback now skips
the re-insert when the row is already back, and still toasts.

P2 — Storage's Retry now performs the same attachment metadata-cache
invalidation the strip's does, so a failed HEAD cached during the outage
doesn't stay poisoned on chips and inline images after recovery. While
there, loadList captures and re-checks its request workspace: the
generation alone couldn't tell a superseded workspace from the current
one, and both the rows and the cache keys are workspace-scoped.

P3 — StorageTab's `anyFilterActive` re-listed the filter fields instead
of reusing `selections()`; one projection now, so they cannot drift.

P3 — the deletion tombstone set survives a Retry and rides a
workspace-wide bus, so it is bounded like the list buffers, shedding
oldest-first (the newest tombstone is the one still racing a response)
and refreshing an id's age when it is re-announced.

Claude-Session: https://claude.ai/code/session_01LmbFxQFDjcYKBLcTnor6DC
2026-08-03 11:30:17 +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
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
      activity/              ActivityFeed
    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