-
Notifications
You must be signed in to change notification settings - Fork 0
Routing & Navigation
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
This document explains the KAIROS MCP UI routing and navigation system. It covers route-level code splitting using React.lazy and Suspense for performance, the route tree and nested routing patterns, BrowserRouter configuration with a basename, dynamic routing via parameters, fallback loading states, navigation flows between pages, and guidance for adding new routes while preserving maintainability.
The routing is implemented in the UI layer under src/ui. The main entry initializes providers and mounts the router. The App component defines the route tree and wraps each page in Suspense for lazy loading. The Layout component provides a shared shell with persistent sidebar navigation and renders child routes via Outlet.
graph TB
Main["main.tsx<br/>Providers + Root"] --> App["App.tsx<br/>BrowserRouter + AppRoutes"]
App --> Layout["Layout.tsx<br/>Sidebar + Outlet"]
Layout --> Routes["Nested Routes<br/>Index/Home /Kairos /Runs /Protocols/*"]
Routes --> Pages["Lazy-loaded Page Components"]
Pages --> |Suspense fallback| Fallback["RouteFallback()"]
Diagram sources
- src/ui/main.tsx:11-19
- src/ui/App.tsx:126-132
- src/ui/App.tsx:37-124
- src/ui/components/Layout.tsx:11-108
Section sources
- src/ui/main.tsx:1-20
- src/ui/App.tsx:126-132
- src/ui/components/Layout.tsx:11-108
- BrowserRouter with basename "/ui": Ensures all client-side routes are prefixed under /ui, aligning with backend static serving expectations.
- AppRoutes: Declares the route tree with nested routes inside Layout.
- Lazy-loaded pages: Each page is imported on-demand using React.lazy and wrapped in Suspense for fallback rendering.
- RouteFallback: Centralized loading indicator for lazy chunks.
- Layout: Provides persistent navigation and renders child routes via Outlet.
Section sources
- src/ui/App.tsx:5-26
- src/ui/App.tsx:28-34
- src/ui/App.tsx:37-124
- src/ui/App.tsx:126-132
- src/ui/components/Layout.tsx:11-108
The routing architecture uses a single route tree with nested routes under a shared layout. Dynamic segments power protocol-centric views, and the basename ensures compatibility with reverse proxies and backend routing.
graph TB
subgraph "Router"
BR["BrowserRouter<br/>basename='/ui'"]
AR["AppRoutes"]
end
subgraph "Layout Shell"
L["Layout"]
NAV["Navigation Links"]
end
subgraph "Routes"
R1["/ → HomePage"]
R2["/kairos → KairosPage"]
R3["/runs → RunsPage"]
R4["/protocols/new → ProtocolEditPage (new)"]
R5["/protocols/:uri/edit → ProtocolEditPage (edit)"]
R6["/protocols/:uri → ProtocolDetailPage"]
R7["/protocols/:uri/run → RunGuidedPage"]
R8["/protocols/:uri/skill → SkillBundlePage"]
R9["/account → AccountPage"]
R10["* → NotFoundPage"]
end
BR --> AR --> L
L --> NAV
L --> R1
L --> R2
L --> R3
L --> R4
L --> R5
L --> R6
L --> R7
L --> R8
L --> R9
L --> R10
Diagram sources
- src/ui/App.tsx:126-132
- src/ui/App.tsx:37-124
- src/ui/components/Layout.tsx:58-90
- Root route "/" renders HomePage inside Layout.
- "/kairos" renders Kairos-related content (implemented in KairosPage).
- "/runs" renders RunsPage with saved run sessions.
- "/protocols/new" renders ProtocolEditPage for creating new protocols.
- "/protocols/:uri/edit" renders ProtocolEditPage for editing existing protocols.
- "/protocols/:uri" renders ProtocolDetailPage for viewing protocol details.
- "/protocols/:uri/run" renders RunGuidedPage for guided runs.
- "/protocols/:uri/skill" renders SkillBundlePage for skill bundle actions.
- "/account" renders AccountPage.
- Wildcard "*" renders NotFoundPage.
Dynamic segment ":uri" carries protocol identifiers across multiple routes, enabling deep linking and navigation between protocol-centric views.
Section sources
- src/ui/App.tsx:37-124
Each page component is imported lazily and wrapped in Suspense with a shared fallback. This keeps the initial bundle small and defers loading of less-frequently visited pages until navigation occurs.
sequenceDiagram
participant U as "User"
participant BR as "BrowserRouter('/ui')"
participant AR as "AppRoutes"
participant S as "Suspense"
participant P as "Lazy Page Component"
U->>BR : Navigate to "/protocols/ : uri"
BR->>AR : Match route
AR->>S : Render with fallback
S->>P : Import on demand
P-->>S : Resolve default export
S-->>U : Render page content
Diagram sources
- src/ui/App.tsx:5-26
- src/ui/App.tsx:28-34
- src/ui/App.tsx:37-124
Section sources
- src/ui/App.tsx:5-26
- src/ui/App.tsx:28-34
- BrowserRouter is configured with basename "/ui". All internal links and navigation should be relative to this base.
- Layout provides NavLink-based navigation for primary sections (Home, Kairos, Create, Runs, Account).
- Many page components construct URLs using template literals with encodeURIComponent to safely encode dynamic segments like ":uri".
Examples of navigation patterns:
- From HomePage to Kairos search with query params.
- From ProtocolDetailPage to run/edit/skill routes using ":uri".
- From RunsPage to resume a run with a session query param.
- From Kairos results to ProtocolDetailPage using ":uri".
Section sources
- src/ui/App.tsx:126-132
- src/ui/components/Layout.tsx:58-90
- src/ui/pages/HomePage.tsx:15-20
- src/ui/pages/ProtocolDetailPage.tsx:94-105
- src/ui/pages/RunsPage.tsx:35-40
- src/ui/pages/kairos-page-sections.tsx:101-107
- ":uri" is a dynamic segment used across protocol routes. Components decode the parameter and use it to fetch data or construct further links.
- RunGuidedPage also reads a "session" query parameter to restore an existing run session.
Common patterns:
- Decoding ":uri" before use.
- Using useNavigate/useSearchParams to pass state via URL.
- Constructing links with proper encoding for special characters.
Section sources
- src/ui/App.tsx:74-82
- src/ui/pages/ProtocolDetailPage.tsx:18-20
- src/ui/pages/RunGuidedPage.tsx:26-31
- RouteFallback provides a consistent loading indicator during lazy imports.
- Individual pages may render loading placeholders while fetching data (e.g., ProtocolDetailPage, ProtocolEditPage, RunsPage).
flowchart TD
Start(["Route Enter"]) --> Check["Is Page Chunk Loaded?"]
Check --> |No| ShowFallback["Show RouteFallback()"]
Check --> |Yes| RenderPage["Render Page Component"]
ShowFallback --> Wait["Chunk Load Complete"]
Wait --> RenderPage
Diagram sources
- src/ui/App.tsx:28-34
- src/ui/App.tsx:44-46
Section sources
- src/ui/App.tsx:28-34
- src/ui/pages/ProtocolDetailPage.tsx:24-29
- src/ui/pages/RunsPage.tsx:6-8
The typical flow:
- Home: Search or quick links to Kairos browse, Create, or Runs.
- Kairos: Browse or refine search; select a protocol to view details.
- ProtocolDetail: Actions to run, edit, duplicate, or download skill bundle.
- RunGuided: Guided execution with start, step submission, and reward.
- Runs: Resume or remove previous sessions.
- Account: View profile and theme preferences.
sequenceDiagram
participant H as "HomePage"
participant K as "KairosPage"
participant PD as "ProtocolDetailPage"
participant PG as "RunGuidedPage"
participant RP as "RunsPage"
participant AC as "AccountPage"
H->>K : "Search or Browse"
K->>PD : "View Protocol"
PD->>PG : "Run Guided"
PG-->>RP : "Resume Later"
RP-->>PG : "Continue Session"
H->>AC : "Account"
Diagram sources
- src/ui/pages/HomePage.tsx:56-90
- src/ui/pages/kairos-page-sections.tsx:187-211
- src/ui/pages/ProtocolDetailPage.tsx:94-105
- src/ui/pages/RunGuidedPage.tsx:56-81
- src/ui/pages/RunsPage.tsx:35-40
- src/ui/pages/AccountPage.tsx:24-48
Section sources
- src/ui/pages/HomePage.tsx:56-90
- src/ui/pages/kairos-page-sections.tsx:187-211
- src/ui/pages/ProtocolDetailPage.tsx:94-105
- src/ui/pages/RunGuidedPage.tsx:56-81
- src/ui/pages/RunsPage.tsx:35-40
- src/ui/pages/AccountPage.tsx:24-48
- Authentication state is surfaced in AccountPage (signed-in vs anonymous).
- Authentication callbacks and logout links are present in AccountPage.
- No explicit route guard logic is implemented in the routing layer itself; authentication checks are typically handled by hooks and page components.
Recommendation:
- Add a higher-order wrapper around lazy components to check auth state before rendering.
- Alternatively, enforce guards at the component level using redirect logic when unauthenticated.
Section sources
- src/ui/pages/AccountPage.tsx:24-48
Steps to add a new route:
- Create a new page component under src/ui/pages/.
- Import the component lazily in App.tsx and wrap it in Suspense with RouteFallback.
- Add a new Route under the Layout in App.tsx with appropriate path and parameter segments.
- Update Layout navigation (optional) to include a link to the new route.
- Ensure any dynamic parameters are decoded and sanitized before use.
- Verify basename "/ui" compatibility for internal links.
Best practices:
- Keep route paths concise and hierarchical.
- Use consistent parameter naming (e.g., ":uri").
- Centralize fallback UI in RouteFallback.
- Prefer relative links within the app; absolute links should respect the basename.
Section sources
- src/ui/App.tsx:5-26
- src/ui/App.tsx:37-124
- src/ui/components/Layout.tsx:58-90
The routing layer depends on:
- react-router-dom for routing primitives (BrowserRouter, Routes, Route, Outlet, NavLink, useNavigate, useLocation, useSearchParams, useParams).
- Internal page components and shared layout.
- Suspense and lazy for code splitting.
graph LR
RR["react-router-dom"] --> APP["App.tsx"]
APP --> LYT["Layout.tsx"]
APP --> PAGES["Page Components"]
LYT --> NAV["NavLink / useLocation"]
PAGES --> ROUTES["Route Definitions"]
Diagram sources
- src/ui/App.tsx:1-3
- src/ui/components/Layout.tsx:1-3
Section sources
- src/ui/App.tsx:1-3
- src/ui/components/Layout.tsx:1-3
- Route-level code splitting reduces initial bundle size by deferring page loads until navigation.
- Suspense fallback prevents blank screen while chunks are loading.
- Keep lazy imports granular; avoid overly large lazy boundaries.
- Minimize heavy work in route components during initial render; defer to effects or lazy initialization.
[No sources needed since this section provides general guidance]
Common issues and resolutions:
- Blank screen on navigation: Verify Suspense fallback is present and lazy imports resolve correctly.
- 404 after refresh: Confirm BrowserRouter basename "/ui" matches backend static serving and that links use relative paths.
- Broken dynamic links: Ensure ":uri" parameters are encoded/decoded properly when constructing or parsing URLs.
- Navigation not updating active state: Check NavLink end and aria-current attributes in Layout.
Section sources
- src/ui/App.tsx:28-34
- src/ui/App.tsx:126-132
- src/ui/pages/ProtocolDetailPage.tsx:18-20
- src/ui/components/Layout.tsx:58-90
The routing system leverages React Router with route-level code splitting to optimize performance, a shared Layout for consistent navigation, and a clear route tree with dynamic segments for protocol-centric workflows. By following the established patterns for lazy loading, basename usage, and parameter handling, new features can be integrated efficiently while maintaining a predictable and scalable structure.