Portfolio · Full-stack · Open Source
💼 LinkedIn ✉️ Email

Proyecto destacado · Product Engineering · Full Stack

KAVANA Manufacturing - MES offline-first nacido desde el suelo de fábrica

Proyecto portfolio de full-stack. Construí un MES (Manufacturing Execution System) que resuelve el problema que viví durante 8 años como operario en el sector industrial: escritura transaccional offline (IndexedDB + outbox), multi-tenant con aislamiento a nivel de base de datos (PostgreSQL RLS), sincronización durable con BullMQ y una interfaz pensada para manos con guantes.

Tecnologías: TypeScript, NestJS, React, PostgreSQL 16 + Prisma, Redis + BullMQ, Dexie.js, Docker/K8s, GitHub Actions. Ver arquitectura completa →

233
Tests (216 API + 17 frontend)
17
Módulos NestJS
5
ADRs documentados
RLS
Aislamiento multi-tenant
📐 Decisiones técnicas 🔒 ADR: Multi-tenant RLS 📴 ADR: Offline-first 🧤 ADR: UX operario 🚩 ADR: Feature flags 📋 Ver los 5 ADRs
El origen

Por qué construí esto

Pasé mis últimos 8 años como operario de fábrica en el sector industrial. Vi cómo el trabajo real -turnos, máquinas CNC, operarios con guantes, ruido y WiFi que cae- chocaba cada día con herramientas diseñadas en oficinas con conexión estable y ratón.

Registros en papel por manos manchadas de grasa o aceite, con letra ilegible. Cada operario pierde una media de 5 minutos al día para después traspasarlo a Excel. El jefe de equipo no tiene control real de lo producido sin pasearse por cada puesto. Los relevos no se comunican entre sí. Y los ERPs generalistas son complejos para el operario y obsoletos para la planta.

Kavana Manufacturing no nació de un ejercicio de programación. Nació de la desconexión que yo mismo viví entre lo planificado y la experiencia real en el suelo de la fábrica. Mi cabeza empezó a detectar patrones y medidas para hacer el trabajo mucho más sencillo al operario y a oficina: si algo se puede hacer en dos clics en lugar de cinco, eso ya es una mejora sustancial. Este proyecto demuestra cómo traduje esa experiencia en arquitectura.

Lo que demuestra

Capacidades técnicas visibles en este proyecto

🏗️

Arquitectura backend real

NestJS con 17 módulos (orders, OEE, quality, costs, sync, auth, tenants...) y guards globales: auth, contexto de tenant, rate-limit, validación. API OpenAPI 3.1.

🔒

Multi-tenant con RLS

Shared schema + Row Level Security en PostgreSQL. El aislamiento lo enforza la base de datos (client_id), imposible de evadir incluso con SQL raw. Verificado con tests cross-tenant. ADR →

📴

Offline-first real, no cache-only

Dexie.js/IndexedDB como base de datos local completa, no un Service Worker que solo cachea assets. El operario crea órdenes y registra calidad sin red; cada mutación genera un evento en cola local (outbox). ADR →

🔄

Sync durable con BullMQ

Colas Redis (sync:push, sync:pull, analytics:aggregate) con retry exponencial, dead-letter e idempotency keys. Nada se pierde aunque el cliente esté días offline. Métricas Prometheus por cola.

🧪

233 tests (216 backend + 17 frontend)

Unitarios, integración y e2e con Testcontainers (PostgreSQL y Redis reales en CI). Incluye tests de aislamiento multi-tenant, cálculos OEE y transacciones atómicas de stock.

🧤

UX diseñada para guantes

Botones de 64px, contraste alto, flujo lineal. Diseñada para pantallas táctiles industriales y manos con guantes, no para ratón de oficina. Si el control es pequeño, el operario falla y deja de registrar. ADR →

🗄️

PostgreSQL 16 + Prisma

Soft deletes, optimistic locking y transacciones atómicas multi-paso. Índices compuestos para las queries de planta. La BD es la única fuente de verdad del aislamiento.

📊

OEE y coste por orden reales

Disponibilidad, rendimiento y calidad calculados por línea y turno en planta, no estimados en papel. Material + mano de obra + energía registrados por orden en origen.

🐳

Deploy reproducible

Docker multi-stage (builder → distroless, non-root) + manifiestos K8s (Deployment, HPA, Ingress) + GitHub Actions: lint → typecheck → test → build → push.

📋

5 ADRs documentados

Cada decisión clave con contexto, alternativas evaluadas y consecuencias: RLS, feature flags, offline-first, UX, toolings. Ver ADRs →

Decisiones técnicas

Criterio aplicado, no solo código

Más allá de las tecnologías, aquí hay decisiones de arquitectura que nacen del producto, no de la tecnología. Cada una responde a un requisito real de planta y tiene su ADR.

