Humbolt MVP

HumboltTracking · ERP de Logística

Humbolt MVP

ERP de logística multi-rol: cuatro portales sobre una misma API, del despacho en oficina al escaneo del paquete en la calle.

Software empresarial2026MVP

Desarrollo frontend completo: arquitectura de portales por rol, capa de servicios generada desde OpenAPI, integración con API REST/WebSocket y portal operador móvil

Pedir un recorrido guiadoAplicación interna: sin acceso público
M-01Dashboard
M-02Usuarios
M-03Clientes
M-04Destinatarios
M-05Tipos de Destino
M-06Choferes
M-07Envíos
M-08Rutas

100%

Trazabilidad

24/7

Monitoreo

Aplicación web empresarial / ERP de logística y última milla2026

Humbolt MVP —la marca dentro de la interfaz es “HumboltTracking · ERP de Logística”— es una aplicación web React/TypeScript que cubre el ciclo completo de un envío: alta del cliente y del destinatario, creación del envío, generación de la etiqueta con QR, armado de la ruta, escaneo del paquete en cada parada y cierre de la ruta.

Una sola build sirve a cinco roles (`super_admin`, `admin`, `operator`, `client_master`, `client_agency`). El componente raíz `src/app/App.tsx` lee el usuario autenticado, lo mapea a un rol de aplicación y monta uno de cuatro portales distintos: portal supervisor de escritorio, portal operador pensado para el móvil del chofer, portal de cliente master y portal de agencia cliente.

El proyecto arrancó como un bundle de código exportado de Figma Make (el README apunta al archivo original y `ATTRIBUTIONS.md` acredita a shadcn/ui). El trabajo posterior fue sustituir los datos simulados por la API real: un script propio, `gen_services.py`, descarga el `openapi.json` del backend y genera `src/services/types.ts` (98 interfaces y tipos) más los quince servicios que consumen 45 rutas entre REST y WebSocket.

El portal operador es el corazón operativo: obliga a un orden de trabajo —primero foto de evidencia subida al servidor, después escaneo del QR del mismo paquete— usando la cámara trasera del teléfono con `html5-qrcode` y `getUserMedia`, con registro manual de código y peso como respaldo cuando el escáner no lee.

Estado del proyecto

MVP funcional conectado a la API de producción (axiomcoretech.store); build publicado bajo la ruta base /humbolt/, con módulos de inventario, reportes e Intelligence Hub aún fuera del árbol de navegación

01 / El problema

Cada actor ve sólo su parte del mismo dato

Una operación logística con oficina, almacén, choferes y clientes corporativos necesita que cada actor vea sólo su parte del mismo dato, y que el evento de la calle llegue al escritorio sin pasar por WhatsApp ni por papel. El supervisor necesita dar de alta clientes, destinatarios, choferes y envíos, y armar rutas con paradas; el chofer necesita, en un teléfono y con una mano, saber qué paradas tiene, dejar constancia fotográfica de la entrega y confirmar paquete por paquete; el cliente corporativo necesita ver sus envíos y sus destinatarios sin acceso al resto del sistema. Sumado a eso, el dominio venezolano impone reglas propias: documentos RIF/NIT y cédula con formato validable, y direcciones en cascada de país → estado → ciudad → municipio → parroquia → zona postal.

Oficina

Alta de clientes, destinatarios, choferes y envíos; armado de rutas.

Calle

Un teléfono, una mano: paradas, evidencia y confirmación paquete a paquete.

Cliente corporativo

Sus envíos y sus destinatarios, sin acceso al resto del sistema.

Dominio venezolano

RIF/NIT y cédula validables; dirección en cascada de país a zona postal.

M-01Dashboard
M-02Usuarios
M-03Clientes
M-04Destinatarios
M-05Tipos de Destino
M-06Choferes
M-07Envíos
M-08Rutas

módulos sin tablero común

02 / La solución

Cuatro portales, una sola build

Las ocho losas se ensamblan en un tablero continuo. Encima se levantan las cuatro cáscaras que monta App.tsx según el rol.

Supervisorsuper_admin · admin
Operadoroperator
Cliente Masterclient_master
Agenciaclient_agency

