Skip to content

feat: Migrate web UI to TanStack Router#19

Merged
dastratakos merged 7 commits into
mainfrom
dastratakos/tanstack-files-route
May 4, 2026
Merged

feat: Migrate web UI to TanStack Router#19
dastratakos merged 7 commits into
mainfrom
dastratakos/tanstack-files-route

Conversation

@dastratakos

@dastratakos dastratakos commented May 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrate the stage-cli web UI from hash-tab state to TanStack Router so Files changed lives at /runs/:runId/files.

Changes

  • Add TanStack Router setup, generated route tree, and file routes for run overview and files.
  • Replace local tab state with typed route links and update stage-cli show to open /runs/:runId.
  • Remove the old hash run-id hook while preserving a legacy #/runs/... redirect.

Testing

pnpm typecheck && pnpm lint && pnpm test && pnpm build


Open in Stage

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the web application's routing from a custom hash-based implementation to TanStack Router. Key changes include the introduction of a file-based routing system, refactoring the main layout to utilize router-native components like Link and Outlet, and updating the CLI to support path-based navigation. Feedback focuses on improving the idiomatic use of the router by suggesting useMatchRoute for tab state management and recommending the extraction of duplicated logic for calculating viewed chapter counts into a shared utility.

Comment thread packages/web/src/routes/pull-request-layout.tsx
Comment thread packages/web/src/routes/pull-request-layout.tsx
Comment thread packages/web/src/app/runs.$runId.index.tsx Outdated
Comment thread packages/web/src/app/__root.tsx Outdated
@dastratakos dastratakos changed the title Migrate web UI to TanStack Router feat: Migrate web UI to TanStack Router May 3, 2026
TanStack Router's `ParsedLocation.hash` strips the leading `#`
(see router-core/src/router.ts: `hash: decodePath(hash.slice(1)).path`),
so the previous `location.hash.startsWith("#/runs/")` check never matched
and the redirect was dead. `slice(1)` was also stripping the leading `/`
rather than a (non-existent) `#`.

Match `/runs/` and pass `location.hash` through unchanged so legacy
`/#/runs/abc` URLs redirect to `/runs/abc`.
Comment thread packages/web/src/app/runs.$runId.index.tsx Outdated
Comment thread packages/web/src/router.tsx Outdated
Both `PullRequestLayout` (for the tab count chip) and `ChaptersRoute`
(for prop-drilling into ChaptersIndexPage) ran the same useMemo loop to
count viewed chapters. The duplication was introduced by the TanStack
Router migration since `Outlet` doesn't pass props from layout to child.

Extract the loop into a pure helper next to `useViewStateData` and call
it from both sites.
`queryClient` was a module-level constant but the router was created
fresh on every `getRouter()` call, which is asymmetric and risks
multiple routers sharing one queryClient (e.g. under HMR or in tests).

Match TanStack Router's canonical setup (https://tanstack.com/router/latest/docs/framework/react/quick-start)
by exporting `router` directly. Drop the `getRouter`/`getQueryClient`
factory wrappers in favor of named exports.
Pre-ship there are no users with bookmarked `/#/runs/...` URLs to
preserve. The earlier fix (041833a) made the redirect actually fire,
but the simpler answer is to delete it entirely — YAGNI.

export const Route = createFileRoute("/")({
component: NoRunSelected,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy hash URL redirect is missing

Medium Severity

The PR description states it preserves "a legacy #/runs/... redirect," and the old useHashRunId hook is deleted, but no redirect from hash-based URLs to path-based URLs exists anywhere in the codebase. A user arriving at /#/runs/abc (e.g. from browser history or a cached link) lands on the / route and sees "No run selected" instead of being redirected to /runs/abc. The PR discussion references a fix in commit 041833a, but the redirect logic is absent from the final code.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit db957b3. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3b7d776. Configure here.

import { createRouter } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";

export const queryClient = new QueryClient();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QueryClient lost default staleTime affecting view state

Low Severity

The QueryClient previously had staleTime: 30_000 as a global default, with a comment noting it "keeps a single tab from re-fetching too eagerly." The new QueryClient() has no defaults. While useChapters and useDiffPatch received explicit staleTime: Number.POSITIVE_INFINITY, useViewStateData was not updated and now defaults to staleTime: 0, causing it to refetch on every component mount and window focus event.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3b7d776. Configure here.

@dastratakos dastratakos marked this pull request as ready for review May 4, 2026 00:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3b7d776d10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +7 to +8
export const router = createRouter({
routeTree,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve legacy #/runs/... entry URLs

This router initialization drops support for old hash-based links, because it uses default browser history and no startup migration from window.location.hash to a path route. After this commit, opening a previously shared URL like http://127.0.0.1:5391/#/runs/<id> lands on / and shows “No run selected” instead of the run, since the hash is ignored by route matching. This is a user-facing regression for existing bookmarks/links from earlier stage-cli show output and should be handled via a one-time hash redirect or explicit hash history compatibility.

Useful? React with 👍 / 👎.

@dastratakos dastratakos merged commit 3303a59 into main May 4, 2026
5 checks passed
@dastratakos dastratakos deleted the dastratakos/tanstack-files-route branch May 4, 2026 05:09
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