feat(web): upgrade project and thread deep linking#1493
feat(web): upgrade project and thread deep linking#1493anduimagui wants to merge 1 commit intopingdotgg:mainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
|
|
||
| if (!threadsHydrated || target.kind !== "empty") { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Parent route missing Outlet breaks all canonical thread URLs
High Severity
The generated route tree (routeTree.gen.ts) establishes _chat.projects.$projectId as the parent of _chat.projects.$projectId.threads.$threadId (via getParentRoute: () => ChatProjectsProjectIdRoute). In TanStack Router, a parent route must render an <Outlet /> for its child route's component to appear. ProjectRouteView never renders <Outlet /> — it returns either null (when target.kind !== "empty") or a self-contained empty-state div. This means CanonicalThreadRouteView can never render, so all thread content accessed via the new canonical /projects/$projectId/threads/$threadId URLs will show a blank screen.
Additional Locations (1)
| params: { projectId, threadId: target.threadId }, | ||
| replace: true, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Parent route effect redirects away from intended thread
High Severity
When the URL is /projects/$projectId/threads/$threadId, ProjectRouteView still runs as the parent layout component. Its useEffect calls resolveProjectRouteTarget, which picks the latest thread by sort order — not the thread in the URL. The effect then navigates to that latest thread with replace: true, silently redirecting the user away from the thread they intended to view. This redirect is only appropriate when the URL is /projects/$projectId (no child thread route matched), but it fires unconditionally for all child routes too.


What Changed
/projects/$projectIdand/projects/$projectId/threads/$threadId/$threadIdlinks into compatibility redirects so existing deep links still resolve while the app moves to project-scoped URLsWhy
The app already had deep links for individual threads and settings, but thread URLs did not include project context and projects themselves were not first-class deep-link targets. That made links less descriptive and made it harder to build more predictable navigation on top of the current routing model.
This change upgrades deep linking with a canonical project-first URL shape while preserving backward compatibility for old thread links. It improves shareability and routing clarity without broad UI churn or server-side behavior changes.
UI Changes
New threadaction.Checklist
Note
Medium Risk
Moderate risk because it refactors client-side routing/deep-link behavior across thread creation, sidebar navigation, and diff toggling; mistakes could break navigation or redirects but no auth/data-path changes are involved.
Overview
Upgrades deep linking to project-scoped URLs. Adds canonical routes for
/projects/$projectIdand/projects/$projectId/threads/$threadId, with/$threadIdconverted into a compatibility redirect that preserves diff-related search params.Updates in-app navigation to emit the new URLs. Thread/diff navigation from
ChatView,DiffPanel,Sidebar, app bootstrap, and new-thread flows now includeprojectId, with guards for missingactiveThreadand better fallback behavior after deletes.Extracts and tests route resolution/rendering. Introduces
ThreadRouteContentfor shared thread UI andprojectRoutehelpers (resolveProjectRouteTarget,resolveThreadRouteTarget) with unit coverage for missing/empty/latest-thread and draft/server thread resolution.Written by Cursor Bugbot for commit 06c6a37. This will update automatically on new commits. Configure here.
Note
Upgrade thread routing to project-scoped deep links at
/projects/$projectId/threads/$threadId/projects/$projectId/threads/$threadIdinstead of/$threadId.projectIdin the URL./$threadIdroute in _chat.$threadId.tsx now only redirects to the canonical project-scoped path rather than rendering the chat UI.resolveProjectRouteTargetandresolveThreadRouteTargethelpers in projectRoute.ts for resolving project/thread ownership during route transitions./$threadIdwill redirect to the canonical route; any navigation without a resolvableprojectIdwill redirect to/.Macroscope summarized 06c6a37.