Un frontend único con un shell de portal reutilizable (`PortalShell`) que recibe su propio menú por rol y renderiza la misma cáscara —barra lateral navy de 80 px en escritorio, panel deslizante en móvil— con contenidos distintos. Sobre él se montan ocho módulos de administración (Dashboard, Usuarios, Clientes, Destinatarios, Tipos de Destino, Choferes, Envíos y Rutas), cada uno con búsqueda, filtros, paginación servida por el API y tablas que colapsan a tarjetas en móvil. La comunicación pasa por una instancia de axios con interceptores que inyectan el token, traducen los tres formatos de error del backend a modal o toast, reintentan hasta tres veces con backoff y expulsan la sesión ante un 401. El dashboard escucha eventos en vivo por WebSocket con reconexión exponencial, y el portal operador cierra el circuito subiendo la evidencia por multipart y confirmando el escaneo contra la parada concreta de la ruta.

Supervisor

8 secciones

super_admin · admin

Escritorio: alta de clientes, destinatarios, choferes y envíos, armado de rutas y asignación de paradas.

Operador

Rutas asignadas

operator

Móvil del chofer: paradas, cámara trasera, evidencia y escaneo paquete por paquete.

Cliente Master

4 secciones

client_master

Dashboard, usuarios de su compañía, destinatarios y envíos. Nada más del sistema.

Agencia

3 secciones

client_agency

Dashboard, destinatarios y envíos de esa agencia, con el mismo módulo reutilizado.

Portal supervisor · arrastra

M-01

Dashboard

M-02

Usuarios

M-03

Clientes

M-04

Destinatarios

M-05

Tipos de Destino

M-06

Choferes

M-07

Envíos

M-08

Rutas

03 / Lo que sostiene el sistema

Siete piezas bien apoyadas

01

Capa de servicios generada desde el OpenAPI del backend

`gen_services.py` descarga `https://axiomcoretech.store/openapi.json` y escribe `src/services/types.ts` con 98 interfaces y enums más los quince ficheros de servicio. El contrato del frontend deja de escribirse a mano: cuando el backend cambia, se regenera y el compilador señala lo que se rompió.

02

Cuatro portales, una sola build

`App.tsx` mapea el usuario de `/users/me` a uno de cinco roles y monta SupervisorPortal, OperatorApp, ClientMasterPortal o ClientAgencyPortal. Los tres portales de escritorio comparten `PortalShell`, `PageHeader` y `ResponsiveDataTable`, así que un módulo escrito para el supervisor —como Destinatarios o Envíos— se reutiliza tal cual en el portal del cliente pasando `isClientUser`.

03

Evidencia obligatoria antes del escaneo

En cada parada el operador debe cumplir dos pasos en orden: “1. Tomar foto de evidencia”, que sube la imagen por multipart a `/api/v1/uploads/evidence`, y “2. Escanear paquete”, que permanece deshabilitado hasta que existe una evidencia pendiente. El escaneo confirma contra `/routes/{id}/stops/{id}/scan` el mismo paquete de la foto.

04

Dashboard alimentado por WebSocket con reconexión progresiva

`websocket.service.ts` abre `/api/v1/ws/dashboard/live` con el token en la query, distribuye cada evento a los suscriptores y, si la conexión cae, reintenta con un retardo que crece de 3 s a un tope de 30 s multiplicando por 1,5. La UI clasifica los eventos en cuatro tipos (éxito, información, acción requerida, error) con su propio color y glow.

05

Interceptor que traduce tres formatos de error distintos

El interceptor de axios distingue el formato `{ status: 'VALIDATION_ERROR', message, data }`, el `detail` clásico de FastAPI —cadena o lista de `{loc, msg, type}`— y los errores de integridad de base de datos. Un 422 abre modal global; 400, 409 y 500 muestran toast; el 401 limpia la cookie y recarga; el duplicado de correo en PATCH de usuario se deja pasar para que el formulario lo pinte en su propio tooltip.

06

Etiquetas con QR y comprobantes generados en el cliente

`ShippingLabelGenerator` abre una ventana de impresión con una etiqueta por bulto: número de pieza `GP…​ 1/N`, número referencial derivado del tracking y un QR con `{tracking, reference, piece}` en JSON. El comprobante del envío se arma con jsPDF en el navegador para no depender del PDF del servidor.

07

Rutas con paradas y asignación envío → parada

El módulo de rutas (2.322 líneas) permite crear la ruta con sus paradas por destinatario, editarla, verla en detalle y entrar a una vista de asignación donde cada envío seleccionado elige su parada de descarga; `buildShipmentAssignmentsFromStops` resuelve el `dropoff_stop_id` real que devolvió el servidor.

04 / El recorrido

Un paquete cruzando las ocho losas

Del alta del cliente al escaneo en la calle: el mismo dato cambiando de manos, y su insignia de estado cambiando de color.

01

Alta de cliente

RIF J-30… validado

02

Destinatario

país → estado → ciudad

03

Envío

3 bultos · peso por bulto

Pendiente

04

Etiqueta QR

GP… 1/3 impresa

En Almacén

05

Ruta

paradas por destinatario

06

Parada

dropoff_stop_id resuelto

En Tránsito

07

Foto

multipart /uploads/evidence

08

Escaneo

/routes/{id}/stops/{id}/scan

09

Entregado

cierre de la parada

Entregado

Siete estados de envío, siete insignias

PendienteEn AlmacénAduanaEn TránsitoEntregadoRetrasadoCancelado
05 / La interfaz

Del escritorio del supervisor al bolsillo del chofer

Cinco pantallas reconstruidas: la puerta de entrada, el centro de comando, la operación diaria, el trabajo de asignación y la vista de una mano.

Humbolt · Acceso
HumboltTrackingERP de Logística

Sistema de Gestión de Envíos

Gestión de envíos, tracking en tiempo real y control operacional multi-rol.

100%

Trazabilidad

24/7

Monitoreo

Iniciar Sesión

Ingresa tus credenciales para acceder al sistema

Correo Electrónico

usuario@ejemplo.com

Contraseña

••••••••

Credenciales incorrectas o error en el servidor…

Iniciar Sesión

Login — HumboltTracking

…/humbolt/ · supervisor › dashboard
En vivo

Dashboard

Centro de comando operacional en tiempo real

Estado operativo

Todo al día

Sin alertas ni acciones pendientes

Resumen de eventos

47 en la sesión
14Éxito
27Información
5Acción requerida
1Error

Sin actividad reciente en esta sesión

Dashboard del supervisor — centro de comando en vivo

…/humbolt/ · supervisor › envíos

Gestión de Envíos

Control centralizado de operaciones de envío

Nuevo Envío
Buscar por código, cliente, origen o destino...
Código de SeguimientoClienteRutaPesoEstadoEntrega Est.Actualización
GP-4417832Inversiones Delta C.A.CaracasValencia12,40 kgEntregado12/03hace 4 min
GP-4417791Comercial ÁvilaMaracayBarquisimeto3,15 kgEn Tránsito12/03hace 22 min
GP-4417744Agencia GuaicaipuroCaracasMaracaibo28,00 kgEn Almacén13/03hace 1 h
GP-4417702Distribuidora SurValenciaPuerto La Cruz7,80 kgRetrasado11/03hace 3 h
GP-4417688Textiles del CentroCaracasMérida1,05 kgPendiente14/03hace 5 h
GP-4417650Logística AndinaMéridaCaracas16,60 kgAduana15/03ayer
Mostrando 6 de 128 envíos123

Gestión de Envíos — listado y filtros

…/humbolt/ · rutas › asignar envíos

Asignar Envíos a Ruta

Ruta Centro-Occidente — Selecciona envíos y asígnalos a paradas específicas

Asignar 2 Envío(s)Cancelar

Paradas de la Ruta

1 · Inversiones Delta+22 · Comercial Ávila3 · Agencia Guaicaipuro+14 · Distribuidora Sur
Buscar envíos por código o destino...
GP-441783212,40 kgInversiones Delta C.A. · Caracas → Valencia
GP-44177913,15 kgComercial Ávila · Maracay → Barquisimeto
GP-441774428,00 kgAgencia Guaicaipuro · Caracas → Maracaibo

