Deep links and Copy link across the whole UI #65

Open
opened 2026-09-24 15:53:55 +00:00 by kayg · 5 comments
Owner

Owner rule (2026-09-24): "everything has a copy link action, meaning all parts of the UI should be deep-linkable". CLAUDE.md now makes this binding for every UI job; DESIGN §33 holds the URL grammar.

Build the shared deep-link foundation in apps/web + packages/ui:

  • A route/intent layer implementing the §33 grammar (calendar views, days + block anchors, notes + headings/blocks, files/folders, photos/albums, external events, tasks, tags, saved searches, search queries, settings sections, admin pages), following calternal.js docs/deep-linking.md (imperative navigation + URL→intent effect for cold load and back/forward; overlay-guarded; ready-gated).
  • Server redirects/lookups by stable ID (/n/<calternal-id>, /f/<item-id>, /t/<task-id>) so links survive renames and moves; permission-checked without leaking existence; deleted targets show a friendly state with a Trash link when restorable.
  • One CopyLinkAction used everywhere: context menu item, ⋯ menu item, swipe-from-left action on touch (default action), header copy button, keyboard shortcut (⌘⇧C) — using calternal.js's copy interaction aesthetics (header link copy feedback) and a Sonner toast.
  • Audit every existing screen and add Copy link; add an e2e test that visits each route kind from a cold load and asserts the exact view restores.
    Read CLAUDE.md, CONTEXT.md, docs/DESIGN.md §25, §29–§33. Comment on this issue as you work; never close it.
Owner rule (2026-09-24): "everything has a copy link action, meaning all parts of the UI should be deep-linkable". CLAUDE.md now makes this binding for every UI job; DESIGN §33 holds the URL grammar. Build the shared deep-link foundation in apps/web + packages/ui: - A route/intent layer implementing the §33 grammar (calendar views, days + block anchors, notes + headings/blocks, files/folders, photos/albums, external events, tasks, tags, saved searches, search queries, settings sections, admin pages), following calternal.js `docs/deep-linking.md` (imperative navigation + URL→intent effect for cold load and back/forward; overlay-guarded; ready-gated). - Server redirects/lookups by stable ID (`/n/<calternal-id>`, `/f/<item-id>`, `/t/<task-id>`) so links survive renames and moves; permission-checked without leaking existence; deleted targets show a friendly state with a Trash link when restorable. - One `CopyLinkAction` used everywhere: context menu item, ⋯ menu item, swipe-from-left action on touch (default action), header copy button, keyboard shortcut (⌘⇧C) — using calternal.js's copy interaction aesthetics (header link copy feedback) and a Sonner toast. - Audit every existing screen and add Copy link; add an e2e test that visits each route kind from a cold load and asserts the exact view restores. Read CLAUDE.md, CONTEXT.md, docs/DESIGN.md §25, §29–§33. Comment on this issue as you work; never close it.
Author
Owner

Started: deep-link and Copy link audit on branch job/deeplinks (from main cf3c094). Plan: inventory every surface and item type, fix missing routes and Copy link actions, add docs/deep-links.md and an e2e test apps/web/e2e/deeplinks.mjs.

Started: deep-link and Copy link audit on branch job/deeplinks (from main cf3c094). Plan: inventory every surface and item type, fix missing routes and Copy link actions, add docs/deep-links.md and an e2e test apps/web/e2e/deeplinks.mjs.
Author
Owner

Finished: branch job/deeplinks, head 5821fde (rebased on main 1bbd40e). Not pushed or merged.

Fixed:

  • /t/ was missing (every copied Task link failed). Added, with GET /api/v1/notes/tasks/by-id; the Day view selects the Task (?task=).
  • Copied Event links failed: the grid copies occurrence ids (@) that GET /api/v1/calendar/events/{id} refused. The endpoint now resolves occurrences; /e/ selects the Event (?event=).
  • /d/#^ now follows an entry moved to another day (GET /api/v1/notes/journal/entries/{block_id}).
  • Added /p/ (to /f/), /admin/ (to /settings/admin/), /f/?open=share.
  • Copy link added: search results (preview and phone peek; stable /n/ or /f/ only), Recent and Trash headers, All notes and Journal rows, sidebar tag menu, undated Tasks in the Day panel.
  • Long press opens row menus on touch (Notes explorer, saved searches, tags, Recent).
  • Trash swipe said Copy link but put the item back; label fixed.
  • noteHref/tagHref give canonical /n/ and /tag/.
  • docs/deep-links.md (inventory) and DESIGN §33 updated to reality (/search/saved/, /e/[@]).
  • e2e apps/web/e2e/deeplinks.mjs passes; adversarial section deeplinks added.

