Arquitectura micro-frontends
El frontend del ERP se divide en micro-apps Next.js 16 independientes(npm workspaces en web/modular-frontend): un shell que orquesta autenticación y navegación + 16 apps de módulo en producción, cada una en su puerto bajo PM2. Además hay dos apps fuera del contenedor principal: lab (experimentos, solo dev) y panel (con workflow de deploy propio).
Diagrama de arquitectura
Auth + Nav + proxy] --> APPS[16 micro-apps
:3001-3015, :3017] APPS --> API[API :4000] SHELL --> API SHELL --> AUTH[zentto-auth
auth.zentto.net] style SHELL fill:#6C63FF,color:#fff style API fill:#FF6584,color:#fff style AUTH fill:#10b981,color:#fff
Mapa de puertos (producción, pm2.config.cjs)
| App | Puerto | basePath | Descripción |
|---|---|---|---|
| shell | 3000 | / | Login, dashboard, navegación, backoffice |
| contabilidad | 3001 | /contabilidad | Plan de cuentas, asientos, reportes |
| nomina | 3002 | /nomina | Empleados, nómina, prestaciones, portal del empleado |
| pos | 3003 | /pos | Punto de venta |
| bancos | 3004 | /bancos | Conciliación bancaria, movimientos |
| inventario | 3005 | /inventario | Productos, almacenes, kardex |
| ventas | 3006 | /ventas | Facturación, CxC, cobros, vendedores |
| compras | 3007 | /compras | Órdenes de compra, CxP, proveedores |
| restaurante | 3008 | /restaurante | Mesas, comandas, cocina |
| ecommerce | 3009 | /ecommerce | Tienda online (Zentto Store del tenant) |
| auditoria | 3010 | /auditoria | Auditoría y trazabilidad |
| logistica | 3011 | /logistica | Logística y despachos |
| crm | 3012 | /crm | CRM del ERP (el CRM standalone vive en zentto-crm) |
| manufactura | 3013 | /manufactura | Órdenes de producción, BOM, MES |
| flota | 3014 | /flota | Gestión de flota de vehículos |
| shipping | 3015 | /shipping | Envíos y tracking (portal de envíos) |
| report-studio | 3017 | /report-studio | Diseñador de reportes (Report Engine) |
| lab | 3016 (solo dev) | — | Experimentos; no se despliega |
| panel | 3018 | — | Panel operativo; deploy propio (deploy-panel.yml) y APK wrapper (zentto-mobile-panel) |
Discrepancia conocida
En los package.json de dev, pos y nomina tienen los puertos invertidos respecto a producción (dev: pos=3002, nomina=3003). La tabla de arriba reflejaproducción (pm2.config.cjs), que es la canónica para Nginx.
Cómo el shell orquesta las apps
Nginx enruta app.zentto.net/* al shell (:3000). Cada micro-app corre conNEXT_BASE_PATH=/<modulo> y conoce SHELL_URL=http://127.0.0.1:3000para redirigir al shell cuando necesita autenticación. La sesión viaja en la cookie compartida del dominio .zentto.net, por lo que funciona igual en subdominios de tenant.
El login del shell usa NextAuth 5 (beta) con credentials provider contrazentto-auth (AUTH_SERVICE_URL, build-argNEXT_PUBLIC_AUTH_URL); como fallback autentica contra /v1/auth/logindel ERP. El TenantGuard de @zentto/shared-auth fija el contexto de tenant al entrar por subdominio.
PM2 en Docker
El contenedor zentto-frontend corre las 17 apps de producción conpm2-runtime. Cada entrada define puerto, NEXT_BASE_PATH,SHELL_URL y el env runtime (BACKEND_URL, AUTH_SECRET,AUTH_TRUST_HOST, AUTH_SERVICE_URL):
// docker/pm2.config.cjs (extracto)
{ name: 'shell', script: 'node_modules/.bin/next', args: 'start -p 3000', cwd: '/app/apps/shell' },
{ name: 'nomina', script: 'node_modules/.bin/next', args: 'start -p 3002', cwd: '/app/apps/nomina',
env: { ...runtimeEnv, NEXT_BASE_PATH: '/nomina', SHELL_URL: 'http://127.0.0.1:3000' } },
// ...Paquetes compartidos (27 en packages/)
@zentto/shared-ui
Componentes comunes (layout, diálogos, chips, FilterPanel) sobre MUI + Tailwind. Las tablas usan siempre <ZenttoDataGrid>.
@zentto/shared-auth
Configuración NextAuth, TenantGuard, hooks de sesión y permisos.
@zentto/shared-api
Fetch helpers tipados con credenciales, formato de fechas y useTimezone.
Además: design-tokens, erp-ux, vertical-layout,vertical-auth, landing-kit, editor, geo,shared-i18n, shared-reports y los module-*(pos, restaurante, crm, inventario, …): la lógica de cada módulo empaquetada para que los verticales standalone (p. ej. zentto-pos, zentto-restaurante) la consuman desde el registry sin duplicar código.
Cómo agregar una nueva micro-app
- Copiar una app existente de
apps/como plantilla (mantiene configuración de workspace, tsconfig y deps compartidas) y ajustar nombre + puerto enpackage.json. - Configurar
next.config.tscon elbasePathdel módulo. ⚠️ Si la app hace prerender estático, definirassetPrefix: ''primero — sin eso, el HTML estático apunta a assets del build viejo y la página no hidrata en deploy. - Registrar la navegación en el shell.
- Agregar a PM2 (
docker/pm2.config.cjs) con puerto,NEXT_BASE_PATHySHELL_URL. - Exponer el puerto en
docker/Dockerfile.frontendy, si aplica, la regla de proxy en la config de Nginx (repozentto-infra). - Actualizar el contrato OpenAPI con los endpoints que consuma.