Asignar Envíos a Ruta

HumboltTrackingPortal Operador
Luis Marcano

← Volver a rutas

RT-00918 paquetes
Empezar rutaCompletar ruta

Parada 3 de 5 · Av. Bolívar, Torre Delta, Valencia

Paso 1: foto de evidencia. Paso 2: escanear o registrar el código del mismo paquete.

1. Tomar foto de evidenciaFoto lista · escanea el paquete
2. Escanear paquete3 / 8 registrados
Foto lista — escanea el paqueteCambiar

Escaneando · html5-qrcode

Registro manual

CódigoPeso (kg)
Completar Parada

Portal Operador — parada de ruta (foto y escaneo)

Las maquetas reproducen la interfaz real; los datos que muestran son de ejemplo.

En vivo

El evento de la calle llega al escritorio sin pasar por WhatsApp

`websocket.service.ts` abre `/api/v1/ws/dashboard/live` con el token en la query y reparte cada evento entre sus suscriptores. Cuatro tipos, cuatro colores, un solo canal.

Éxito

shipment.delivered · GP-4417832

Información

route.started · RT-0091

Acción requerida

recipient.address.pending

Error

scan.mismatch · stop 4

Reconexión progresiva

3s4.5s6.75s10.1s15.2s22.8s30s30s

Si la conexión cae, el retardo crece multiplicando por 1,5 desde 3 s hasta un tope de 30 s. El feed vuelve solo; nadie recarga la pestaña.

06 / Funcionalidades

25 losas de producto terminado

No es una lista de intenciones: cada una está construida, conectada al API real y en uso dentro de alguno de los cuatro portales.

F-01

Login por correo y contraseña contra `/api/v1/auth/login`, token guardado en cookie `AUTH_TOKEN` con vencimiento de un día y auto-login al recargar si la cookie sigue viva

F-02

Enrutado por rol en el cliente: super admin y admin al portal supervisor, operador al portal móvil, cliente master y agencia a sus portales acotados

F-03

Portal supervisor con ocho secciones: Dashboard, Usuarios, Clientes, Destinatarios, Tipos de Destino, Choferes, Envíos y Rutas

F-04

Gestión de usuarios con asistente de alta en varios pasos, pantalla de edición, asignación de roles, reseteo de contraseña y filtros por rol y por estado (activo, inactivo, bloqueado, invitado)

F-05

Gestión de clientes y de tipos de cliente, con cambio de estado y ficha de detalle

F-06

Módulo de destinatarios con flujo de aprobación: direcciones en estado pendiente, aprobada o rechazada, aprobables desde la vista consolidada de agencias

F-07

Alta y edición de choferes y de tipos de destino, con activación/desactivación

F-08

Creación de envíos con remitente (sucursal de origen), destinatario, tipo de servicio, cantidad de bultos, tipo y descripción de contenido, y peso y valor declarado por bulto

F-09

Listado de envíos con búsqueda por código, cliente, origen o destino, filtro de estado, ordenamiento y paginación del servidor

F-10

Siete estados de envío con su insignia de color: Pendiente, En Almacén, Aduana, En Tránsito, Entregado, Retrasado y Cancelado

F-11

Generación e impresión de etiquetas con QR y número referencial, una por bulto, y previsualización en modal

F-12

Comprobante del envío en PDF generado en el navegador con jsPDF

F-13

Carga masiva de envíos por archivo CSV/XLSX con zona de arrastre, barra de progreso y validación fila por fila

F-14

Gestión de rutas: creación con paradas por destinatario, edición, detalle, eliminación con confirmación y asignación de envíos a paradas concretas

F-15

Portal operador: lista de rutas asignadas desde `/routes/driver/me` con código, cantidad de paradas, fecha, chofer y estado (Pendiente, En tránsito, Completada, Cancelada)

F-16

Acciones de ruta del operador: “Empezar ruta” y “Completar ruta” contra los endpoints `/routes/{id}/start` y `/routes/{id}/complete`

F-17

