CXB Console is a single-page React app. src/App.tsx owns the route tree, wraps everything in the auth and toast providers, and lazy-loads every page so the initial bundle stays small.

Provider Stack

App.tsx mounts three nested providers around the router:
  • AuthProvider (src/auth/AuthContext.tsx) holds the JWT token, the current user, and role booleans.
  • ToastProvider (src/components/Toast.tsx) supplies the useToast() notification helper used across pages.
  • Suspense shows RouteFallback (a simple “Loading…” div) while a lazy page chunk is fetched.

Two Layouts, Two Audiences

There are two top-level protected branches, each behind ProtectedRoute with a roles allow-list and rendering a distinct layout via <Outlet />.
BranchLayout fileAllowed rolesPurpose
/dashboard/*src/layouts/DashboardLayout.tsxadmin, super_adminAdmin/operator console
/agent-console/*src/layouts/AgentLayout.tsxagent, supervisorAgent Desk handling surface
A catch-all path="*" renders RoleRedirect, which sends agents/supervisors to /agent-console (when ADK is on) and everyone else to /dashboard.

Dashboard Routes

All children of /dashboard are nested routes rendered inside DashboardLayout.
RoutePage componentFile
/dashboard (index)Overviewsrc/pages/Overview.tsx
/dashboard/botsBotListsrc/pages/BotList.tsx
/dashboard/bots/createBotCreatesrc/pages/BotCreate.tsx
/dashboard/bots/:idBotDetailsrc/pages/BotDetail.tsx
/dashboard/knowledge-basesKnowledgeBasessrc/pages/KnowledgeBases.tsx
/dashboard/knowledge-bases/:idKnowledgeBaseDetailsrc/pages/KnowledgeBaseDetail.tsx
/dashboard/callsCallListsrc/pages/CallList.tsx
/dashboard/calls/:idCallDetailsrc/pages/CallDetail.tsx
/dashboard/campaignsCampaignssrc/pages/Campaigns.tsx
/dashboard/campaigns/new, /dashboard/campaigns/:id/editCampaignCreatesrc/pages/CampaignCreate.tsx
/dashboard/campaigns/:idCampaignDetailsrc/pages/CampaignDetail.tsx
/dashboard/carriersCarrierListsrc/pages/CarrierList.tsx
/dashboard/carriers/createCarrierCreatesrc/pages/CarrierCreate.tsx
/dashboard/carriers/exotelExotelDetailsrc/pages/ExotelDetail.tsx
/dashboard/carriers/:idCarrierDetailsrc/pages/CarrierDetail.tsx
/dashboard/fleetFleetsrc/pages/Fleet.tsx
/dashboard/api-keysApiKeyssrc/pages/ApiKeys.tsx
/dashboard/changelogChangeLogsrc/pages/ChangeLog.tsx
/dashboard/settingsSettingssrc/pages/Settings.tsx
/dashboard/usersUserssrc/pages/Users.tsx
/dashboard/agent-deskAgentDeskMetricssrc/pages/AgentDeskMetrics.tsx
/dashboard/agent-assistAgentAssistMomentssrc/pages/AgentAssistMoments.tsx
The agent-desk and agent-assist dashboard routes are only registered when the ADK flag is true (see below).

Agent Console Routes

The entire /agent-console branch is registered only when ADK is true.
RoutePage componentFile
/agent-console (index)AgentQueue (imported as AgentHome)src/pages/AgentQueue.tsx
/agent-console/analyticsAgentAnalyticssrc/pages/AgentAnalytics.tsx
/agent-console/callAgentCallsrc/pages/AgentCall.tsx
/agent-console/historyAgentHistorysrc/pages/AgentHistory.tsx
/agent-console/calls/:idCallDetailsrc/pages/CallDetail.tsx
/agent-console/agentsSupervisorDashboardsrc/pages/SupervisorDashboard.tsx
/agent-console/assistAgentAssistMomentssrc/pages/AgentAssistMoments.tsx
CallDetail is shared between dashboard and agent console. It branches on location.pathname: under /agent-console it loads from /api/v1/agent-desk/calls/:id and hides the admin-only raw JSON export.

Role Gating

DashboardLayout builds its sidebar from a navSections array. Each item can declare superAdmin or gated flags:
  • superAdmin: true items (Carriers, Settings) are only shown when user.role === 'super_admin'.
  • gated: true items (Agent Desk, Agent Assist) are only shown when ADK is true.
AgentLayout filters its navItems by a supervisorOnly flag, so agents see Home/Analytics/My History while supervisors additionally get Agent Overview and Agent Assist. ProtectedRoute (src/auth/ProtectedRoute.tsx) enforces the same boundaries at the route level: while auth is loading it shows a spinner; with no token it redirects to /login; and when the user’s role is not in the route’s roles list it redirects to the role’s home surface.

The ADK Feature Flag

src/tier.ts derives a single boolean ADK by hashing the lowercased BRAND_NAME (FNV-1a) against a fixed allow-list. When false, the Agent Desk / Agent Console routes and nav items are never registered. This keeps Agent Desk out of brands that have not licensed it, without per-brand source changes.

Lazy Loading

Every page and both layouts are wrapped in React.lazy(() => import(...)). Route transitions therefore fetch the page chunk on demand, falling back to RouteFallback during load.

API Client & Auth

JWT injection, 401 handling, and ProtectedRoute internals.

Design System

Shared UI primitives, DataTable, and form patterns.

White-Label Build

Brand config, CSS-var injection, and the ADK gate.

CXB Console Overview

Product role and main workflows.