Arquitectura del Frontend CDP
Visión General
El frontend del Customer Data Platform (CDP) de Nerdistan es una aplicación web moderna construida con React 18 y optimizada para visualización de datos en tiempo real. La arquitectura está diseñada para manejar grandes volúmenes de datos de clientes (200K+ consumidores) con una experiencia de usuario fluida y responsiva.
Stack Tecnológico
Core
- React 18.2.0: Framework principal para construcción de UI
- Vite 5.0.11: Build tool ultra-rápido con HMR (Hot Module Replacement)
- JavaScript/JSX: Lenguaje principal (sin TypeScript por simplicidad)
UI y Visualización
- Tremor.so 3.x: Biblioteca de componentes especializados en dashboards
- Recharts 2.x: Gráficos y visualizaciones interactivas
- Tailwind CSS 3.x: Sistema de diseño utility-first
- Heroicons: Iconografía consistente
Estado y Datos
- React Hooks: useState, useEffect para gestión de estado local
- Fetch API: Comunicación con backend sin librerías adicionales
- Local State: Sin Redux/Context API por simplicidad
Estructura del Proyecto
nerdistan-cdp-frontend/
├── src/
│ ├── components/ # Componentes reutilizables
│ │ ├── DashboardTremor.jsx # Dashboard principal con selector de tenants
│ │ ├── CDPAnalytics.jsx # Análisis RFM y segmentación
│ │ ├─ ─ DataViewer.jsx # Visualizador de datos raw
│ │ ├── VTEXIntegrationConfig.jsx # Configuración VTEX
│ │ └── GoogleAds/
│ │ └── AudienceManager.jsx # Gestión de audiencias Google Ads
│ ├── App.jsx # Componente raíz
│ ├── main.jsx # Entry point
│ └── index.css # Estilos globales
├── public/ # Assets estáticos
├── dist/ # Build de producción
└── vite.config.js # Configuración de Vite
Componentes Principales
1. DashboardTremor
El componente central que orquesta toda la aplicación:
- Selector de Tenants: Permite cambiar entre diferentes cuentas (56, 52, 53, etc.)
- Tabs de Navegación: Overview, CDP Analytics, Data Viewer, Google Ads, VTEX
- Estado Global: Mantiene tenantId y tenantName para toda la app
2. CDPAnalytics
Sistema completo de análisis de clientes:
- Análisis RFM: Segmentación por Recency, Frequency, Monetary
- Churn Prediction: Predicción de abandono con ML
- Customer Profiles: Perfiles detallados de clientes
- Lifecycle Stages: Etapas del ciclo de vida del cliente
3. DataViewer
Explorador de datos raw del CDP:
- Visualización Tabular: Muestra datos directos de la base
- Exportación CSV: Permite descargar datos para análisis externo
- Métricas Agregadas: Overview de KPIs principales
Patrones de Diseño
1. Component Composition
// Composición jerárquica clara
<DashboardTremor>
<TenantSelector onChange={handleTenantChange} />
<TabGroup>
<Tab>Overview</Tab>
<Tab>CDP Analytics</Tab>
</TabGroup>
<TabPanels>
<CDPAnalytics tenantId={selectedTenant} />
</TabPanels>
</DashboardTremor>
2. Props Drilling Controlado
// Props fluyen de arriba hacia abajo
const [selectedTenant, setSelectedTenant] = useState(56);
// Pasar solo lo necesario a cada componente
<CDPAnalytics
tenantId={selectedTenant}
tenantName={getTenantName(selectedTenant)}
/>
3. Error Boundaries Implícitos
// Manejo de errores en cada componente
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
try {
const data = await fetchData();
} catch (err) {
setError(err.message);
// Mostrar UI de error amigable
}
Flujo de Datos
1. Carga Inicial
graph LR
A[App Start] --> B[Load Tenants]
B --> C[Select Default Tenant 56]
C --> D[Fetch Tenant Data]
D --> E[Render Dashboard]
2. Cambio de Tenant
graph LR
A[User Selects Tenant] --> B[Update State]
B --> C[Trigger useEffect]
C --> D[Fetch New Data]
D --> E[Update All Components]
3. Comunicación con API
// Patrón estándar para todas las llamadas API
const API_URL = import.meta.env.VITE_API_URL ||
'https://nerdistan-datalake-production.up.railway.app';
const fetchData = async (tenantId) => {
setLoading(true);
try {
const response = await fetch(
`${API_URL}/api/v2/cdp/analytics/rfm?tenant_id=${tenantId}`
);
if (!response.ok) throw new Error('API Error');
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
throw error;
} finally {
setLoading(false);
}
};
Performance y Optimización
1. Code Splitting
- Vite automáticamente divide el código en chunks
- Lazy loading para componentes pesados
- Dynamic imports para features opcionales
2. Caching Strategy
// Cache local para evitar re-fetches innecesarios
const cache = new Map();
const fetchWithCache = async (key, fetcher) => {
if (cache.has(key)) {
return cache.get(key);
}
const data = await fetcher();
cache.set(key, data);
return data;
};
3. Debouncing y Throttling
// Para búsquedas y filtros
const debounce = (func, wait) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
};
const handleSearch = debounce((query) => {
searchCustomers(query);
}, 300);
Seguridad
1. Sanitización de Inputs
- Todos los inputs de usuario son validados
- Escape de HTML en renderizado
- Validación de tipos en props
2. API Security
- CORS configurado en backend
- Sin credenciales sensibles en frontend
- Variables de entorno para URLs
3. Content Security Policy
// Headers de seguridad en producción
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline';"
/>