refactor(dashboard): move tabs to route segments#317
Conversation
Render only the active dashboard query tab and use hover-intent prefetch for tab links. Add route-level reset-aware error boundaries so tab and page failures stay scoped to their own segment. Co-authored-by: Cursor <cursoragent@cursor.com>
Route the dashboard-level error file through the shared reset-aware route error component so top-level dashboard failures use the same isolated recovery behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Upgrades Next.js to Changes dashboard tabs (sandboxes/templates and sandbox details) from Reviewed by Cursor Bugbot for commit 1fd14c7. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
This PR refactors dashboard tab navigation to be driven by query-based routing (instead of parallel routes) and standardizes dashboard route error handling so error boundaries can reset on navigation and provide a proper “retry” action.
Changes:
- Add
onRetrysupport to the shared error UI, and introduce aDashboardRouteErrorwrapper that auto-resets on route/query changes. - Update
DashboardTabsto render only the active tab content and switch tab links toHoverPrefetchLink. - Convert Templates and Sandboxes tab implementations from parallel routes (
@list,@builds,@monitoring) to a single(tabs)/page.tsxthat selects content based on?tab=..., plus add route-levelerror.tsxfiles across dashboard routes.
Reviewed changes
Copilot reviewed 36 out of 36 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/ui/error.tsx | Plumbs onRetry from the boundary wrapper down into the indicator UI. |
| src/ui/error-indicator.tsx | Adds optional onRetry callback to drive retry behavior (otherwise falls back to router.refresh()). |
| src/ui/dashboard-tabs.tsx | Updates active-tab resolution and only renders the active tab content; swaps tab links to HoverPrefetchLink. |
| src/features/dashboard/shared/route-error.tsx | New shared dashboard route error component that resets on navigation/query changes and wires reset into retry. |
| src/app/dashboard/error.tsx | Switches to DashboardRouteError and uses Next.js reset. |
| src/app/dashboard/[teamSlug]/webhooks/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/usage/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/templates/[templateId]/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/templates/[templateId]/builds/[buildId]/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/templates/(tabs)/page.tsx | New unified templates tabs page that selects list/builds via ?tab=. |
| src/app/dashboard/[teamSlug]/templates/(tabs)/layout.tsx | Updates templates tabs layout to use children instead of parallel-route slots. |
| src/app/dashboard/[teamSlug]/templates/(tabs)/error.tsx | Adds error boundary for the templates tabs route group. |
| src/app/dashboard/[teamSlug]/templates/(tabs)/@list/page.tsx | Removes parallel-route list page (replaced by unified tabs page). |
| src/app/dashboard/[teamSlug]/templates/(tabs)/@list/default.tsx | Removes parallel-route list default. |
| src/app/dashboard/[teamSlug]/templates/(tabs)/@builds/page.tsx | Removes parallel-route builds page (replaced by unified tabs page). |
| src/app/dashboard/[teamSlug]/templates/(tabs)/@builds/default.tsx | Removes parallel-route builds default. |
| src/app/dashboard/[teamSlug]/sandboxes/[sandboxId]/monitoring/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/sandboxes/[sandboxId]/logs/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/sandboxes/[sandboxId]/filesystem/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/sandboxes/[sandboxId]/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/page.tsx | Replaces placeholder with unified sandboxes tabs page selecting monitoring/list via ?tab= (and prefetching list data). |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/layout.tsx | Updates sandboxes tabs layout to use children instead of parallel-route slots. |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/error.tsx | Adds error boundary for the sandboxes tabs route group. |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/@monitoring/page.tsx | Removes parallel-route monitoring page (replaced by unified tabs page). |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/@monitoring/default.tsx | Removes parallel-route monitoring default. |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/@list/page.tsx | Removes parallel-route list page (replaced by unified tabs page). |
| src/app/dashboard/[teamSlug]/sandboxes/(tabs)/@list/default.tsx | Removes parallel-route list default. |
| src/app/dashboard/[teamSlug]/members/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/limits/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/keys/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/general/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/error.tsx | Adds route-level error boundary at the team dashboard segment. |
| src/app/dashboard/[teamSlug]/billing/plan/select/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/billing/plan/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/billing/error.tsx | Adds route-level error boundary using DashboardRouteError. |
| src/app/dashboard/[teamSlug]/account/error.tsx | Adds route-level error boundary using DashboardRouteError. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Apply formatter output for the shared dashboard route error component so format CI passes. Co-authored-by: Cursor <cursoragent@cursor.com>
matthewlouisbrockman
left a comment
There was a problem hiding this comment.
some bot comments and formatting nit need to get fixed but looks god direction
Streamline dashboard tab resolution and rendering while preserving active-tab-only content rendering and hover-based prefetch behavior. Include lockfile updates from local tooling to keep installs reproducible. Co-authored-by: Cursor <cursoragent@cursor.com>
Call router.refresh() before reset() in dashboard route error retries so server-component failures can recover instead of immediately replaying cached error state. Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid direct indexed access in dashboard tabs by guarding the first tab before use so strict TypeScript builds pass. Co-authored-by: Cursor <cursoragent@cursor.com>
Make dashboard tabs navigation-only and move templates and sandboxes tabs onto path segments so each tab owns its page content and error boundary. Co-authored-by: Cursor <cursoragent@cursor.com>
Update Next.js and add browser stubs for Node built-ins pulled into the sandbox inspector client bundle so webpack builds can compile successfully. Co-authored-by: Cursor <cursoragent@cursor.com>
Move the dashboard tab redirect map into a config module so integration tests can import it without violating Next route export constraints. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit cabdb74. Configure here.
Add an explicit fs/promises browser alias so node:fs/promises requests still resolve correctly after the webpack node: scheme replacement runs. Co-authored-by: Cursor <cursoragent@cursor.com>
Add integration coverage for webpack browser stub aliases and the sandbox inspector's E2B filesystem methods so build-time shims and runtime SDK usage stay aligned. Co-authored-by: Cursor <cursoragent@cursor.com>

Motivation
Dashboard tab pages were still vulnerable to stale RSC/module payloads when users navigated quickly between templates and sandboxes tabs. This PR moves route-backed tabs onto real path segments so the App Router owns tab content, loading, and error boundaries per page instead of switching tab content client-side.
Summary
?tab=query state to/list,/builds, and/monitoringroute segments.Validation
bun run format:checkbunx tsc --noEmit --pretty falsebunx next build --webpack