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 refleja
producció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 con
NEXT_BASE_PATH=/<modulo> y conoce SHELL_URL=http://127.0.0.1:3000
para 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 contra
zentto-auth (AUTH_SERVICE_URL, build-arg
NEXT_PUBLIC_AUTH_URL); como fallback autentica contra /v1/auth/login
del 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 con
pm2-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.