Captura de evidencia con la cámara trasera del teléfono (`facingMode: environment`, 1280×720) y subida multipart antes de habilitar el escaneo

F-18

Escáner QR embebido con `html5-qrcode`, recuadro de escaneo calculado según el ancho de pantalla, y registro manual de código y peso como alternativa

F-19

Dashboard en vivo por WebSocket con panel “Estado operativo” (alertas y acciones pendientes) y “Resumen de eventos” de la sesión

F-20

Búsqueda global y feed de actividad en el portal supervisor

F-21

Portal de cliente master con Dashboard, Usuarios de su compañía, Destinatarios y Envíos; portal de agencia cliente con Dashboard, Destinatarios y Envíos

F-22

Validación de documentos venezolanos: RIF/NIT con prefijo J, G, V, E o P y de seis a diez dígitos, cédula con prefijo V o E, rechazo de dígitos todos iguales y limpieza de prefijos duplicados pegados al número

F-23

Direcciones en cascada contra el API de localidades: países → estados → ciudades → municipios → parroquias → zonas postales

F-24

Modal global de errores de validación alimentado por un servicio de suscripción, más notificaciones toast con Sonner

F-25

Interfaz responsive de verdad: tablas que se convierten en tarjetas en móvil, barra lateral que se transforma en panel deslizante y menú hamburguesa

07 / Stack

Con qué está hecho

Núcleo

4 piezas

React 18.3.1TypeScriptVite 6.3.5@vitejs/plugin-react 4.7.0

Interfaz y estilos

14 piezas

Tailwind CSS 4.1.12 (@tailwindcss/vite)Radix UI (28 primitivas: dialog, select, tabs, dropdown-menu, popover, tooltip…)shadcn/ui (49 componentes en src/app/components/ui)lucide-react 0.487.0motion 12.23.24class-variance-authority 0.7.1tailwind-merge 3.2.0tw-animate-css 1.3.8next-themes 0.4.6sonner 2.0.3vaul 1.1.2cmdk 1.1.1MUI 7.3.5 + Emotion 11Inter y JetBrains Mono (Google Fonts)

Datos y red

5 piezas

axios 1.13.6axios-retry 4.5.0js-cookie 3.0.5WebSocket nativo del navegadorAPI REST/WebSocket en axiomcoretech.store (OpenAPI)

Captura y documentos

6 piezas

html5-qrcode 2.3.8qrcode 1.5.4qrcode.react 4.2.0jsbarcode 3.12.3jspdf 2.5.2MediaDevices getUserMedia

Formularios, tablas y gráficos

10 piezas

react-hook-form 7.55.0react-day-picker 8.10.1date-fns 3.6.0input-otp 1.4.2react-dnd 16.0.1 + react-dnd-html5-backendrecharts 2.15.2embla-carousel-react 8.6.0react-resizable-panels 2.1.7react-responsive-masonry 2.7.1react-slick 0.31.0

Pruebas y tooling

5 piezas

Vitest 4.1.2Testing Library (react, jest-dom, user-event)happy-dom 20.8.9gen_services.py (generador OpenAPI → TypeScript)script QA de rutas del portal operador
08 / Bajo el capó

El tablero desmontado en capas

De la primitiva de Radix al openapi.json del backend, con el hilo esmeralda atravesándolo todo.

Primitivas de interfaz

src/app/components/ui

shadcn/ui · 49 componentes sobre 28 primitivas de Radix

Layout propio

src/app/components/layout

PortalShell · PageHeader · ResponsiveDataTable

Módulos de dominio

20 módulos

admin/ · shipping/ · routes/ · operator/ · client/

Servicios generados

src/services

15 servicios + types.ts emitidos por gen_services.py

API REST + WebSocket

45 rutas

axiomcoretech.store · openapi.json

Arquitectura, en detalle