🔒 RLS en vez de schema-per-tenant

Un solo esquema = migraciones únicas, pooling eficiente, simplicidad operativa. El aislamiento se enforza a nivel de fila con current_setting('app.current_tenant'). Trade-off: disciplina en middleware y tests de aislamiento obligatorios. ADR →

📴 IndexedDB + outbox en vez de PWA estándar

El Service Worker cachea assets pero no resuelve la escritura transaccional offline. Con Dexie + outbox el operario sigue trabajando sin red y la UI nunca bloquea por red. Trade-off: complejidad de sincronización e idempotency keys. ADR →

🧤 UX tunnel vision para la mano, no el ratón

Poca información por pantalla, 64px mínimo, contraste alto. La interfaz se diseñó para el operario con guantes en una pantalla industrial: si algo se puede hacer en dos clics en lugar de cinco, eso ya es una mejora sustancial. ADR →

🔄 BullMQ en vez de polling

El polling gasta batería y red. La cola durable garantiza que ninguna mutación se pierde aunque el cliente esté offline días. Retry exponencial, dead-letter y observabilidad real por cola.

🧪 Testing como red de seguridad

Si no testeas el aislamiento multi-tenant, no tienes multi-tenant. 233 tests (216 backend + 17 frontend) verifican comportamiento: aislamiento cross-tenant, cálculos OEE, sync offline, auth flows. Con Testcontainers, la CI usa PostgreSQL y Redis reales.

📋 Decisiones documentadas

En 6 meses no recordarás por qué elegiste RLS sobre schema-per-tenant. Los 5 ADRs y el DECISIONS.md convierten decisiones tribales en conocimiento transferible. Es como trabajan los equipos de ingeniería maduros. Ver ADRs →

Stack tecnológico

Arquitectura real, no mockups

🔙 Backend

TypeScriptNestJS 11FastifyPrismaPostgreSQL 16RedisBullMQZodJWT + RLS
  • 17 módulos NestJS + guards globales
  • Multi-tenant con Row Level Security
  • Colas duras con retry y dead-letter
  • API OpenAPI 3.1 documentada

🎨 Frontend

React 19ViteTanStack QueryTailwindDexie.jsVitestPlaywright
  • Offline-first con IndexedDB local
  • Optimistic updates, la UI nunca bloquea
  • UI 64px para manos con guantes
  • Tests de componentes + e2e Playwright

🏗️ Infraestructura

DockerKubernetesGitHub ActionsVercelRenderNeonOpenTelemetryPrometheus
📚 README completo · DECISIONS.md · ADRs (5 documentos) · Repositorio
El flujo completo

Cómo circula una orden en planta

Operario (HMI táctil, sin red) │ crea orden · registra calidad · mermas · tiempos ▼ IndexedDB local (Dexie.js) + outbox │ trabaja offline, la UI nunca bloquea ▼ Sync BullMQ (Redis) │ retry exponencial · dead-letter · idempotency keys ▼ API REST (NestJS + RLS) │ valida tenant y solapamientos de bloques ▼ PostgreSQL 16 (shared schema, aislamiento por fila) │ ▼ Oficina (dashboard) OEE por línea · coste por orden · calidad · incidencias
Estado real

Qué está hecho (verificable) y qué no

Transparencia total: cada punto se puede verificar en el repositorio público. No hay clientes en producción.

Implementado y verificable en repo

Multi-tenant con RLS + tests de aislamiento cross-tenant
Backend NestJS (17 módulos) con auth, tenant context, OpenAPI
Offline-first operativo (Dexie/IndexedDB + sync BullMQ)
233 tests (216 backend + 17 frontend) con Testcontainers
5 ADRs documentados con alternativas evaluadas + DECISIONS.md
Docker multi-stage + K8s manifests + GitHub Actions CI/CD
Frontend React + optimistic updates + demo desplegada

🚧 Planificado (no implementado)

🚧 Envío de fotos desde el móvil del operario para incidencias
🚧 Cálculo automático de kg de materia prima al finalizar orden o turno
🚧 Panel para mecánicos e integración PLC/OPC-UA (requiere hardware real)
🚧 App móvil nativa para supervisores y trazabilidad ISO 9001/GMP
🚧 Implantación en producción piloto

El proyecto está vivo. Cada semana avanzo en los módulos planificados. El repo refleja el estado real en cada commit.

Demo en vivo

Pruébalo ahora

🏭 Kavana Manufacturing

Frontend en Vercel, backend en Render, PostgreSQL en Neon. Demo pública desplegada.

Abrir demo →

💻 Código completo

Repositorio público con docker-compose: levanta PostgreSQL, Redis, backend y frontend en local con un comando.

Ver en GitHub →

¿Quieres ver más?

Este es uno de los proyectos de mi portfolio. Si quieres ver el código, las decisiones técnicas documentadas, o simplemente conectar: