mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-25 03:42:06 +00:00
a40049c214
Final round, scoped to this phase's six acceptance criteria rather than to whatever the diff suggested — the previous rounds had started finding issues in adjacent surfaces, which is the signal that the core had converged and the review was expanding. Three of the six were not actually met: 3. Download returned `undefined` for a nameless row, which drops the attribute entirely and turns Download back into a navigation. The server sends an inline disposition for most types, so the file would have OPENED instead of saving — the precise regression this action exists to prevent, reachable whenever a chip's metadata is partial. The attribute is now always present; empty just lets the browser name the file. 5. "A peeked pane offers no delete" was implemented as a visible, disabled Delete row. The strip hides its delete control outright in the same state, so one object was offering two different affordances for one permission depending on which surface you met it through. Delete is absent now, with `enabled` and `run` still gating behind it. That change surfaced a conflation in the panel: its action context ANDed permission with `missing`, so once the descriptor used it to decide EXISTENCE, a gone row lost Delete while Open and Download stayed present-and-disabled beside it. Permission and reachability are separate questions again — the render site already disables every action while missing. 1. The editor-chip half of "the same panel wherever you meet an attachment" had no end-to-end coverage: the chip's tests mock the bus and the host's inject events directly, so nothing exercised a real NodeView reaching a real host. Covered now by a browser test that drops a text file and clicks the resulting chip. make check exit 0, 745 unit tests, 6/6 e2e locally.
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