Nexivo Admin Portal¶
The Nexivo Admin Portal is the super-admin web application for managing the entire Nexivo omnichannel contact centre platform. It is used by platform administrators and tenant managers to configure AI agents, channels, workflows, knowledge bases, campaigns, reporting, and user roles.
Source
VSCodeProjects/Nexivo/nexivo-admin — React 18 / TypeScript / Vite SPA
Tech Stack¶
| Layer | Technology |
|---|---|
| Framework | React 18.3 + TypeScript 5.6 |
| Build | Vite 6 |
| Routing | React Router DOM 7 |
| State | Redux Toolkit 2.5 + Redux Persist |
| Auth | Keycloak JS 26 (PKCE flow) |
| UI components | Fluent UI React 8 + Fluent UI v9 + Ant Design 5 |
| Styling | Tailwind CSS 3.4 |
| Forms | React Hook Form 7 + Zod 4 validation |
| Charts | ApexCharts · Google Charts · Recharts |
| Workflow editor | @xyflow/react 12 (React Flow) |
| Rich text | React Quill (Quill.js) |
| HTTP | Axios 1.7 |
| Real-time | react-use-websocket + RxJS 7 |
| Media | HLS.js 1.6 + custom cc-audio-player |
| Maps | Leaflet 1.9 + React Leaflet 4 |
| Animations | Framer Motion 12 |
| DI | Inversify React 1.2 |
Authentication¶
Authentication is handled entirely by Keycloak using the PKCE flow.
Initialisation¶
On app load AuthContext (src/context/authContex.tsx) initialises Keycloak and silently logs the user in. Once authenticated:
- Axios
apiConnectorandadminConnectorhave theAuthorization: Bearer <token>header injected automatically. - Token refresh runs every 30 seconds; a refresh is forced when less than 70 seconds of validity remain.
- On expiry, the user is redirected to the Keycloak logout endpoint.
Tenant & licence extraction¶
The JWT contains an organization object. Two hooks abstract this:
const { hasLicense, hasResourceAccess } = useAuthContext()
const getTenantId = useAuthTenant() // memoised extraction from token
hasLicense(license) checks token.organization.licenses[]; hasResourceAccess(resource) checks Keycloak client roles. Both are used by LicenseGuard to gate routes and UI elements.
Environment variables¶
| Variable | Purpose |
|---|---|
VITE_KEYCLOAK_BASE_URL |
Keycloak server URL |
VITE_KEYCLOAK_REALM |
Realm name |
VITE_KEYCLOAK_CLIENT_ID |
OAuth client ID |
VITE_API_BASE_URL |
Backend API base URL |
VITE_KNOWLEDGE_TENANT_ID |
Fallback tenant ID |
Architecture¶
graph TD
Browser -->|PKCE login| Keycloak
Browser -->|REST / Axios| API[Platform API]
Browser -->|WebSocket| WS[Live Updates]
Browser -->|HLS| Media[Media Server]
subgraph SPA[Nexivo Admin SPA]
Router[React Router v7] --> ProtectedLayout
ProtectedLayout --> Pages
Pages --> Services[45 Service Files]
Pages --> Redux[Redux Store]
Pages --> Contexts[Context Providers]
end
All routes are wrapped in ProtectedLayout, which enforces authentication. LicenseGuard then provides per-route licence enforcement on top.
Pages & Features¶
Dashboards¶
| Route | Page | Key features |
|---|---|---|
/dashboards/overview |
Overview Dashboard | Drag-drop widget grid; KPI cards; call trends; team/agent/queue widgets; layout persisted to Redux + localStorage |
/dashboards/ai |
AI Analytics | Model usage; token consumption; AI conversation quality metrics |
/dashboards/service-level |
Service Level | SLA compliance; wait-time analysis; SLO visualisation |
/dashboards/live-queue |
Live Queue | Real-time queue depth; agent availability; WebSocket-based live updates |
Dashboard layouts are stored in overviewLayoutSlice / aiOverviewLayoutSlice Redux slices and persisted across sessions via redux-persist.
AI Agents¶
Route group: /ai-agents — licence-gated to AI_AGENT.
Agent gallery¶
- Lists all agents with status badges: Active · Inactive · Provisioning · Failed
- Quick actions: edit, view, duplicate, delete
- Avatar display with fallback initials
Create / Edit agent (multi-step wizard)¶
Step 1 — Basic info name · greeting · language · direction (inbound/outbound)
Step 2 — Personality system prompt (rich text) · model provider selection
Step 3 — Execution concurrency · timeout · runtime settings
Step 4 — Knowledge base KB category assignment (modal picker)
Step 5 — Tasks workflow task list · execution order
Agent creation requires the AI_AGENT_CREATOR licence. The final POST /tenants/{id}/agents payload is assembled from all wizard steps.
Key model:
interface AIAgentItem {
agent_id: string
agent_name: string
agent_prompt: string
base_greeting: string
status: 'active' | 'inactive' | 'provisioning' | 'failed'
agent_type: 'inbound' | 'outbound'
agent_category: 'ai_ivr' | 'ai_agent' | 'human_agent'
language: string | string[]
metadata: {
avatar_url?: string
tools?: string[]
teams?: string[]
outbound_variables?: Record<string, string>
}
config_version: number
}
Background Agents¶
Separate agent type for non-voice, autonomous background task execution. Managed under /background-agents with its own create/edit flow and background-agent.service.ts.
Knowledge Base¶
Route group: /knowledge-base
| Route | Purpose |
|---|---|
/knowledge-base |
Gallery — filter by status, template, agent |
/knowledge-base/create |
Create KB (blank or from template) |
/knowledge-base/:id |
Browse categories & articles |
/knowledge-base/articles |
Article list with rich-text preview |
/knowledge-base/article/create |
Create article (Quill editor) |
/knowledge-base/templates |
Pre-built KB structure templates |
/knowledge-base/search |
Semantic search (licence: KB_SEARCH) |
Data shape:
interface KnowledgeBase {
knowledge_base_id: string
agent_id?: string // optional agent association
template_id?: string
name: string
description: string
status: 'active' | 'inactive' | 'archived'
category_count: number
article_count: number
}
Articles are written in the Quill rich-text editor and stored as HTML. Templates provide a hierarchical category+article scaffold that can be imported into a new KB.
Workflows¶
Route group: /workflow
The workflow editor is built on @xyflow/react (React Flow), providing a drag-drop visual IVR/routing flow builder.
Node types¶
| Node | Purpose |
|---|---|
| AI Agent | Route caller to a configured AI agent |
| Transfer | Transfer to human agent / team |
| Menu | DTMF menu selection |
| Condition | Branch on call metadata or variable |
| Wait | Introduce delay |
| API Call | Trigger external webhook |
Edges carry routing conditions; the full flow is serialised as workflow_json and sent to POST /workflows.
Demo workflows (read-only templates)¶
- Trading Agent · Trader Agent · Insurance Agent · Appointment Booking · Multi-Agent Orchestration
Execution profiles (ExecutionProfile) define runtime constraints (concurrency limits, timeouts) and are assigned to workflows at save time.
Channels¶
Phone Numbers (/phone-numbers)¶
- Provision new numbers from the marketplace (
POST /numbers/buy) - Configure existing numbers: inbound routing, capacity/concurrency limits
WhatsApp (/whatsapp)¶
- WhatsApp Business API integration configuration
- Managed via
whatsapp.service.ts
Email (/email)¶
- Email channel setup and routing configuration
Chat Widgets (/widgets)¶
- Create embeddable chat/call widgets for web properties
- Configurable branding, routing, and queue assignment
App Connectors (/app-connectors)¶
- Create connections to external systems (CRM, EHR, REST APIs)
- Tool creation: define input schemas and outbound HTTP call mapping
- Integrates with the App Connect service
Contacts & Lists¶
Contacts (/contacts)¶
- Full directory: search, filter by type/tag/team
- Create/edit with custom properties, tags, CRM link (
cxConnectionId) - Supports CSV import (tracked via
CsvImportJobContext)
Contact model:
interface Contact {
id: string
firstName: string
lastName: string
email?: string
phoneNumber?: string
whatsappNumber?: string
address?: { country; city; postalCode; coordinates }
tags: Tag[]
properties: Record<string, any>
teams?: string[]
cxConnectionId?: string // CRM integration link
languages?: string[]
}
Contact Lists (/contact-lists)¶
- Named segments used as campaign targets
- Bulk import from CSV
- Displays member count and last-updated metadata
Campaigns¶
Route group: /campaigns · /scheduled-calls
Campaigns¶
- Multi-channel: Voice, WhatsApp, Email
- Target a contact list with optional filter criteria
- Configure: calling hours · retry attempts · concurrency · script/template
- Route to: role · AI agent · team
Scheduled Calls¶
- Automated outbound call scheduling
- Frequency options: one-time · daily · weekly · custom
- Do-not-call compliance rules
- Outbound trunk assignment
Calls & Transcripts¶
Call list (/calls)¶
- Sortable/filterable: direction, duration, status, outcome, disposition
- Quick-access: notes · AI summary · transcript · structured JSON view
AI Summary (/calls/:callId/ai-summary)¶
interface AISummaryDto {
mainReason: string
summary: string
resolutionStatus: 'RESOLVED' | 'NOT_RESOLVED' | 'CALLBACK'
takeaways: string[]
topics: string[]
followUpActions: string[]
sentimentAnalysis: {
callScore: number
customerSentiment: string
emotionAnalysis: string
}
emailStatus: 'sent' | 'failed' | 'sending'
}
Transcript (/calls/:callId/transcript)¶
- Participant-identified segments with timing offsets
- Per-statement sentiment scores (negative · neutral · positive · compound)
Call notes (/calls/:callId/notes)¶
- Rich-text note editor (Quill)
- AI-generated note suggestions when enabled
Call quality (/call-quality)¶
- Quality scoring and analytics for AI agent performance
Message & Clinical Templates¶
| Section | Route | Purpose |
|---|---|---|
| Message Templates | /message-templates |
Reusable multi-channel message templates with variable substitution |
| Clinical Templates | /clinical-templates |
Healthcare-specific message templates |
Teams & Roles¶
| Section | Purpose |
|---|---|
/teams |
Create teams; assign members, skills, availability schedules |
/roles |
Assign Keycloak roles to human agents; manage user-role bindings |
/skill-templates |
Define skill sets that can be attached to agents |
Settings¶
| Route | Purpose |
|---|---|
/settings |
Organisation-level preferences and branding |
/settings/disposition |
Call outcome code configuration and AI auto-tagging thresholds |
/direct-routes |
Direct number-to-destination routing rules |
/outbound-trunks |
SIP trunk management for outbound calls |
Analytics & Reporting¶
| Route | Purpose |
|---|---|
/dashboards/service-level |
SLA compliance dashboard |
/ai-insights |
AI agent performance and conversation analytics |
/opportunities |
Sales/conversion opportunity tracking |
Full report generation (XLSX/CSV/PDF export, 29 report types) is handled by the Reporting Service; nexivo-admin triggers report requests through reports.service.ts.
State Management¶
Redux store (src/store/index.ts)¶
| Slice | What it holds |
|---|---|
overviewLayoutSlice |
Overview dashboard widget grid positions (persisted) |
aiOverviewLayoutSlice |
AI dashboard widget grid positions (persisted) |
filterDataSlice |
Shared date range, search, and status filter state |
confirmModal |
Generic confirm/cancel modal visibility and callbacks |
Redux Persist serialises overviewLayoutSlice and aiOverviewLayoutSlice to localStorage so dashboard customisations survive page reload.
Context providers¶
| Context | Purpose |
|---|---|
AuthContext |
Keycloak instance; hasLicense; hasResourceAccess; org metadata |
ThemeContext |
Light / dark theme |
AgentStatusContext |
Real-time human agent availability (SSE / WebSocket) |
LiveQueueWaitingContext |
Real-time queue depth and wait-time metrics |
CsvImportJobContext |
CSV import progress tracking for contacts / contact lists |
AIDashboardContext |
AI dashboard date/filter state |
OverviewDashboardContext |
Overview dashboard state |
Services¶
All 45 service files in src/services/ use an Axios-based apiConnector (or adminConnector for Keycloak Admin API calls). The base URL is VITE_API_BASE_URL.
Error handling is centralised in createAPIError, which transforms Axios errors into APIError objects with an intent field (info | warning | error | success) consumed by the global toast notification system.
Key services and their primary endpoints:
| Service file | Primary endpoint | Purpose |
|---|---|---|
ai-agent.service.ts |
/tenants/{id}/agents |
AI agent CRUD + avatar URL resolution |
calls.service.ts |
/calls |
Call history, disposition, notes, transcription, summaries |
workflow.service.ts |
/workflows |
Workflow CRUD + execution profile management |
knowledge-base.service.ts |
/knowledge-bases |
KB + article + category management |
campaign.service.ts |
/campaigns |
Campaign CRUD, targeting, scheduling |
contact.service.ts |
/contacts |
Contact CRUD, custom properties, CRM sync |
phone-number.service.ts |
/phone-numbers |
Provisioning and routing configuration |
live-queue.service.ts |
/live-queue |
Real-time queue metrics |
reports.service.ts |
/reports |
Report generation and export |
keycloak.service.ts |
Keycloak Admin API | User + role management |
app-connect.service.ts |
/app-connections |
External API tool/webhook integrations |
Licence Gating¶
Feature licences are embedded in the Keycloak JWT under token.organization.licenses[]. LicenseGuard wraps any route or component that requires a specific licence:
Known licence constants (from src/config/licenses.ts):
| Constant | Feature |
|---|---|
AI_AGENT |
Access AI Agents gallery and features |
AI_AGENT_CREATOR |
Create / edit AI agents |
KB_SEARCH |
Semantic knowledge base search |
Key Components¶
React Flow Workflow Builder (src/components/ReactFlowBuilder/)¶
Visual IVR/routing editor — drag-drop nodes, conditional edges, execution profile assignment, undo/redo, JSON import/export.
Data Table (src/components/DataTable/)¶
Reusable sortable/filterable data grid with column-visibility toggling, inline row actions, pagination, status badges, and avatar support.
Rich Text Editor (src/components/Form/RichText/)¶
React Quill wrapper used for AI agent prompts, KB articles, and call notes.
HLS Audio Player¶
Embeds hls.js for call recording playback directly in the call detail view.
Dashboard Widget System (src/components/dashboards/gadget/)¶
React Grid Layout-based drag-drop widgets. New widget types can be added by implementing the widget interface and registering in the widget catalogue.