Un portfolio con un chatbot que responde sobre mi perfil profesional. Lo construí en público, con el repositorio abierto, porque en un perfil de IA aplicada el código verificable vale más que la descripción de un proyecto que nadie puede abrir.
El único proyecto de mi perfil que quien me evalúa puede auditar entero: el repositorio es público y cada decisión de arquitectura está justificada por escrito, incluida la de no usar RAG.
Un CV afirma cosas y hay que creerle. Quería que al menos un proyecto de mi perfil fuera enteramente auditable por quien lo lee.
El chatbot suma un riesgo que un sitio estático no tiene: un endpoint de modelo expuesto a internet es, sin límites, una factura abierta para cualquiera que encuentre la URL.
El contenido tiene que ser consistente entre el sitio, el bot y mi CV. Tres lugares afirmando lo mismo divergen; es cuestión de tiempo, no de disciplina.
01
El corpus completo de mi perfil entra holgadamente en la ventana de contexto del modelo. La regla es que el retrieval se justifica cuando el corpus NO entra; acá no es el caso. Es la decisión de la que más orgulloso estoy del proyecto, porque la respuesta fácil era agregar un vector store y decir que hago RAG.
Trade-off: Cada llamada envía el corpus entero, así que el costo por request es mayor y crece si el corpus crece. A esta escala es irrelevante, y el día que deje de serlo, la condición para revisar la decisión ya está escrita.
02
El proveedor es la dependencia con más probabilidad de cambiar —por precio, disponibilidad o calidad— y la más fácil de aislar. Una variable de entorno selecciona la implementación y el resto del código no sabe cuál está activa.
Trade-off: Una capa de indirección por adelantado, que normalmente evito. La acepto acá porque el eje de cambio está identificado, no supuesto.
03
El contenido cambia pocas veces por año y lo edita una sola persona. El esquema de tipos es la barrera: un proyecto marcado como archivado no puede renderizarse como enlace, y una recomendación no puede existir sin declarar la relación de quien la escribió. Esas reglas las hace cumplir el compilador, no la memoria.
Trade-off: Editar contenido requiere un commit. Es aceptable, y hasta deseable: deja cada cambio de una afirmación pública en el historial.
04
Dos requisitos que se contradicen: el repo tiene que compilar recién clonado sin credenciales, y un valor malformado no puede llegar a producción. La solución es que nada sea obligatorio pero todo valide su forma cuando está presente. Ausencia igual a degradación prevista; presencia inválida igual a build roto.
Trade-off: Es más código que leer `process.env` directo, y obliga a pensar qué pasa visualmente cuando cada variable falta.
05
El chat solo se habilita si están el kill switch encendido, la clave del proveedor y el backend de rate limit. Si falta cualquiera de los tres, el chat queda apagado y el sitio se sirve completo.
Trade-off: Más configuración antes del primer deploy del endpoint. Prefiero un portfolio sin chat que un chat usable como cómputo gratuito.
Next.js con App Router y TypeScript. El sitio es enteramente Server Components y se prerenderiza estático: no envía JavaScript de cliente, salvo el selector de tema. El contenido vive en JSON tipado que se valida contra el esquema en tiempo de compilación, así que un dato que no cumple el contrato rompe el build en lugar de la página. El chatbot es un Route Handler que inyecta el corpus completo como contexto, con el proveedor detrás de una interfaz intercambiable, reglas duras en el prompt, rate limit por IP y kill switch. La entrada del usuario siempre viaja en su propio turno, nunca concatenada al prompt de sistema.