Nexxus

Frontend DeveloperDesarrollador Frontend2025
ReactTypeScriptReact FlowZustandSSE

Nexxus is the network monitoring platform I work on at Osnet, a WISP in Colombia. It's a real-time operational workspace where NOC operators monitor 200+ network devices -- MikroTik routers, Ubiquiti and Cambium access points, HPE switches, Juniper gear -- all visualized on interactive maps with live status updates.

What it does

The core is a React Flow-based map editor. Each map shows network devices as nodes and their physical/wireless connections as edges. Operators can create multiple maps with nested sub-maps for different network segments, add text annotations with a Tiptap rich text editor, and navigate between levels.

Nexxus map workspace showing network devices, wireless links, and live status indicators
Main map workspace: devices, links, nested maps, and live status in one operational canvas

Devices are polled via SNMP/ICMP by the NestJS backend, and status changes push to the frontend through SSE streams -- one for device status, one for link status. The UI updates in real time without polling.

Nexxus device details panel showing monitoring data, metadata, and integration context
Device details: monitoring state and integration context without leaving the map
Nexxus access point clients modal showing connected clients and radio information
Cambium integration view: AP clients and radio context surfaced inside Nexxus
Nexxus traffic chart showing bandwidth utilization over time for network links
Traffic view: utilization trends used to understand link pressure without leaving the device context

Integrations

Osnet already had established tools for different parts of network management before Nexxus existed. Rather than asking operators to abandon them overnight, Nexxus bridges into these platforms -- surfacing their data in context, on the map. Most of these integrations are planned to be replaced by Nexxus-native features as the platform matures; for now, they let operators work from a single interface without a disruptive migration.

  • Cambium cnMaestro -- AP performance metrics, radio stats, client counts (OAuth2 proxy through Next.js API routes with automatic token refresh)
  • UISP/UNMS -- Ubiquiti device telemetry
  • Unimus -- config backup diffs and change tracking
  • Ubersmith -- ticketing integration (ticket badges render directly on device nodes)
  • LibreNMS -- extended monitoring data

Map UX details

The map is more than a simple graph viewer. Some of the operational features:

  • Level of Detail -- nodes render differently based on zoom: just a status dot at low zoom, icon + name at medium, full detail with IP, badges, integrations at high zoom
  • Context menus -- right-click on nodes, edges, labels, selections, or empty canvas each open different context menus with relevant actions
  • 8-direction edge handles -- edges connect from the optimal side of the node
  • Parallel edge offset -- multiple links between the same pair of devices spread out visually
  • Edge waypoints -- custom routing points for complex topologies
  • Traffic visualization -- edge color and thickness change based on bandwidth utilization
  • Sub-map connections -- map links connect sub-maps to each other at the parent level
  • Undo/redo -- full edit history in edit mode
  • Auto-layout -- grid, hierarchical, and force-directed layout algorithms
  • Search -- command palette for finding devices across maps
  • Alerts and channels -- configurable alert rules with notification channels (Teams, etc.)
  • Event log -- status change history for audit and troubleshooting
  • i18n -- full English/Spanish support via next-intl

The performance problem

When I joined the project, the map was slow. Frame drops during pan and zoom, visible lag on SSE events, and the UI choking as device count climbed past 100.

The team had started exploring a V3 map built with Konva (HTML5 Canvas) to replace React Flow, under the assumption that the rendering library was the bottleneck.

Profiling told a different story. React Flow was fine. The real problem was the state layer.

Every SSE event -- even a single device flipping from up to down -- triggered re-renders across the entire component tree. The Zustand stores weren't granular enough. State updates cascaded through shared selectors, so nodes that hadn't changed were still re-rendering.

The fix

The V2 map was restructured with a clear separation:

Refactored map layers
Map componentReact Flow rendering boundary
├── ViewModel layerstore → ReactFlow nodes/edges
│ ├── Granular node stateper-device selectors
│ └── Granular edge stateper-link selectors
├── Actions layerlayout, persistence, selection
│ ├── Layout actionsundo, redo, auto-layout
│ ├── Persistencesave positions to backend
│ └── Edge editingwaypoints, handles
└── Overlaysheaders, context menus, modals
├── Status bar
├── Context menus
└── Sidebars

The data store uses Map<string, T> for O(1) device lookups. Selectors subscribe to individual device IDs, so an SSE update for one device only re-renders that one node. The V3 Konva rewrite became unnecessary.

After the state refactoring, the map runs at consistent 60 FPS with 200+ devices. The rendering layer was always capable -- it just needed clean state.

Stack

Frontend: Next.js 14, React 18, TypeScript, React Flow, Zustand, TanStack Query, Tiptap, Framer Motion, next-intl, next-auth

Backend: NestJS, MongoDB, SNMP/ICMP polling, SSE streams

Nexxus es la plataforma de monitoreo de red en la que trabajo en Osnet, un WISP en Colombia. Es un espacio de trabajo operativo en tiempo real donde los operadores del NOC monitorean 200+ dispositivos de red -- routers MikroTik, access points Ubiquiti y Cambium, switches HPE, equipos Juniper -- todos visualizados en mapas interactivos con actualizaciones de estado en vivo.

Que hace

El nucleo es un editor de mapas basado en React Flow. Cada mapa muestra dispositivos de red como nodos y sus conexiones fisicas/inalambricas como aristas. Los operadores pueden crear multiples mapas con sub-mapas anidados para diferentes segmentos de red, agregar anotaciones de texto con un editor Tiptap, y navegar entre niveles.

Workspace de mapa de Nexxus mostrando dispositivos de red, enlaces wireless e indicadores de estado en vivo
Workspace principal del mapa: dispositivos, enlaces, sub-mapas y estado en vivo en un solo canvas operativo