Aplicación de una sola página servida por Vite bajo la ruta base `/humbolt/`, sin router: la navegación es estado de React. `src/main.tsx` monta `src/app/App.tsx`, que resuelve la sesión (cookie `AUTH_TOKEN` + caché de `/users/me`) y, según el rol mapeado por `current-user.service.ts`, renderiza uno de cuatro portales. La capa de presentación se organiza en tres niveles: primitivas de shadcn/ui en `src/app/components/ui` (49 componentes), primitivas de layout propias en `src/app/components/layout` (`PortalShell` para la cáscara con menú, `PageHeader` para el encabezado con acciones, `ResponsiveDataTable` para tablas que degradan a tarjetas en móvil), y módulos de dominio agrupados por carpeta: `admin/` (20 módulos: clientes, destinatarios, sucursales, choferes, tipos de destino, usuarios de cliente, feeds del dashboard), `shipping/` (gestión, formulario, carga masiva, etiquetas), `routes/`, `operator/` (app del chofer, escáner QR, captura de foto) y `client/`. La capa de datos vive en `src/services`: `config/axios.ts` centraliza la instancia con `baseURL` tomada de `VITE_API_URL` —en desarrollo el proxy de Vite reenvía `/api` y `/api/v1/ws` a `axiomcoretech.store`—, inyecta el Bearer desde la cookie, desactiva el `Content-Type` JSON cuando el payload es `FormData` o `Blob`, y aplica la política de errores y reintentos. Los quince servicios restantes y `types.ts` son generados por `gen_services.py` a partir del OpenAPI, de modo que los nombres de método reflejan literalmente el `operationId` del backend. Fuera del eje HTTP, `websocket.service.ts` es un singleton con lista de suscriptores para el feed en vivo, y `validation-error.service.ts` es un bus mínimo de suscripción que permite al interceptor abrir el modal global de validación desde fuera del árbol de React. Las utilidades transversales (`src/utils`) aíslan la lógica pura y comprobable: normalización de paginación, fecha y hora de rutas, mapeo de paradas a asignaciones, validación de documentos, conversión de data URL a `File` y construcción del PDF de comprobante; sobre ellas corren 34 pruebas en seis ficheros con Vitest y happy-dom.

09 / Retos

Seis cosas que se rompieron primero

Cada losa del tablero se asentó después de un fallo concreto. Aquí está el fallo y aquí está lo que lo sostiene ahora.

Se rompió · 01

El escáner QR se reiniciaba en cada pulsación de tecla. Como `OperatorApp` vuelve a renderizarse mientras el operador escribe el código o el peso manualmente, los callbacks pasados a `QRScanner` cambiaban de identidad, el efecto de arranque de la cámara se relanzaba y `html5-qrcode` lanzaba “Cannot clear while scan is ongoing” y un AbortError que tumbaba la pantalla.

Se sostiene así

Los callbacks se guardan en refs (`onScanCompleteRef`, `onCancelRef`) que se actualizan en un efecto aparte, y el manejador de éxito se estabiliza con `useCallback` sin dependencias. Así el efecto que abre la cámara sólo corre al montar; además un `finishedRef` evita procesar dos lecturas y el cierre detiene y limpia el escáner de forma ordenada.

Se rompió · 02

El backend devuelve errores en tres formas distintas —`{status:'VALIDATION_ERROR', message, data}`, el `detail` de FastAPI (cadena o lista de `{loc,msg,type}`) y errores de integridad de base de datos—, y aplicar una sola política producía o modales de más o mensajes inútiles como “Error 500 del servidor”.

Se sostiene así

Un único interceptor de respuesta clasifica: el 422 siempre abre modal; 400, 409 y 500 muestran toast; cuando `data` trae el motivo concreto y `message` es genérico, gana el motivo concreto; el prefijo técnico del 500 sólo se antepone si no hubo mensaje legible del API. Los fallos de `/auth/login` y `/auth/register` se marcan como excepción para que los resuelva el formulario, y el duplicado de correo en PATCH de usuario se deja pasar para pintarse como tooltip en el campo.

Se rompió · 03

El PDF de comprobante generado por el servidor fallaba al serializar modelos ORM anidados (ciudad, país) del destinatario.

Se sostiene así

El comprobante se construye en el navegador con jsPDF a partir de los datos ya normalizados del API: `shipment-comprobante-pdf.ts` incluye helpers que extraen el `name` de objetos de localidad, resuelven el código o nombre de la zona postal y traducen los siete estados internos a español antes de dibujar el documento.

