Skip to content

improvement(settings): remove the 300ms floor under settings section switches - #8435

Merged
waleedlatif1 merged 2 commits into
stagingfrom
improvement/settings-navigation-speed
Sep 29, 2026
Merged

waleedlatif1 merged 2 commits into
stagingfrom
improvement/settings-navigation-speed

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Every settings section switch paid a fixed ~300ms before the section even rendered. Each switch mounted a fresh Suspense boundary: the empty section loading.tsx, plus a page-level <Suspense fallback={null}> around the code-split body. React 19 holds content that resolves into a just-committed fallback until 300ms after that fallback appeared, so the body, its chunk and its queries all queued behind that floor
  • Removed the section loading.tsx (workspace + org) and the page-level Suspense on all four settings planes. Navigations are transitions, so the outgoing section stays on screen until the incoming one is ready. The boundary can't be hoisted into the settings layout: that would wrap the [section] layout, where 404 and legacy 307 are decided, and both would turn into 200
  • Sidebar rows move their selection on click (usePendingSettingsSelection, cleared on any pathname change), so the click is still acknowledged immediately
  • Warm each hot section's first-content queries on sidebar intent (secrets env, forks lineage, teammates invitations, API keys, custom tools, MCP, workflow MCP) so data loads alongside the route payload. Extracted queryOptions factories for those hooks; behavior is unchanged apart from retryOnMount: true, per the prefetch-on-intent rule
  • Forks and custom tools downloaded a ~6MB block/trigger registry chunk just to render their lists. The fork sync editor and the custom tool editor now load on open, and "Add tool" warms the editor on hover. Views opened by a plain state update get loading: () => null so they have their own boundary

Type of Change

  • Performance improvement

Testing

  • A/B of production builds in headless Chromium, interleaved base/opt ×3, 40ms emulated browser latency, 1.5ms/leg DB latency proxy. Seed: 64 workspaces, ~340 secrets in one workspace, 17 forks, 44 API keys
    • First visit to a section: 330–410ms → 80–90ms (forks 404→90, custom-tools 372→80, teammates 330→87, apikeys 402→88); secrets 500→174
    • 14-step navigation route total: 4146ms → 1292ms (−69%)
  • Behavioral verification against both builds (JSON report per build):
    • All 20 sections render byte-identical content on direct load and on client navigation (40/40)
    • 404 for an unknown section; 307 for legacy integrations / privacy
    • Clicked row is selected in ~20ms; selection follows the URL on the browser back button
    • Unsaved-changes guard still blocks a switch and keeps the selection
    • Fork sync deep link and custom tool editor still open
    • React chore(deps): bump the workspace-dependencies group with 22 updates #418 hydration errors: 5 on base, 0 on this branch
  • bun run --cwd apps/sim test over settings, sidebar, hooks/queries and workspace-forking: 108 files / 648 tests pass
  • bun run lint, bun run type-check, check-block-registry, bun run check:audits (52 audits), docs-manifest:check
  • Tool-registry boundary ratchet: workspace layout graph within baseline; the removed loading.tsx entry is dropped from the baseline

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…switches

Every section switch mounted a fresh Suspense boundary (the empty section loading.tsx and a page-level <Suspense fallback={null}> around the code-split body). React 19 holds content that resolves into a just-committed fallback for at least 300ms, so every switch paid that before the section even rendered or started its queries.

- drop the section loading boundaries and page-level Suspense on all settings planes; navigations are transitions, so the outgoing section stays until the incoming one is ready
- move the sidebar selection on click so the click still reads as acknowledged
- warm each hot section's first-content queries on navigation intent
- load the fork sync editor and custom tool editor on open; they pulled the block and trigger registries into the list chunks
@vercel

vercel Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Sep 29, 2026 10:24pm UTC

Request Review

@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Settings navigation removes loading boundaries to speed up section switches.

The PR appears safe to merge; no new actionable issue or outstanding previous finding was established.

Summary

The PR removes settings-section loading boundaries and delays loading the fork-sync and custom-tool editors until they are opened. Since the previous review, it changes sidebar navigation to keep the clicked row selected during a route transition and restore the route’s selection when that transition settles.

Reviews (2) · Last reviewed commit: "fix(settings): tie the pending sidebar s..."

Comment thread apps/sim/components/settings/use-pending-settings-selection.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 20 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/app/selfhost/settings/[section]/page.tsx
Comment thread apps/sim/components/settings/settings-sidebar.tsx
The pending row cleared only on a pathname change, so a navigation the server redirected back to the current section, or one that failed, left the clicked row selected and its click guard swallowing retries. Set the selection optimistically inside the navigation's own transition so React drops it when that transition settles.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 20 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit c82d618 into staging Sep 29, 2026
23 checks passed
@waleedlatif1
waleedlatif1 deleted the improvement/settings-navigation-speed branch September 29, 2026 22:32

This branch was previously deployed

1 inactive deployment
Preview — 0d84d1e5 Deployed Sep 29, 2026 by vercel[bot]
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