Phase 3 (Web UX Polish) of the execution roadmap:
- Add reusable Pagination component for list views
- Fix getNoteDetail to avoid fetching all notes when workspaceId is unknown
- Add file upload button to ArtifactPanel using uploadArtifact() from blob-client
- Remove unused zustand and zod from web dependencies
- SSR safety already addressed via existing lazy-init patterns
Made-with: Cursor
- types.ts: consolidate NoteDoc, WorkspaceDoc, NoteAgentActionDoc etc. from client files
- notes-client.ts: import from types.ts, optimize getNoteDetail with direct GET /notes/:id
- review-client.ts: import from types.ts, use /note-agent-actions/pending (eliminates N+1)
- notes-client.ts: use /workspaces/summaries (eliminates fetch-all-notes for counts)
- backend: add GET /workspaces/summaries with noteCount per workspace
- backend: add GET /note-agent-actions/pending (cross-workspace)
- backend: add countNotesByWorkspaces + listPendingActions repository functions
- Add createNote, archiveNote, restoreNote, createNoteRelationship client functions
- Fix existing tests for new route counts and mock order
- Created api-helpers.ts with shared getAccessToken() + createNotesApiClient()
- Removed duplicate API client factory from notes-client.ts, review-client.ts,
saved-views-client.ts (3 copies → 1 shared module)
- Added reviewedBy/reviewedAt/reviewNote fields to review-client NoteAgentActionDoc
type to match backend response shape
- Search page: use crypto.randomUUID() for saved view IDs instead of Date.now()
to prevent collisions on rapid saves
Verification: web typecheck + 6/6 tests pass.