Skip to content

feat(desktop): add Projects as first-class top-level view#546

Merged
wesbillman merged 1 commit into
mainfrom
desktop/add-projects-feature
May 12, 2026
Merged

feat(desktop): add Projects as first-class top-level view#546
wesbillman merged 1 commit into
mainfrom
desktop/add-projects-feature

Conversation

@wesbillman
Copy link
Copy Markdown
Collaborator

Summary

  • Adds Projects to the desktop sidebar as a top-level navigation entry (between Pulse and Agents)
  • /projects route with dense operational project list sourced from kind:30617 (NIP-34 repo announcements)
  • /projects/$projectId route with detail page showing clone URLs, web link, resolved contributors with avatars
  • Data fetching via relayClient.fetchEvents() with NIP-33 dedup and 60s stale time

Details

Navigation & routing:

  • AppView type extended with "projects", deriveShellRoute() updated
  • goProjects() and goProject(id) navigation functions
  • TanStack file-based routes with lazy loading and Suspense

Data layer (features/projects/hooks.ts):

  • useProjectsQuery() — fetches kind:30617 events, deduplicates by pubkey:kind:d-tag
  • useProjectQuery(id) — targeted #d tag filter query (not capped by list limit)
  • Multi-value clone URL parsing (tag.slice(1) for single ["clone", url1, url2] tags)
  • Composite pubkey:d IDs for React key uniqueness
  • KIND_REPO_ANNOUNCEMENT constant in shared/constants/kinds.ts

UI:

  • Keyboard-accessible project cards (button overlay pattern, matching WorkflowCard)
  • Error/empty/loading states with retry buttons
  • Owner and contributors resolved to display names via useUsersBatchQuery + resolveUserLabel
  • UserAvatar for contributor display
  • isSafeUrl gate on web URLs (extracted to shared/lib/url.ts, shared with DiffMessage)

Notable NITs (not addressed)

  • No unit tests for hooks or isSafeUrl (desktop has no vitest/jest infra — e2e only)
  • setTimeout cleanup in CloneUrlRow copy button
  • Loading skeleton reuses CardListLoadingBody (renamed from WorkflowsLoadingBody)

Test plan

  • Click Projects in sidebar → navigates to /projects, shows project list
  • Click a project card → navigates to /projects/$projectId, shows detail
  • Detail page shows resolved display names and avatars for owner/contributors
  • Clone URLs show all URLs (HTTPS + SSH) from multi-value tag
  • Error state: disconnect relay → shows error with Retry button
  • Empty state: relay with no repos → shows "No projects yet"
  • Keyboard: Tab to project card, press Enter → navigates to detail
  • Direct URL navigation to /projects/$projectId works (targeted query)
  • Web URL with javascript: scheme does not render as a link

🤖 Generated with Claude Code

Add Projects to the desktop sidebar with full routing, data fetching,
and detail pages. Projects are sourced from kind:30617 (NIP-34 repo
announcement) events via the relay.

Navigation:
- Projects sidebar entry between Pulse and Agents
- /projects route with dense project list
- /projects/$projectId route with targeted #d tag query

Data layer:
- useProjectsQuery() for list, useProjectQuery() for detail
- Multi-value clone URL tag parsing (single tag with multiple values)
- NIP-33 dedup by pubkey:kind:d-tag, composite IDs for uniqueness
- KIND_REPO_ANNOUNCEMENT constant in shared/constants/kinds.ts

UI:
- Keyboard-accessible project cards (button overlay pattern)
- Error/empty/loading states with retry buttons
- Resolved display names via useUsersBatchQuery + resolveUserLabel
- UserAvatar for contributors, isSafeUrl gate on web URLs
- Shared isSafeUrl extracted to shared/lib/url.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesbillman
Copy link
Copy Markdown
Collaborator Author

Screenshot 2026-05-12 at 10 50 24 AM Screenshot 2026-05-12 at 10 50 47 AM

@wesbillman wesbillman merged commit ef5fdca into main May 12, 2026
15 checks passed
@wesbillman wesbillman deleted the desktop/add-projects-feature branch May 12, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant