Aplyra
Un monorepo TypeScript construido como ejercicio de arquitectura: hexagonal estricta, proveedores de IA intercambiables, caché por similitud, y 243 tests contra servicios reales.
Por qué existe
Los generadores de CVs con IA suelen tener dos problemas: (1) alucinan — agregan experiencias, certificaciones o tecnologías que no existen — y (2) re-llaman al modelo cada vez que pides un cambio pequeño, lo cual cuesta dinero y tiempo.
Aplyra es mi intento de resolver los dos. Lo construí también para presionar mi propia idea de qué tan disciplinada puede ser una arquitectura hexagonal en TypeScript cuando nadie te está empujando a tomar atajos.
Las decisiones que importan
Hexagonal estricta, validada con ESLint. Cuatro puertos definen las únicas formas en que el dominio se comunica con el mundo (IA, persistencia, render, búsqueda). Reglas de ESLint custom impiden importar adaptadores desde el dominio — el commit no entra si rompes la arquitectura.
Dos proveedores de IA intercambiables. OpenAI y Gemini, detrás de la misma interfaz de puerto. Cambiar el proveedor es cambiar una variable de entorno; el dominio no se entera.
Guard anti-alucinación. Después de generar, comparo el CV de salida contra los hechos de entrada. Si aparecen empleos, fechas o tecnologías que no estaban en la fuente, la respuesta se rechaza con HTTP 422 antes de salir.
Caché por similitud Jaccard + SHA-256. Hash exacto primero (devuelve en milisegundos); si no hay match, similitud Jaccard sobre el conjunto de tokens del input. Inputs muy parecidos reutilizan la última respuesta del modelo. El gasto en LLM cae drásticamente con uso real.
Testing en serio
243 tests entre tres niveles: unit sobre el dominio puro, integration contra MongoDB real (no mocks) y Puppeteer real para PDFs, y e2e sobre toda la cadena. Nada de mocks de proveedores externos que mienten — si Mongo se cae en CI, el test se cae, y eso es información.
Esto es deliberado. Mockear la infraestructura te da tests verdes y producción rota; testear contra servicios reales te da feedback honesto y un CI un poco más lento que vale cada segundo.
Lo que aprendí
Que la disciplina arquitectónica no es opcional cuando trabajas solo. Sin code review, lo único que te protege de tomar atajos es hacer que los atajos sean técnicamente imposibles — vía linters, types, y barreras explícitas.
También que las cachés inteligentes son una forma muy barata de hacer producto. Cada llamada que evitas al LLM es plata, latencia y huella de carbono. Una caché Jaccard de 200 líneas vale más que casi cualquier optimización de prompt.