Los dispositivos se consultan via SNMP/ICMP desde el backend NestJS, y los cambios de estado llegan al frontend a traves de streams SSE -- uno para estado de dispositivos, otro para estado de enlaces. La UI se actualiza en tiempo real sin polling.

Panel de detalles de dispositivo en Nexxus mostrando datos de monitoreo, metadata y contexto de integraciones
Detalle de dispositivo: estado de monitoreo y contexto de integraciones sin salir del mapa
Modal de clientes de access point en Nexxus mostrando clientes conectados e informacion de radio
Vista de integracion Cambium: clientes de AP y contexto de radio dentro de Nexxus
Grafica de trafico en Nexxus mostrando utilizacion de ancho de banda en el tiempo para enlaces de red
Vista de trafico: tendencias de utilizacion para entender presion sobre enlaces sin salir del contexto del dispositivo

Integraciones

Osnet ya tenia herramientas establecidas para distintas partes de la gestion de red antes de que existiera Nexxus. En lugar de pedirle a los operadores que las abandonaran de golpe, Nexxus se conecta a estas plataformas -- trayendo sus datos al contexto del mapa. La mayoria de estas integraciones estan planificadas para ser reemplazadas por funcionalidades propias de Nexxus a medida que la plataforma madura; por ahora, permiten trabajar desde una sola interfaz sin una migracion disruptiva.

  • Cambium cnMaestro -- metricas de rendimiento de APs, stats de radio, conteo de clientes (proxy OAuth2 a traves de rutas API de Next.js con refresh automatico de tokens)
  • UISP/UNMS -- telemetria de dispositivos Ubiquiti
  • Unimus -- diffs de backups de configuracion y tracking de cambios
  • Ubersmith -- integracion de tickets (badges de tickets se renderizan directamente sobre los nodos de dispositivos)
  • LibreNMS -- datos extendidos de monitoreo

Detalles de UX del mapa

El mapa es mas que un visor de grafos simple. Algunas de las funcionalidades operativas:

  • Nivel de detalle -- los nodos se renderizan diferente segun el zoom: solo un punto de estado en zoom bajo, icono + nombre en medio, detalle completo con IP, badges, integraciones en zoom alto
  • Menus contextuales -- click derecho en nodos, aristas, etiquetas, selecciones, o canvas vacio abre diferentes menus con acciones relevantes
  • Handles de aristas en 8 direcciones -- las aristas se conectan desde el lado optimo del nodo
  • Offset de aristas paralelas -- multiples enlaces entre el mismo par de dispositivos se separan visualmente
  • Waypoints de aristas -- puntos de ruteo personalizados para topologias complejas
  • Visualizacion de trafico -- el color y grosor de las aristas cambian segun la utilizacion de ancho de banda
  • Conexiones entre sub-mapas -- enlaces que conectan sub-mapas entre si a nivel del mapa padre
  • Deshacer/rehacer -- historial completo de edicion en modo edicion
  • Auto-layout -- algoritmos de layout en grilla, jerarquico y dirigido por fuerzas
  • Busqueda -- paleta de comandos para encontrar dispositivos a traves de mapas
  • Alertas y canales -- reglas de alerta configurables con canales de notificacion (Teams, etc.)
  • Log de eventos -- historial de cambios de estado para auditoria y troubleshooting
  • i18n -- soporte completo ingles/español via next-intl

El problema de rendimiento

Cuando me uni al proyecto, el mapa era lento. Caidas de frames durante pan y zoom, lag visible en eventos SSE, y la UI se ahogaba cuando los dispositivos superaban los 100.

El equipo habia comenzado a explorar un mapa V3 construido con Konva (HTML5 Canvas) para reemplazar React Flow, bajo la suposicion de que la libreria de renderizado era el cuello de botella.

El profiling conto una historia diferente. React Flow estaba bien. El problema real era la capa de estado.

Cada evento SSE -- incluso un solo dispositivo pasando de up a down -- disparaba re-renders en todo el arbol de componentes. Las stores de Zustand no eran suficientemente granulares. Las actualizaciones de estado se propagaban a traves de selectores compartidos, asi que nodos que no habian cambiado igual se re-renderizaban.

La solucion

El mapa V2 fue reestructurado con una separacion clara:

Capas del mapa refactorizado
Componente Mapalimite de render React Flow
├── Capa ViewModelstore a nodos/aristas ReactFlow
│ ├── Estado granular de nodosselectores por dispositivo
│ └── Estado granular de aristasselectores por enlace
├── Capa de accioneslayout, persistencia, seleccion
│ ├── Acciones de layoutdeshacer, rehacer, auto-layout
│ ├── Persistenciaguarda posiciones al backend
│ └── Edicion de aristaswaypoints, handles
└── Overlaysheaders, menus contextuales, modales
├── Barra de estado
├── Menus contextuales
└── Sidebars

El store de datos usa Map<string, T> para busquedas O(1) de dispositivos. Los selectores se suscriben a IDs individuales de dispositivos, asi que una actualizacion SSE para un dispositivo solo re-renderiza ese nodo. La reescritura V3 con Konva se volvio innecesaria.

Despues de la refactorizacion de estado, el mapa corre a 60 FPS consistentes con 200+ dispositivos. La capa de renderizado siempre fue capaz -- solo necesitaba estado limpio.

Stack

Frontend: Next.js 14, React 18, TypeScript, React Flow, Zustand, TanStack Query, Tiptap, Framer Motion, next-intl, next-auth

Backend: NestJS, MongoDB, polling SNMP/ICMP, streams SSE