Open gaps: Task ids are Markdown paths, so a Task file rename breaks /t/; share dialog has a link but no Copy link control; info panel open state is not in the URL; photos/albums not built. Pre-existing on main: collab hostile_clients unrepresentable_update test and server wire live_apps test fail.

Finished: branch job/deeplinks, head 5821fde (rebased on main 1bbd40e). Not pushed or merged. Fixed: - /t/<task-id> was missing (every copied Task link failed). Added, with GET /api/v1/notes/tasks/by-id; the Day view selects the Task (?task=). - Copied Event links failed: the grid copies occurrence ids (<id>@<start>) that GET /api/v1/calendar/events/{id} refused. The endpoint now resolves occurrences; /e/ selects the Event (?event=). - /d/<date>#^<block> now follows an entry moved to another day (GET /api/v1/notes/journal/entries/{block_id}). - Added /p/<item-id> (to /f/), /admin/<page> (to /settings/admin/<page>), /f/<id>?open=share. - Copy link added: search results (preview and phone peek; stable /n/ or /f/ only), Recent and Trash headers, All notes and Journal rows, sidebar tag menu, undated Tasks in the Day panel. - Long press opens row menus on touch (Notes explorer, saved searches, tags, Recent). - Trash swipe said Copy link but put the item back; label fixed. - noteHref/tagHref give canonical /n/ and /tag/. - docs/deep-links.md (inventory) and DESIGN §33 updated to reality (/search/saved/<id>, /e/<event-id>[@<start>]). - e2e apps/web/e2e/deeplinks.mjs passes; adversarial section deeplinks added. Open gaps: Task ids are Markdown paths, so a Task file rename breaks /t/; share dialog has a link but no Copy link control; info panel open state is not in the URL; photos/albums not built. Pre-existing on main: collab hostile_clients unrepresentable_update test and server wire live_apps test fail.
Author
Owner

Hygiene review: the final report still lists path-based Task IDs that break on rename, no Copy link control in the share dialog, no URL state for the inspector, and Photos/albums not built. Keeping #65 open.

Hygiene review: the final report still lists path-based Task IDs that break on rename, no Copy link control in the share dialog, no URL state for the inspector, and Photos/albums not built. Keeping #65 open.
Author
Owner

Static audit evidence for DESIGN §33 reality check:

The last two bullets in docs/DESIGN.md:1011-1012 still say that a Task ID is its Markdown location and stable identity is still to do. The implementation now has a stable identity: crates/plugins/notes/src/tasks_api.rs:835-842 resolves stable IDs and legacy aliases, crates/plugins/notes/src/tasks_store.rs:308-324 retargets aliases after projection changes, and crates/plugins/notes/migrations/0010_task_identity.sql:1-12 adds the identity and alias table.

Please update the stale reality-check text. Regression idea: create a /t link, rename or move the Task file, and confirm the same stable link still resolves.

Static audit evidence for DESIGN §33 reality check: The last two bullets in docs/DESIGN.md:1011-1012 still say that a Task ID is its Markdown location and stable identity is still to do. The implementation now has a stable identity: crates/plugins/notes/src/tasks_api.rs:835-842 resolves stable IDs and legacy aliases, crates/plugins/notes/src/tasks_store.rs:308-324 retargets aliases after projection changes, and crates/plugins/notes/migrations/0010_task_identity.sql:1-12 adds the identity and alias table. Please update the stale reality-check text. Regression idea: create a /t link, rename or move the Task file, and confirm the same stable link still resolves.
Author
Owner

Design-sync #864 corrected DESIGN §33 on job/design-sync, commit 01c089351.

Old docs/DESIGN.md:1011-1012 said a Task rename breaks its link. crates/plugins/notes/src/tasks_api.rs:835-842, tasks_store.rs:308-324 and migration 0010_task_identity.sql:1-16 already support permanent Task file identity and retained aliases. The text now records calternal-id and old-path / Reminders UID aliases.

Expected behaviour stays: Task file links survive renames and moves. Regression idea: open the permanent link and a retained old-path alias after each operation. No runtime claim or test run from this LIGHT documentation job.

Design-sync #864 corrected DESIGN §33 on `job/design-sync`, commit `01c089351`. Old docs/DESIGN.md:1011-1012 said a Task rename breaks its link. crates/plugins/notes/src/tasks_api.rs:835-842, tasks_store.rs:308-324 and migration 0010_task_identity.sql:1-16 already support permanent Task file identity and retained aliases. The text now records calternal-id and old-path / Reminders UID aliases. Expected behaviour stays: Task file links survive renames and moves. Regression idea: open the permanent link and a retained old-path alias after each operation. No runtime claim or test run from this LIGHT documentation job.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal-v0#65
No description provided.