Se rompió · 04

Al crear una ruta, las paradas del formulario no tienen todavía identificador; sólo el `POST /routes/` devuelve las paradas reales, y los envíos deben asignarse a un `dropoff_stop_id` concreto del servidor.

Se sostiene así

`buildShipmentAssignmentsFromStops` empareja cada parada de la UI con la del servidor primero por posición —validando que coincida el `recipient_id`— y, si no cuadra, buscando por la combinación de `recipient_id` y `stop_number`. Devuelve un resultado tipado `{ok:true, assignments}` o `{ok:false, error}` con un mensaje que nombra la parada problemática, y está cubierto por pruebas unitarias.

Se rompió · 05

Un login lento seguido de un segundo intento dejaba llegar la respuesta vieja y sobrescribía el estado; y los reintentos automáticos de axios convertían un DELETE con 500 en varias peticiones y varios toasts idénticos.

Se sostiene así

El formulario de login usa un `AbortController` que cancela la petición anterior más un contador de intento que descarta cualquier respuesta que no sea la del intento vigente. En el interceptor, la lógica de reintento (hasta tres, con backoff de 1 s, 2 s y 3 s) se aplica sólo a errores de red y 5xx y excluye explícitamente el método DELETE.

Se rompió · 06

El proyecto nació como un bundle exportado de Figma Make: pantallas completas pero pobladas con datos simulados y sin contrato con ningún backend.

Se sostiene así

Se escribió `gen_services.py`, que descarga el `openapi.json` del backend y emite `types.ts` (98 interfaces y enums) y los servicios; la migración se hizo módulo a módulo sustituyendo el mock por la llamada real, con `normalizePaginationMeta` para tolerar las distintas formas de metadatos de paginación. Quedan aún en el repositorio pantallas heredadas del prototipo (Intelligence Hub, Reportes, Inventario, ShippingModule) que no están enganchadas a ningún menú.

10 / Métricas

El proyecto en ocho cifras

4

portales por rol en una sola build

5

roles de usuario soportados

45

rutas de API consumidas (REST + WebSocket)

98

tipos TypeScript generados desde el OpenAPI

20

módulos de administración

49

componentes de interfaz reutilizables

34

pruebas unitarias en 6 ficheros

35.688

líneas de TypeScript/TSX en 139 ficheros

Paleta

#003153navy-blue#004C7Anavy-blue-light#10B981emerald-green#F8F9FAsoft-slate#FFFFFFsurface

Institucional y sobrio: azul marino profundo como color de mando —barra lateral, encabezados, títulos— y un verde esmeralda que se reserva para lo que está vivo o confirmado: el estado activo del menú, la insignia de “Entregado”, el botón de escanear, el anillo de foco. Todo respira sobre un gris casi blanco, con tipografía Inter para el texto y JetBrains Mono para códigos de seguimiento, pesos y correos. Es la estética de un panel de control serio, no de una app de consumo.

El tablero, completo

Ocho módulos, cuatro portales, una sola pieza de software

Lo que empezó como un bundle exportado de Figma Make hoy habla con el OpenAPI de producción, sube fotos desde la calle y confirma paquetes contra la parada exacta de la ruta.

M-01Dashboard
M-02Usuarios
M-03Clientes
M-04Destinatarios
M-05Tipos de Destino
M-06Choferes
M-07Envíos
M-08Rutas
DashboardUsuariosClientesDestinatariosTipos de DestinoChoferesEnvíosRutasOpenAPI → TypeScriptWebSocket en vivoEvidencia + escaneoRIF / CédulaDashboardUsuariosClientesDestinatariosTipos de DestinoChoferesEnvíosRutasOpenAPI → TypeScriptWebSocket en vivoEvidencia + escaneoRIF / Cédula

Humbolt MVP

¿Quieres algo así para tu producto?

Un ERP multi-rol conectado a una API real, con la calle y la oficina en la misma build. Si tu operación necesita portales por rol, evidencia en campo y un contrato de datos que no se escriba a mano, es exactamente el terreno que conozco.

2026MVP