The staged changes remove the main source of project-load latency by avoiding repeated full scans of ~/.codex/sessions for every project and by removing redundant client-side cursor session refetches.
Server changes (server/projects.js):\n- Add a per-request Codex index reference in getProjects so Codex metadata is built once and reused across all projects, including manually added ones.\n- Introduce normalizeComparablePath() to canonicalize project paths (including Windows long-path prefixes and case-insensitive matching on Windows).\n- Introduce findCodexJsonlFiles() + buildCodexSessionsIndex() to perform a single recursive Codex scan and group sessions by normalized cwd.\n- Update getCodexSessions() to accept indexRef and read from the prebuilt index, with fallback index construction when no ref is provided.\n- Preserve existing session limiting behavior (limit=5 default, limit=0 returns all).
Client changes (src/hooks/useProjectsState.ts):\n- Remove loadCursorSessionsForProjects(), which previously triggered one extra /api/cursor/sessions request per project after /api/projects.\n- Use /api/projects response directly during initial load and refresh.\n- Expand projectsHaveChanges() to treat both cursorSessions and codexSessions as external session deltas.\n- Keep refresh comparison aligned with external session updates by using includeExternalSessions=true in sidebar refresh path.
Impact:\n- Reduces backend work from roughly O(projects * codex_session_files) to O(codex_session_files + projects) for Codex discovery during a project load cycle.\n- Removes an additional client-side O(projects) network fan-out for Cursor session fetches.\n- Improves perceived and actual sidebar project-loading time, especially in large session datasets.
- Replace `src/App.jsx` with `src/App.tsx` and move route-level UI orchestration into `src/components/app/AppContent.tsx`.
This separates provider/bootstrap concerns from runtime app layout logic, keeps route definitions minimal, and improves readability of the root app entry.
- Introduce `src/hooks/useProjectsState.ts` to centralize project/session/sidebar state management previously embedded in `App.jsx`.
This keeps the existing behavior for:
project loading,
Cursor session hydration,
WebSocket `loading_progress` handling,
additive-update protection for active sessions,
URL-based session selection,
sidebar refresh/delete/new-session flows.
The hook now exposes a typed `sidebarSharedProps` contract and typed handlers used by `AppContent`.
- Introduce `src/hooks/useSessionProtection.ts` for active/processing session lifecycle logic.
This preserves session-protection behavior while isolating `activeSessions`, `processingSessions`, and temporary-session replacement into a dedicated reusable hook.
- Replace monolithic `src/components/Sidebar.jsx` with typed `src/components/Sidebar.tsx` as a thin orchestrator.
`Sidebar.tsx` now focuses on wiring controller state/actions, modal visibility, collapsed mode, and version modal behavior instead of rendering every UI branch inline.
- Add `src/hooks/useSidebarController.ts` to encapsulate sidebar interaction/state logic.
This includes expand/collapse state, inline project/session editing state, project starring/sorting/filtering, lazy session pagination, delete confirmations, rename/delete actions, refresh state, and mobile touch click handling.
- Add strongly typed sidebar domain models in `src/components/sidebar/types.ts` and move sidebar-derived helpers into `src/components/sidebar/utils.ts`.
Utility coverage now includes:
session provider normalization,
session view-model creation (name/time/activity/message count),
project sorting/filtering,
task indicator status derivation,
starred-project persistence and readbacks.
- Split sidebar rendering into focused components under `src/components/sidebar/`:
`SidebarContent.tsx` for top-level sidebar layout composition.
`SidebarProjectList.tsx` for project-state branching and project iteration.
`SidebarProjectsState.tsx` for loading/empty/no-search-result placeholders.
`SidebarProjectItem.tsx` for per-project desktop/mobile header rendering and actions.
`SidebarProjectSessions.tsx` for expanded session area, skeletons, pagination, and new-session controls.
`SidebarSessionItem.tsx` for per-session desktop/mobile item rendering and session actions.
`SessionProviderIcon.tsx` for provider icon normalization.
`SidebarHeader.tsx`, `SidebarFooter.tsx`, `SidebarCollapsed.tsx`, and `SidebarModals.tsx` as dedicated typed UI surfaces.
This keeps rendering responsibilities local and significantly improves traceability.
- Convert shared UI primitives from JSX to TSX:
`src/components/ui/button.tsx`,
`src/components/ui/input.tsx`,
`src/components/ui/badge.tsx`,
`src/components/ui/scroll-area.tsx`.
These now provide typed props/variants (`forwardRef` where appropriate) while preserving existing class/behavior.
- Add shared app typings in `src/types/app.ts` for projects/sessions/websocket/loading contracts used by new hooks/components.
- Add global window declarations in `src/types/global.d.ts` for `__ROUTER_BASENAME__`, `refreshProjects`, and `openSettings`, removing implicit `any` usage for global integration points.
- Update `src/main.jsx` to import `App.tsx` and keep app bootstrap consistent with the TS migration.
- Update `src/components/QuickSettingsPanel.jsx` to self-resolve mobile state via `useDeviceSettings` (remove `isMobile` prop dependency), and update `src/components/ChatInterface.jsx` to render `QuickSettingsPanel` directly.
This reduces prop drilling and keeps quick settings colocated with chat UI concerns.