Como crear un nuevo modulo
Guia paso a paso para agregar un modulo completo a Zentto, desde la API hasta el frontend y el despliegue.
1. Crear el modulo API
Los modulos de la API viven en web/api/src/modules/. Cada modulo tiene su propio directorio con rutas y servicios.
web/api/src/modules/[nombre]/
├── routes.ts # Express Router con endpoints
└── service.ts # Logica de negocio (llama a SPs) Ejemplo de routes.ts:
import { Router } from 'express';
import { authMiddleware } from '../../middleware/auth';
import * as svc from './service';
const router = Router();
router.use(authMiddleware);
router.get('/', svc.list);
router.get('/:id', svc.getById);
router.post('/', svc.create);
router.put('/:id', svc.update);
router.delete('/:id', svc.remove);
export default router; Ejemplo de service.ts:
import { callSp, callSpOut } from '../../db/query';
export async function list(req, res) {
const result = await callSpOut('usp_Mod_Entity_List', {
CompanyId: req.companyId,
Page: req.query.page || 1,
PageSize: req.query.pageSize || 25,
}, ['TotalCount']);
res.json({ ok: true, data: result.recordset, total: result.output.TotalCount });
} 2. Crear los Stored Procedures
Crear los SPs en ambos motores de base de datos:
web/api/sqlweb/includes/sp/usp_[modulo].sql— SQL Serverweb/api/sqlweb-pg/includes/sp/usp_[modulo].sql— PostgreSQL
Agregar el archivo a run_all.sql de cada motor. Ver la pagina Crear nuevo SP para detalles.
3. Registrar rutas en la API
Importar el router del modulo en el archivo principal de la aplicacion y montarlo bajo el prefijo /v1/[nombre]:
// web/api/src/app.ts
import moduloRoutes from './modules/[nombre]/routes';
app.use('/v1/[nombre]', moduloRoutes); 4. Crear la app frontend
Las micro-apps viven en web/modular-frontend/apps/. La forma mas rapida es copiar una app existente como plantilla:
# Copiar una app existente como base
cp -r web/modular-frontend/apps/inventario web/modular-frontend/apps/[nombre]
# Actualizar package.json (nombre, puerto)
# Actualizar next.config.ts (basePath si es sub-app independiente) Si el modulo es parte del shell (navegacion integrada), no necesita basePath. Si es independiente (como POS o Ventas), debe tener su propio basePath.
5. Agregar a PM2
Editar docker/pm2.config.cjs para agregar el nuevo proceso con su puerto asignado:
{ name: '[nombre]', script: 'node_modules/.bin/next',
args: 'start -p [PUERTO]', cwd: '/app/apps/[nombre]',
env: { ...runtimeEnv, NEXT_BASE_PATH: '/[nombre]',
SHELL_URL: 'http://127.0.0.1:3000' } }, 6. Agregar a la navegacion del shell
Si el modulo aparece en el menu lateral, agregarlo en el archivo de navegacion del shell:
// web/modular-frontend/apps/shell/src/components/navigation.tsx
{ label: '[Nombre]', href: '/[nombre]', icon: IconComponent } 7. Agregar al build Docker
Exponer el nuevo puerto en docker/Dockerfile.frontend y actualizar el rango de puertos en docker-compose.prod.yml si es necesario.
Si es una sub-app independiente, agregar la regla de proxy en nginx/zentto.conf:
location /[nombre] {
proxy_pass http://127.0.0.1:[PUERTO];
proxy_http_version 1.1;
proxy_set_header Host $host;
# ... demas headers de proxy
} 8. Actualizar contrato OpenAPI
Documentar los nuevos endpoints en web/contracts/openapi.yaml antes de que el frontend los consuma.
9. Verificar ambos motores de BD
Probar con ambos valores de DB_TYPE:
# Probar SQL Server
DB_TYPE=sqlserver npm run dev
# Probar PostgreSQL
DB_TYPE=postgres npm run dev Checklist final
- API: modulo creado en
modules/, rutas registradas - SQL: SPs en ambos motores, agregados a
run_all.sql - Frontend: app creada, package instalado, build funciona
- PM2: proceso agregado con puerto asignado
- Shell: navegacion actualizada (si aplica)
- Docker: puerto expuesto, Nginx configurado (si sub-app)
- OpenAPI: endpoints documentados
- Test: ambos motores de BD verificados