Este archivo servirá como registro cronológico del proceso de desarrollo de EXPERTECH CV. La idea es documentar decisiones, tareas realizadas, cambios aplicados, validaciones y próximos pasos para facilitar la elaboración de la memoria técnica al finalizar el proyecto.
- Añadir una entrada cada vez que se complete un avance relevante
- Registrar qué se ha hecho, por qué se ha hecho y qué resultado ha dejado
- Incluir, cuando tenga sentido, incidencias, decisiones técnicas y validaciones realizadas
- Mantener un formato simple y cronológico para que luego sea fácil reutilizarlo en la memoria final
- Objetivo:
- Trabajo realizado:
- Archivos afectados:
- Resultado:
- Validación:
- Próximo paso:
- Objetivo: dejar una base inicial del proyecto lista para empezar el desarrollo con una estructura mínima ordenada.
- Trabajo realizado: revisión de la estructura del repositorio, detección de carpetas principales y preparación de una documentación inicial para acompañar el arranque del proyecto.
- Archivos afectados:
README.md, carpetasassets,docs,js,js/models,js/services,js/ui,js/utilsystyles. - Resultado: repositorio preparado con una estructura simple y válida para comenzar a trabajar y subir el proyecto a GitHub.
- Validación: comprobación manual de la estructura existente y del estado del repositorio.
- Próximo paso: definir y desarrollar la primera base funcional del proyecto.
- Objetivo: documentar el proyecto con una presentación profesional mínima desde el inicio.
- Trabajo realizado: creación de una primera versión del
README.mdprincipal con nombre del proyecto, descripción corta, estado del proyecto, objetivo, stack previsto, roadmap resumido y autor. - Archivos afectados:
README.md. - Resultado: documento inicial disponible para presentar el proyecto de forma clara en GitHub.
- Validación: revisión manual del contenido generado y comprobación visual del archivo.
- Próximo paso: ampliar la documentación a medida que avance el desarrollo.
- Objetivo: dejar configurado el acceso al repositorio remoto mediante SSH.
- Trabajo realizado: sustitución de la URL HTTPS del remoto
originpor la URL SSH del repositorio. - Archivos afectados:
.git/config. - Resultado: el repositorio queda preparado para operaciones
pushypullmediante autenticación SSH. - Validación: comprobación con
git remote -v. - Próximo paso: continuar con la implementación del proyecto ya sobre la configuración definitiva del repositorio.
- Objetivo: establecer un registro continuo de avances para reutilizarlo en la memoria técnica final.
- Trabajo realizado: creación y estructuración del archivo
docs/evidencias.mdcon propósito, normas de uso, plantilla base y primeras entradas del proyecto. - Archivos afectados:
docs/evidencias.md. - Resultado: documento operativo preparado para ir registrando el proceso de programación durante todo el proyecto.
- Validación: revisión manual del contenido y de la estructura propuesta.
- Próximo paso: actualizar este archivo en cada hito relevante del desarrollo.
- Objetivo: dejar definida la base de trabajo de la primera feature con reglas claras de colaboración, control básico de Git y una validación inicial de la estructura del proyecto.
- Trabajo realizado: se revisó la hoja de ruta del proyecto para alinear el trabajo con el roadmap del MVP, se decidió trabajar creando las ramas según se vayan necesitando y no todas de golpe, y se dejó fijada como rama activa
feat/project-setup. También se preparó una guía práctica de Git para consulta rápida y se creó un archivoAGENTS.mden la raíz del repositorio para definir cómo debe colaborar Codex en este proyecto. - Trabajo realizado por el usuario: creación y actualización de la rama
feat/project-setup, ejecución de los comandos Git para commit y push del archivoAGENTS.md, sincronización de la rama con GitHub y mantenimiento del control directo sobre el flujo de ramas y commits. - Trabajo realizado por Codex: análisis del estado del repositorio, propuesta del flujo más limpio para ramas y sincronización con GitHub, redacción del contenido de
AGENTS.md, actualización de.gitignorecon una configuración mínima y prudente, y revisión del checklist del primer bloque de preparación. - Archivos afectados:
AGENTS.md,.gitignore,docs/git_guia_practica.md,docs/EXPERTECH_CV_hoja_de_ruta.mdydocs/evidencias.md. - Resultado: queda establecida una forma de trabajo explícita entre usuario y asistente, el repositorio dispone de una base documental más sólida y la feature
feat/project-setupavanza con un criterio más claro de organización y aprendizaje. - Validación: comprobación manual del estado de Git, confirmación de que la rama
feat/project-setupexiste y está sincronizada con su remoto, revisión del checklist de estructura inicial y verificación de que.gitignoreya no está vacío. - Próximo paso: cerrar los puntos pendientes de preparación de la feature
feat/project-setup, subir los commits necesarios y decidir cuándo se da por concluida esta fase para integrarla endev.
- Objetivo: dejar una base visible y ejecutable en navegador para comprobar que la estructura inicial del frontend está correctamente conectada.
- Trabajo realizado: se añadió la carga de
js/app.jsdesdeindex.htmly se consolidó una base mínima de presentación constyles/reset.cssystyles/main.css. - Trabajo realizado por el usuario: edición de
index.html,js/app.js,styles/reset.cssystyles/main.csspara dejar una primera pantalla base y verificar el arranque del script en el navegador. - Trabajo realizado por Codex: revisión de los cambios realizados, comprobación de la conexión entre HTML, CSS y JavaScript, y actualización de la documentación para reflejar el estado real del proyecto.
- Archivos afectados:
index.html,js/app.js,styles/reset.css,styles/main.css,README.md,docs/evidencias.md,docs/roadmap.mdydocs/architecture-notes.md. - Resultado: el proyecto ya dispone de una base estática mínima cargable en navegador, con HTML inicial, estilos enlazados y script JavaScript ejecutándose correctamente.
- Validación: revisión de la carga del script desde
index.htmly comprobación de que elconsole.logdejs/app.jspuede mostrarse en la consola del navegador. - Próximo paso: dejar cerrada la documentación de
feat/project-setupy preparar la transición haciafeature/layout-base.
- Objetivo: dejar el trabajo del día documentado, coherente y listo para retomarlo en la siguiente sesión sin perder contexto.
- Trabajo realizado: se revisó y rehizo el
README.mdcon un enfoque más profesional, se actualizarondocs/roadmap.mdydocs/architecture-notes.mdpara alinearlos con la base real del proyecto, y se corrigió lameta descriptiondeindex.html. - Trabajo realizado por el usuario: ajuste del roadmap operativo con la convención actual de features y consolidación de la base visual y JavaScript del arranque del proyecto.
- Trabajo realizado por Codex: revisión de la documentación, corrección puntual de
index.html, actualización del registro de evidencias y preparación del cierre de la sesión de trabajo. - Archivos afectados:
README.md,docs/roadmap.md,docs/architecture-notes.md,docs/evidencias.mdeindex.html. - Resultado: el repositorio queda mejor documentado, con una dirección de trabajo más clara y con una base inicial más fácil de retomar en la siguiente sesión.
- Validación: revisión manual del contenido de los documentos, del estado actual de la rama
feat/project-setupy de la coherencia entre HTML, CSS, JavaScript y documentación. - Próximo paso: subir todos los cambios a GitHub y continuar la siguiente sesión desde esta misma feature o preparar su cierre hacia
dev.
- Objetivo: construir la primera maqueta real del producto y dejar cerrada la arquitectura visual base de
EXPERTECH CV. - Trabajo realizado: se sustituyó el placeholder inicial por una pantalla completa con flujo visual claro, se consolidó una estructura
editor + preview, se trabajó con enfoque mobile-first, se añadió adaptación a escritorio, se pulieron estados vacíos, badges y microcopy, y se ajustó la preview para que sea sticky solo en desktop. - Trabajo realizado por el usuario: implementación de la maqueta base en
index.htmlystyles/main.css, revisión visual de la feature, cierre funcional de la rama y apertura de la PR haciadev. - Trabajo realizado por Codex: revisión del cierre de feature, ajuste puntual del comportamiento sticky de la preview, comentarios explicativos en HTML y CSS para facilitar lectura y mantenimiento, y actualización de la documentación del proyecto.
- Archivos afectados:
index.html,styles/main.css,README.md,docs/evidencias.mdydocs/roadmap.md. - Resultado: el proyecto ya no muestra una pantalla base vacía, sino una interfaz real con
header,hero,quick actions,editor,previewyfinal actions, preparada para conectar lógica en las siguientes fases del MVP. - Validación: comprobación visual manual del layout en móvil y escritorio, verificación del apilado de bloques en pequeño formato, confirmación de la disposición
editorizquierda /previewderecha en desktop, y validación de que la preview solo queda sticky en escritorio. - Próximo paso: empezar
feat/domain-modelpara definir entidades, estado base del CV y preparar la persistencia local sin mezclar todavía lógica de GitHub ni render dinámico completo.
- Objetivo: definir el núcleo de datos del CV y dejar una estructura inicial estable para las siguientes features.
- Trabajo realizado: se crearon las factories
CandidateProfile,ProjectyPortfolioCV, se añadiócreateInitialCVState()como punto de partida consistente del estado de la app y se conectó temporalmente el modelo desdejs/app.jspara validar la estructura inicial. - Trabajo realizado por el usuario: implementación del modelo de dominio, preparación del estado inicial, revisión de la salida en consola y apertura de la PR hacia
dev. - Trabajo realizado por Codex: revisión del cierre de feature, comprobación del estado real de la PR en GitHub, sincronización de
devcon el remoto y actualización de la documentación de proyecto para reflejar el nuevo estado del MVP. - Archivos afectados:
js/models/CandidateProfile.js,js/models/Project.js,js/models/PortfolioCV.js,js/models/createInitialCVState.js,js/app.js,README.md,docs/evidencias.mdydocs/roadmap.md. - Resultado: el proyecto ya no depende solo de una maqueta visual; ahora dispone también de un contrato de datos base del CV con perfil, proyectos y metadatos, listo para soportar persistencia local y evolución posterior.
- Validación: revisión manual del código del modelo, confirmación de que la PR
#2quedó mergeada endeven GitHub y verificación local de quedevincorpora los nuevos archivos del dominio mediantegit pull origin dev. - Próximo paso: arrancar
feat/local-storagepara guardar y recuperar el estado del CV desde el navegador sin mezclar aún edición completa ni live preview.
- Objetivo: añadir persistencia mínima del estado del CV en el navegador sin mezclar todavía edición completa ni render dinámico real.
- Trabajo realizado: se creó
CVStorageServicecon operaciones de guardado, carga, reset y comprobación de existencia previa, se integró el flujo enjs/app.js, se evitó que la app destruyera la persistencia en cada carga y se dejaron utilidades mínimas accesibles desde consola para validación manual. - Trabajo realizado por el usuario: implementación del servicio de
localStorage, conexión del flujo base enjs/app.js, revisión visual y funcional de la feature y preparación de la rama para PR posterior haciadev. - Trabajo realizado por Codex: revisión del diff de la feature, detección y corrección del problema que reseteaba el almacenamiento en cada arranque, restauración de
README.mdinternos que se estaban borrando accidentalmente, y actualización de la documentación de proyecto para reflejar el nuevo estado de la rama. - Archivos afectados:
js/services/CVStorageService.js,js/app.js,js/models/README.md,js/services/README.md,README.md,docs/evidencias.mdydocs/roadmap.md. - Resultado: el proyecto ya puede guardar y recuperar un estado base del CV en
localStorage, manteniendo una estructura normalizada y preparada para que la siguiente feature conecte edición real sobre persistencia existente. - Validación: revisión manual del servicio y del punto de entrada, comprobación de que la rama queda limpia salvo los cambios esperados y verificación sintáctica prevista antes del push final.
- Próximo paso: arrancar
feat/editor-profilepara editar datos reales del candidato sobre el estado persistido y preparar la conexión posterior con la preview.
- Objetivo: permitir edición manual real de los datos principales del CV, conectando el formulario con el estado persistido.
- Trabajo realizado: se montó el formulario de perfil en
index.html, se añadieron estilos específicos y feedback visual enstyles/main.css, se creóProfileEditor.jspara rellenar, leer y enviar el formulario, y se conectójs/app.jscon la persistencia existente para cargar, guardar y rehidratar el perfil. - Trabajo realizado por el usuario: implementación del formulario, ajuste de estilos, conexión del módulo UI y validación manual del flujo de guardado, recarga y feedback visual.
- Trabajo realizado por Codex: revisión del working tree real de la rama, restauración de
README.mdborrados accidentalmente, verificación sintáctica dejs/app.jsyjs/ui/ProfileEditor.js, y actualización de la documentación de cierre. - Archivos afectados:
index.html,styles/main.css,js/ui/ProfileEditor.js,js/app.js,README.md,docs/evidencias.mdydocs/roadmap.md. - Resultado: el proyecto ya permite editar manualmente el perfil principal del candidato, guardar los cambios en
localStoragey rehidratar el formulario al recargar, dejando una base clara para conectar la preview en la siguiente feature. - Validación: revisión manual del código, verificación de nombres de campos entre HTML y JS, comprobación sintáctica con
node --checky confirmación de que el feedback visual permanece oculto cuando está vacío. - Próximo paso: arrancar
feat/live-previewpara reflejar en tiempo real los cambios del perfil en la vista previa del CV.
- Objetivo: conectar la edición del perfil con una vista previa recruiter-friendly que responda en tiempo real sin romper la persistencia existente.
- Trabajo realizado: se creó
PreviewRenderer.jspara renderizar nombre, titular y resumen del perfil, se amplióProfileEditor.jspara emitir cambios mientras el usuario escribe, y se conectójs/app.jspara mantener sincronizados editor, preview ylocalStoragesin mezclar responsabilidades. - Trabajo realizado por el usuario: implementación del renderizador de preview, conexión del flujo
editor -> estado -> preview, ajuste del HTML de la tarjeta de vista previa y validación manual del comportamiento durante escritura y guardado. - Trabajo realizado por Codex: revisión del cierre funcional de la feature, comprobación de coherencia entre módulos y actualización de la documentación del proyecto para dejar el estado del MVP alineado con lo ya implementado.
- Archivos afectados:
index.html,js/ui/PreviewRenderer.js,js/ui/ProfileEditor.js,js/app.js,README.md,docs/roadmap.mdydocs/evidencias.md. - Resultado: el proyecto ya muestra en la preview los datos principales del perfil en tiempo real, mantiene fallbacks cuando faltan campos y conserva el flujo de guardado sobre
localStoragecomo fuente persistente. - Validación: revisión manual del código y del flujo de interfaz, comprobación de sincronización entre editor y preview, y validación sintáctica con
node --checkdejs/app.js,js/ui/ProfileEditor.jsyjs/ui/PreviewRenderer.js. - Próximo paso: arrancar
feat/github-integrationpara consultar datos públicos básicos desde GitHub sin sustituir la edición manual ya disponible.
- Objetivo: enriquecer el CV con una integración pública básica de GitHub sin romper el flujo manual ya existente del perfil.
- Trabajo realizado: se añadió un bloque independiente para búsqueda de usuario GitHub, se creó
GitHubProfileService.jspara consultar perfil y repositorios públicos, se implementóGitHubIntegration.jspara renderizar perfil, candidatos y selección manual, y se conectójs/app.jspara persistirgithubUsernamey proyectos derivados de repositorios seleccionados dentro del estado actual del CV. - Trabajo realizado por el usuario: implementación del bloque GitHub en HTML y CSS, construcción del servicio y del módulo UI, validación manual del flujo de búsqueda y selección, y cierre del ajuste visual del empty-state para que responda correctamente al atributo
hidden. - Trabajo realizado por Codex: auditoría del flujo de carga y rehidratación, identificación de la causa raíz del empty-state visible, aplicación del fix mínimo en estilos, revisión de coherencia visual de la feature y actualización de la documentación de cierre.
- Archivos afectados:
index.html,styles/main.css,js/app.js,js/ui/GitHubIntegration.js,js/services/GitHubProfileService.js,README.md,docs/roadmap.mdydocs/evidencias.md. - Resultado: el proyecto ya puede consultar datos públicos de GitHub, mostrar perfil y repositorios candidatos, permitir selección manual de repos destacados, persistir esa selección dentro del estado del CV y rehidratar el bloque de forma coherente dentro del alcance MVP actual.
- Validación: revisión manual del flujo UI, comprobación de que el empty-state GitHub se oculta tras una carga correcta, confirmación de que el badge cambia a
Conectado, validación del fallback manual cuando la API falla y verificación sintáctica connode --checkdejs/app.js,js/ui/GitHubIntegration.jsyjs/services/GitHubProfileService.js. - Próximo paso: arrancar
feat/projects-visualizationpara representar de forma más clara en el CV los proyectos ya seleccionados y mejorar la lectura recruiter-friendly del portfolio. - Orden posterior recomendado:
feat/login-screenpara preparar identidad de usuario sin autenticación externa compleja,feat/github-project-sourcespara ampliar orígenes y atribución de proyectos GitHub, y despuésfeat/export-pdf-qr,feat/polish-accessibilityyfeat/documentacion-final.
- Objetivo: mejorar la lectura y visualización de proyectos dentro del CV, aprovechando la selección GitHub ya persistida como base del bloque de proyectos.
- Trabajo realizado: se adaptó la preview para incluir un contenedor dinámico de proyectos, se amplió
PreviewRenderer.jspara renderizar cards desdecvState.projects, se priorizaron proyectos marcados comofeatured, se añadió un empty-state específico y se incorporaron estilos para nombre, descripción, stack y enlaces. - Trabajo realizado por el usuario: implementación y validación visual del bloque de proyectos en la preview, revisión manual del resultado recruiter-friendly y comprobación de que la selección GitHub ya persistida se refleja correctamente en el CV.
- Trabajo realizado por Codex: revisión del estado real de la base tras la integración completa de GitHub en
dev, validación de que la preview ya no dependía de contenido estático, comprobación del cumplimiento de objetivos de la feature y actualización de la documentación de cierre. - Archivos afectados:
index.html,styles/main.css,js/ui/PreviewRenderer.js,README.md,docs/roadmap.md,docs/evidencias.mdydocs/EXPERTECH_contexto_actualizado.md. - Resultado: el proyecto ya representa proyectos destacados dentro de la preview con una presentación más clara para recruiters, reutilizando el estado persistido del CV y manteniendo separación limpia entre datos, selección GitHub y render visual.
- Validación: revisión visual manual de la preview con varios proyectos, comprobación de cards con nombre, descripción, stack y enlaces, verificación del empty-state específico y comprobación sintáctica con
node --check js/ui/PreviewRenderer.js. - Próximo paso: arrancar
feat/login-screenpara preparar una pantalla de acceso clara y una base de identidad de usuario sin introducir todavía autenticación externa compleja.
- Objetivo: añadir una pantalla de acceso
login/registerpara el MVP, introducir una capa básica de identidad local y reducir la responsabilidad deapp.jsmediante una organización más clara de la aplicación. - Trabajo realizado: se implementó una auth local básica con registro y login por email + contraseña, persistencia de usuarios y sesión en
localStorage, restauración automática de sesión al recargar y logout visible dentro de la app autenticada. Además, se extrajeron templates de UI para auth, preview y bloque GitHub, se creó la carpetajs/application/y se movió la orquestación principal aAppRuntime.jsyAuthenticatedCVApp.js. - Trabajo realizado por el usuario: implementación del flujo
login/register/logout, refactor del arranque general de la app, extracción de templates reutilizables y adaptación de los módulos existentes para trabajar con roots más limpios enindex.html. - Trabajo realizado por Codex: auditoría del estado real de la rama, detección de incoherencias documentales frente al código, validación mínima de sintaxis de los nuevos módulos y actualización de la documentación viva del proyecto para reflejar el estado actual del MVP.
- Archivos afectados:
index.html,js/app.js,js/application/AppRuntime.js,js/application/AuthenticatedCVApp.js,js/services/AuthStorageService.js,js/ui/AuthScreen.js,js/ui/AuthScreenTemplate.js,js/ui/PreviewTemplate.js,js/ui/GitHubBlockTemplate.js,README.md,docs/roadmap.md,docs/evidencias.mdydocs/EXPERTECH_contexto_actualizado.md. - Resultado: el proyecto ya obliga a pasar por una pantalla de acceso local antes de entrar a la app principal, mantiene sesión activa entre recargas, conserva el flujo del CV una vez autenticado y presenta una arquitectura más clara para evolucionar después hacia backend y PostgreSQL.
- Validación: lectura del flujo implementado en runtime y auth, verificación de que Google y GitHub solo muestran mensajes informativos en esta fase, y comprobación sintáctica con
node --checkdejs/app.js,js/application/AppRuntime.js,js/application/AuthenticatedCVApp.js,js/ui/AuthScreen.jsyjs/services/AuthStorageService.js. - Próximo paso: arrancar
feat/github-project-sourcespara ampliar la atribución y el origen de proyectos GitHub sin mezclar todavía OAuth real ni backend.
- Objetivo: añadir trazabilidad mínima a los proyectos importados desde GitHub y evitar la confusión del proyecto demo legado en la preview.
- Trabajo realizado: se amplió la normalización de repositorios GitHub para conservar datos básicos de origen, se extendió el modelo
Projectcon metadatos mínimos de trazabilidad, se adaptó la transformación GitHub -> proyectos del CV para persistir ese origen, se añadió una línea visual compacta de origen en la preview y se retiró la siembra de proyectos demo nuevos. Además, se incorporó una limpieza de migración enCVStorageServicepara eliminar el proyecto demo legadoEXPERTECH CVcuando coincide exactamente con la semilla antigua. - Trabajo realizado por el usuario: validación visual de la línea de origen en la preview, confirmación de que los proyectos manuales siguen diferenciándose de los importados y comprobación manual del comportamiento al seleccionar y deseleccionar repositorios desde el bloque GitHub.
- Trabajo realizado por Codex: auditoría del flujo de estado para distinguir dato demo de bug real, implementación del fix mínimo sobre el estado inicial y
localStorage, refuerzo del fallback visual de origen y validación sintáctica de los módulos tocados. - Archivos afectados:
js/services/GitHubProfileService.js,js/models/Project.js,js/application/AuthenticatedCVApp.js,js/ui/PreviewRenderer.js,js/services/CVStorageService.js,styles/main.css,README.md,docs/roadmap.md,docs/evidencias.md,docs/EXPERTECH_contexto_actualizado.mdydocs/architecture-notes.md. - Resultado: los proyectos importados desde GitHub ya conservan una trazabilidad básica visible en la preview, los proyectos manuales siguen protegidos y el bloque de proyectos vuelve al empty-state cuando no hay proyectos reales ni selección GitHub activa.
- Validación: revisión manual de la preview con proyectos GitHub y manuales, comprobación de que al deseleccionar todos los repos ya no queda el proyecto demo
EXPERTECH CV, y comprobación sintáctica connode --checkdejs/services/GitHubProfileService.js,js/application/AuthenticatedCVApp.js,js/ui/PreviewRenderer.jsyjs/services/CVStorageService.js. - Próximo paso: arrancar
feat/export-pdf-qro iterar sobre el perfil híbrido.
- Objetivo: añadir soporte para avatares (sincronizados desde GitHub o subidos localmente con resize por canvas) y crear una vista local adicional (
public.html) preparada para una futura publicación compartible. - Trabajo realizado: se implementó un sistema híbrido que prioriza imágenes subidas localmente (redimensionadas vía canvas para no saturar
localStorage), luego URL manual externa y finalmente de GitHub. También se creópublic.htmlcon su respectivoPublicCVRenderer.jsreutilizando el motor dePreviewRendererpara montar una versión navegable y responsiva idéntica a la vista previa del dashboard, apoyada en el mismo estado persistido del navegador. - Archivos afectados:
index.html,public.html,styles/main.css,js/application/AuthenticatedCVApp.js,js/models/CandidateProfile.js,js/ui/ProfileEditor.js,js/ui/PublicCVRenderer.js. - Resultado: el usuario puede elegir cómo gestionar su avatar y revisar su CV desde una vista local separada, útil para preparar una futura experiencia compartible cuando exista persistencia/publicación real fuera de
localStorage. - Validación: comprobada la sincronización correcta de la imagen local redimensionada en el preview interactivo y la correcta renderización visual del
public.htmlutilizando el mismo estilo base de previsualización. - Próximo paso: cerrar
feat/export-pdf-qry abrirfeat/github-pages-public-previewpara simular una publicación real con GitHub Pages y QR de demo sin mezclar todavía backend ni base de datos.
- Objetivo: transformar la vista pública local en una demo estática preparada para evolucionar a GitHub Pages sin depender del
localStoragedel editor. - Trabajo realizado: se creó un runtime público modular con
js/public.jsyjs/application/PublicPageRuntime.js, se añadiójs/services/PublicCVDataService.jspara cargar un snapshot estático desdedata/public-cv.jsony se adaptóPublicCVRenderer.jspara renderizar la demo pública a partir de ese estado. Además, se puliópublic.htmlpara que la página se sintiera más cercana a una publicación real: avatar visible, hero más limpia, card propia de tecnologías con iconos y documento central sin helper copy de app. - Trabajo realizado por el usuario: revisión visual iterativa de la demo pública, validación del encaje del avatar, ajuste del contenido del snapshot público y decisión de orientar la siguiente fase hacia una publicación real con GitHub Pages.
- Trabajo realizado por Codex: desacople de la demo respecto a
localStorage, creación de la capa modular pública, preparación del snapshotpublic-cv.json, pulido de copy y jerarquía visual, y alineación de la documentación viva con el nuevo estado del proyecto. - Archivos afectados:
public.html,index.html,js/public.js,js/application/PublicPageRuntime.js,js/services/PublicCVDataService.js,js/ui/PublicCVRenderer.js,data/public-cv.json,README.md,docs/roadmap.md,docs/evidencias.md,docs/EXPERTECH_contexto_actualizado.mdydocs/architecture-notes.md. - Resultado: el proyecto ya dispone de una demo pública estática, modular y coherente visualmente, con datos propios del CV y preparada para pasar a una URL pública real mediante GitHub Pages.
- Validación: comprobación sintáctica con
node --check js/public.js,node --check js/application/PublicPageRuntime.js,node --check js/services/PublicCVDataService.jsynode --check js/ui/PublicCVRenderer.js; revisión manual del hero, avatar, tecnologías con iconos y proyectos visibles enpublic.html. - Próximo paso: abrir PR de
feat/github-pages-public-previewcontradev, revisar el diff final y, tras el merge, activar GitHub Pages y preparar el QR apuntando a la URL publicada.
- Objetivo: implementar el bloque de búsqueda de empleo conectado a una API real (Jooble) a través de un proxy local, sin exponer credenciales en el frontend y con soporte total a degradación elegante (Fallback Mode).
- Trabajo realizado: se iteró sobre la base de la feature de InfoJobs para apuntar definitivamente al backend de Jooble. Se consolidó el proxy Express en
server/server.js, y durante las pruebas se depuró un error 403 modificando la URL correcta haciaes.jooble.org. Adicionalmente, se escribió una lógica robusta en el Frontend (JobSearchIntegration.jsyJobOffersService.js) que logra atrapar cualquier caída de la API devolviendo resultados de Mock locales acompañados de un Warning en UI debajo del botón, para que el usuario nunca perciba una rotura total. - Trabajo realizado por el usuario: validación iterativa del entorno local, inyección de la llave Jooble en .env, comprobación del flujo real (Status 200) tras las correcciones de dominio.
- Trabajo realizado por Codex: migración completa de la lógica desde InfoJobs a Jooble, investigación y fix del error de WAF cambiando a dominio regional
es.jooble.org, flexibilización del CORS local, creación del sistema de degradación elegante y actualización de la bitácora técnica. - Archivos afectados:
js/application/AuthenticatedCVApp.js,js/ui/JobSearchBlockTemplate.js,js/ui/JobSearchIntegration.js,js/services/JobOffersService.js,server/server.js,server/services/JoobleProxyService.js,server/README.md,server/.env.example,server/package.json,.gitignore,README.md,docs/roadmap.mdydocs/evidencias.md. - Resultado: el buscador web es capaz de alimentarse en 100% de datos reales desde una API remota a través de un backend local actuando de proxy ciego. Si el backend falla o la Key caduca, la UI resiste de forma autónoma degradando al escenario estático Mock con su propio aviso visual en color naranja, permitiendo demostrar en la práctica el principio Clean Architecture de separación de responsabilidades.
- Validación: ejecución en el servidor local de Node.js mediante fetch real a la API, recibiendo payload
{ jobs: [...] }. Validado en local que el click sobre un link redirige exitosamente a la oferta de su origen. - Próximo paso: cerrar PR de la feature
feat/jooble-search-proxy-mvpsobredevy mover el foco de desarrollo hacia las próximas piezas, como la generación final del CV (Exportar PDF) que clausura el MVP.
- Objetivo: dejar la documentación viva alineada con el estado real del repositorio para cerrar la feature actual y preparar el flujo de PR hacia
devy despuésmain. - Trabajo realizado: se actualizó
README.mdpara reflejar que la fase activa esfeat/visual-polish-final, que Jooble ya está integrado mediante proxy local y que el orden de cierre recomendado es PR de feature adevy luegodevamain. También se actualizódocs/roadmap.mdcon el estado operativo real del cierre. - Trabajo realizado por el usuario: corrección del entorno local de Jooble y validación funcional del flujo de búsqueda con credencial real en
.env. - Trabajo realizado por Codex: comprobación del flujo completo de validación de Jooble en local (modo fallback sin credencial y modo real con
HTTP 200), y actualización documental para cierre de sprint. - Archivos afectados:
README.md,docs/roadmap.mdydocs/evidencias.md. - Resultado: documentación consistente con la rama activa y con una ruta de release clara para cerrar la fase sin ambigüedades.
- Validación: revisión manual de coherencia entre ramas/estado real y contenido documental, más verificación técnica de Jooble vía endpoint local
/api/jobs/search. - Próximo paso: commit de documentación, push de
feat/visual-polish-final, PR haciadev, validación rápida endevy PR final dedevhaciamain.
- Objetivo: endurecer el MVP existente con una tanda de fixes y refactors enfocados en estabilidad, seguridad y limpieza, sin reabrir arquitectura ni migrar a React.
- Trabajo realizado: se ejecutaron ocho ramas secuenciales con cierre individual sobre
dev. (1)fix/stabilize-authenticated-app-listenersseparó el binding de Vista Pública del de Exportar PDF y añadiórefreshCVStateFromActiveSession()para soportar re-login sin recrear módulos ni duplicar listeners. (2)chore/remove-claude-local-settingsañadió reglas de ignore para.claude/sin tocar JS. (3)fix/jobs-proxy-contract-and-securityendureció el contrato del proxy de empleo y revisó manejo de credenciales. (4)security/remove-exposed-jooble-key-and-local-docsretiró documentación local que contenía una API key de Jooble. (5)fix/storage-fallback-and-quota-handlingcreójs/services/SafeStorageService.jscomo wrapper compatible con Storage API con fallbacklocalStorage → sessionStorage → memoria, integró ese wrapper enAuthStorageServiceyCVStorageServicesin cambiar shapes ni claves, y añadió límites de avatar (2 MB raw / ~450 KB base64) enProfileEditor.jspara mitigarQuotaExceededError. (6)security/remove-reintroduced-local-docshizo una segunda pasada para eliminar docs reintroducidos por accidente. (7)refactor/extract-project-rendering-utilsextrajoisRenderableProjectygetVisibleProjectsajs/utils/projects.jsy eliminó la duplicación entrePreviewRenderer,PrintCVRendereryPublicCVRenderer, dejando una sola fuente de verdad para la regla de visibilidad de proyectos. (8) Tras el merge se detectaron imports no usados deisRenderableProjecten los tres renderers y se limpiaron para dejar soloimport { getVisibleProjects }. - Trabajo realizado por el usuario: dirección estratégica del bloque, redefinición del alcance (descartar migración React, mantener MVP), correcciones de rumbo cuando el asistente se desvió de las restricciones (over-engineering inicial de
SafeStorageService, contaminación de ramas con borrados ajenos, intento erróneo de ignorarpackage-lock.json), validación de cada PR antes del merge. - Trabajo realizado por Codex: implementación de cada cambio, separación de listeners, diseño del wrapper de Storage, integración no invasiva en los servicios existentes, refactor de los renderers, sanitización de secretos en documentación, verificaciones sistemáticas con
git status,git diffygrepantes de cada commit. - Archivos afectados:
js/application/AuthenticatedCVApp.js,js/ui/ProfileEditor.js,js/services/SafeStorageService.js(nuevo),js/services/AuthStorageService.js,js/services/CVStorageService.js,js/utils/projects.js(nuevo),js/ui/PreviewRenderer.js,js/ui/PrintCVRenderer.js,js/ui/PublicCVRenderer.js,.gitignore,docs/docs_V2/fix-storage-fallback-and-quota-handling.mdy varios borrados de docs locales con secretos. - Resultado:
devqueda 18 commits adelante demaincon el bloque de hardening cerrado. La app autenticada soporta re-login sin bugs visibles, el storage degrada con elegancia en Safari privado o iframes restrictivos, el avatar no puede provocarQuotaExceededErrorsin aviso, el proxy de empleo no expone credenciales en el repo, y la regla de visibilidad de proyectos vive en un único módulo reutilizado por los tres renderers. - Validación: revisión PR por PR antes del merge, verificación con
grep -Rde que las funciones extraídas solo tienen una definición real, comprobación de que ningún PR contamina docs/server/styles fuera del alcance declarado. Testing manual en navegador queda como tarea pendiente del bloque siguiente. - Próximo paso: cerrar
chore/add-gitattributes-line-endings, abrir PR adevy, tras validar, abrir PRdev → maincon el bloque completo de hardening.
- Objetivo: añadir un
.gitattributesconservador a la raíz del repo para evitar diffs ruidosos por finales de línea (CRLF/LF) entre Windows, macOS y Linux, sin renormalizar el repo completo. - Trabajo realizado: se creó
.gitattributescon reglas explícitas (* text=auto,eol=lfpara código y docs,eol=crlfpara scripts Windows,binarypara imágenes y PDFs). No se ejecutógit add --renormalize ., no se reescribieron EOL de archivos existentes y no se tocó código fuente. Se actualizarondocs/roadmap.mdydocs/evidencias.mdpara reflejar el cierre del bloque de hardening y la rama activa real. - Trabajo realizado por el usuario: definición del contenido conservador del
.gitattributes, decisión de actualizar la documentación en la misma rama para cerrar la deuda documental del bloque previo. - Trabajo realizado por Codex: creación del archivo, verificación de que el resto del working tree no se modifica más allá del ruido EOL esperado en
git status, actualización del roadmap y de evidencias. - Archivos afectados:
.gitattributes(nuevo),docs/roadmap.md,docs/evidencias.md. - Resultado: el repo dispone de una política explícita de finales de línea para futuras contribuciones cross-plataforma, y la documentación viva refleja el estado real post-hardening.
- Validación: revisión manual del contenido de
.gitattributesy del estado degit statuspara confirmar que no se commitean cambios masivos de EOL en archivos ya existentes. - Próximo paso: PR de
chore/add-gitattributes-line-endingsadev, y posteriormente PRdev → maincon el bloque completo de hardening cerrado.
- Objetivo: cerrar el primer bloque de implementación V2 (Fases 2, 3 y 4) y dejar el repositorio con documentación coherente antes de arrancar el backend (Fase 5).
- Trabajo realizado:
- PR #37 (
feat/v2-react-ts-scaffold): scaffold inicial Vite 8 + React 19 + TypeScript 6 enapps/web/. Estructurasrc/app|components|features|lib|styles. Scriptsdev,build,preview,typecheck,lint. Pantalla mínima EXPERTECH CV V2. Verificado: 16 módulos, 333ms. - PR #38 (
feat/v2-domain-models-and-storage): modelos TypeScript de dominio (CandidateProfile,Project,CVMeta,PortfolioCV) ensrc/lib/domain/.SafeStorageServicecon fallbacklocalStorage → sessionStorage → memoria.CVStorageServiceconsave/load/reset/hasStoredCV. Verificado: 20 módulos, 83ms. - PR #39 (
feat/v2-react-auth-and-editor-shell): auth local React con tabs login/registro, layout autenticado dos columnas (editor + preview),ProfileFormcon guardado explícito,CVPreviewcongetVisibleProjects. Port TypeScript deAuthStorageService. Verificado: 28 módulos, 86ms. chore/v2-fase-4-docs-and-polish(esta rama):lang="es"y<title>EXPERTECH CV V2</title>enapps/web/index.html; sustitución del README genérico de Vite por README propio del proyecto; actualización dedocs/roadmap.mdcon Fases 2/3/4 cerradas, limitaciones temporales y siguiente paso; esta entrada endocs/evidencias.md.
- PR #37 (
- Archivos afectados:
apps/web/index.html,apps/web/README.md,docs/roadmap.md,docs/evidencias.md. - Resultado: frontend V2 funcional (register → login → editar perfil → ver preview), documentación coherente con el estado real del repositorio y limitaciones temporales explícitas antes del backend.
- Validación:
npm run typecheck— 0 errores (TypeScript 6,noUnusedLocals,noUnusedParameters)npm run lint— 0 warnings (ESLint 10 flat config)npm run build— build limpio, 28 módulosgit diff --name-only— solo archivos dentro de los permitidos por la micro-rama
- Próximo paso:
feat/v2-backend-api-foundation— backend TypeScript enapps/api/con endpoints mínimos (/health,/auth/*,/cvs/me,/jobs/search) sin base de datos todavía.
- Objetivo: completar el bloque de backend V2 con persistencia real y dejar el frontend plenamente conectado al backend antes de Dockerizar el stack completo en Fase 7.
- Trabajo realizado:
- PR #41 (
feat/v2-backend-api-foundation): backend Express 4 + TypeScript 6 enapps/api/. CORS con allowlist, JSON body parser, 6 routers (/health,/auth,/users,/cvs,/public-profiles,/jobs). Proxy Jooble con contrato estable{ results, fallbackWarning, source }y degradación a mock. Sesiones en memoria (temporal). Frontend:src/lib/api/client.tscon fetch wrapper yVITE_API_URL; badge de estado del backend en el header. - PR #42 (
feat/v2-database-persistence): PostgreSQL 16 en Docker Compose (apps/api/docker-compose.yml, puerto 5435 en host). Prisma 6 con schemaUser / CV / PublicProfile / Session. bcryptjs para hashing de contraseñas en register/login. Sesiones en DB. Aislamiento garantizado porownerIden todas las queries CV/PublicProfile. Frontend rewire completo:App.tsxcon bootstrap async (token →/users/me+/cvs/me),AuthScreenasíncrono,AuthenticatedShellconPublicUser. Eliminadoslib/auth/ylib/storage/del frontend (dead code).
- PR #41 (
- Archivos/carpetas afectadas:
apps/api/(completo, nuevo): scaffold + rutas + Prisma schema + migraciones + docker-composeapps/web/src/lib/api/client.ts: cliente HTTP extendido con auth + CV + token en localStorageapps/web/src/app/App.tsx: bootstrap async, loading state, manejo de 401apps/web/src/features/auth/AuthScreen.tsx,features/cv/AuthenticatedShell.tsx: rewire al backendapps/web/src/lib/auth/yapps/web/src/lib/storage/: eliminados (dead code)docs/,apps/*/README.md: actualizados
- Resultado: el flujo completo register → login → editar CV → ver preview opera contra backend real con PostgreSQL. Dos usuarios distintos no se mezclan por diseño (aislamiento a nivel de aplicación por
ownerId). El legacy vanilla JS sigue funcional e intacto. - Validaciones reportadas:
apps/api:npm run typecheckOK,npm run lintOK,npm run buildOKapps/web:npm run typecheckOK,npm run lintOK,npm run buildOK (26 módulos, 84ms)- Smoke test multi-usuario Alice/Bob con aislamiento correcto (curl end-to-end)
- Limitaciones pendientes: sesiones sin TTL, sin rate limit, sin logs estructurados, token en localStorage, tipos duplicados, PublicProfile sin gestión de slug, falta Docker compose completo para web + api.
- Próximo paso:
feat/v2-docker-compose-local— Dockerizar frontend y backend; un solodocker compose uplevanta el stack completo.
- Objetivo: levantar el stack V2 completo (frontend + backend + base de datos) con un solo
docker compose up --builddesde la raíz del repositorio. - Trabajo realizado:
apps/api/Dockerfile: multi-stage (deps → build → runtime).npm ci --omit=dev,prisma generateynpx tsc. CMD:prisma migrate deploy && node dist/server.js.apps/api/.dockerignore: excluyenode_modules,dist,.env.apps/web/Dockerfile: multi-stage (build con Node → runtime con Nginx alpine). Build conVITE_API_URL=/api(build arg), copiadist/+nginx.conf.apps/web/.dockerignore: excluyenode_modules,dist,.env.apps/web/nginx.conf: sirve SPA contry_files $uri /index.html; proxea/api/*ahttp://api:3002/(stripping de prefijo) con headers estándar.docker-compose.yml(raíz): tres serviciospostgres,api,weben redexpertech_network. Healthchecks en los tres.apidepende depostgreshealthy;webdepende deapihealthy. Volumenexpertech_pg_datamarcado comoexternalpara reutilizar datos de desarrollo.- Corrección durante el proceso:
package.jsondebía copiarse en el stage de build para quetsccon"module":"node16"generara ESM (no CJS) al resolver"type":"module"del package.json. - Ajuste de puerto: frontend expone
8090:80localmente (8080 ocupado por otro contenedor en el equipo de desarrollo).
- Archivos afectados:
apps/api/Dockerfile,apps/api/.dockerignore,apps/web/Dockerfile,apps/web/.dockerignore,apps/web/nginx.conf,docker-compose.yml,README.md,docs/roadmap.md,docs/evidencias.md. - Resultado:
docker compose up --buildlevanta los tres servicios. El frontend sirve la SPA React compilada con Nginx. Las llamadas a/api/*llegan al backend sin URL hardcodeada. Las migraciones Prisma se aplican automáticamente en el arranque del contenedor API. - Validación:
docker compose configOKdocker compose buildOK (ambas imágenes)docker compose up -dOK (todos healthy)curl http://localhost:3002/health→{ status: "ok", storage: "postgres" }curl http://localhost:8090/api/health→ mismo resultado vía Nginx proxycurl http://localhost:8090/→ HTTP 200 (SPA)- Smoke test: register "Docker Test" → guardar CV → recuperar CV vía proxy → users: 3
apps/api: typecheck OK, lint OK, build OKapps/web: typecheck OK, lint OK, build OK (26 módulos, 87ms)
- Limitaciones pendientes: Fase 8 (build reproducible, variables dev/prod separadas, rate limit, cookies httpOnly, logs estructurados, checklist de seguridad pre-deploy).
- Próximo paso:
feat/v2-deployment-readiness(Fase 8).
- Objetivo: dejar el proyecto listo para un despliegue real por una persona ajena, con documentación concreta, código endurecido y checklist de seguridad verificado.
- Trabajo realizado:
- Código (
apps/api/):app.ts: añadidohelmet()(headers HTTP de seguridad) antes del middleware CORS; rate limit de 20 req/IP/15min enPOST /auth/registeryPOST /auth/loginconexpress-rate-limit.lib/password.ts:BCRYPT_ROUNDSahora configurable via env (default 10, recomendado 12 en producción).package.json:helmet@8.1.0yexpress-rate-limit@8.5.2añadidos adependencies..env.example: secciones dev/prod separadas con comentarios explícitos sobre valores seguros.
- Documentación nueva:
docs/deploy-guide.md: guía paso a paso para Railway (backend + PostgreSQL) + Vercel (frontend). Incluye variables de entorno, migraciones automáticas, dominio y rollback.docs/security-checklist.md: checklist con estado actual de cada ítem (✅/⚠️ ) y pendientes documentados.
- Código (
- Archivos afectados:
apps/api/src/app.ts,apps/api/src/lib/password.ts,apps/api/package.json,apps/api/package-lock.json,apps/api/.env.example,docs/deploy-guide.md,docs/security-checklist.md,docs/roadmap.md,docs/evidencias.md. - Resultado: el proyecto dispone de guía de despliegue concreta, checklist de seguridad con estado explícito y código con
helmet+ rate limit activos. - Validaciones:
apps/api: typecheck OK, lint OK, build OKapps/web: typecheck OK, lint OK, build OK (26 módulos, 86ms)
- Limitaciones pendientes (documentadas en checklist): sesiones sin TTL, token en
localStorage(no cookie httpOnly), rate limit en/jobs/search, logs estructurados, backups DB automáticos. - Próximo paso: revisión del plan V2 con el usuario para decidir cierre del legacy vanilla JS y siguientes pasos del proyecto.
- Objetivo: introducir la base visual V2 (Tailwind + tokens de DESIGN.md + Inter + lucide-react) y rediseñar la primera pantalla (Login/Registro) con la estética Stitch antes de portar el resto de la UI.
- Trabajo realizado:
apps/web/tailwind.config.ts: configuración Tailwind v3 con todos los tokens del design system (colores primary/secondary/tertiary/surface/on-surface, tipografía Inter con escala headline/body/label, radios, sombras, spacing 8px-base).apps/web/postcss.config.js: PostCSS con tailwindcss + autoprefixer.apps/web/src/styles/index.css: directivas@tailwind base/components/utilities+ imports de Inter (400/500/600/700 vía@fontsource/inter) + CSS legacy preservado para componentes no migrados (convivencia controlada).apps/web/src/features/auth/AuthScreen.tsx: rediseño completo basado en el mockuplogin_register_expertech_cv. Layout dos columnas (panel oscuro decorativo en desktop + tarjeta de auth). Tabs login/registro, inputs con focus ring primario, toggle de contraseña, alertas de error/éxito con iconos lucide-react, social auth placeholders con SVG inline de Google y GitHub, footer de copyright.package.json/package-lock.json: tailwindcss@3, postcss, autoprefixer como devDeps; @fontsource/inter, lucide-react como deps. Lockfile regenerado con inyección de entradas@emnapiopcionales para compatibilidad Docker Alpine.
- Archivos afectados:
apps/web/package.json,apps/web/package-lock.json,apps/web/tailwind.config.ts,apps/web/postcss.config.js,apps/web/src/styles/index.css,apps/web/src/features/auth/AuthScreen.tsx,apps/web/README.md,docs/roadmap.md,docs/evidencias.md. - Resultado: Tailwind activo, design tokens aplicados, Inter como fuente base. AuthScreen con estética SaaS profesional alineada con Stitch. Lógica de auth intacta (backend real, bcrypt, PostgreSQL).
- Nota técnica de lockfile: npm v11 local poda entradas opcionales de otras plataformas (@emnapi, rolldown WASM) que Docker Alpine necesita. Solución: inyección de esas entradas desde el lockfile original HEAD tras cada regeneración.
- Validaciones:
apps/web: typecheck OK, lint OK, build OK (Tailwind: 25.5 kB CSS generado, 26 módulos)docker compose build webOKdocker compose up -d→ 3 servicios healthy, HTTP 200 en / y /api/health
- Próximo paso:
feat/v2-dashboard-and-editor— Dashboard (bento grid) + Editor CV con acordeones + preview Stitch.
- Objetivo: crear la primera experiencia autenticada V2 alineada con los mockups Stitch en la rama
feat/v2-dashboard-and-editor, sin tocar backend, Docker, Prisma ni legacy vanilla JS. - Contexto de partida: PR #46 ya había introducido Tailwind v3, tokens desde
DESIGN.md, Inter, lucide-react y el rediseño deAuthScreen. - Trabajo realizado:
AuthenticatedShell: navegación interna localDashboard / Editor CV, shell autenticado responsive, logout y badge de backend conservados.Dashboard: layout tipo bento grid con saludo al usuario, estado del backend, métricas derivadas del CV (completitud aproximada, skills, proyectos visibles, última actualización) y acciones rápidas.- Acciones futuras: GitHub, empleo, PDF y perfil público quedan como placeholders visuales “Próximamente”; no implementan features reales.
ProfileForm: editor visual con paneles plegables para perfil profesional, contacto, skills y proyectos; mantiene el contratoonSave(profile)y el flujo de guardado existente.CVPreview: preview portada a Tailwind/Stitch manteniendo datos actuales y reglas de visibilidad de proyectos.apps/web/src/styles/index.css: retirada de estilos manuales sustituidos por Tailwind en shell/editor/preview; se conservan Tailwind imports, Inter yloading-screen.
- Fuera de alcance mantenido: GitHub real, Jobs UI, export PDF, PublicProfile, landing, backend, Prisma, Docker, package files y legacy (
js/**,styles/**). - Validación prevista antes de cerrar:
apps/web:npm run typecheck,npm run lint,npm run build- raíz:
docker compose build web,docker compose up -d,curl http://localhost:8090,curl http://localhost:8090/api/health,docker compose down
- Próximo sprint recomendado:
feat/v2-github-integration.
- Objetivo: portar a V2 la integración GitHub pública del legacy en la rama
feat/v2-github-integration, sin OAuth, sin tokens, sin backend proxy y sin tocar legacy. - Contexto de partida: PR #46 dejó Tailwind/Stitch/AuthScreen; PR #47 dejó Dashboard, Editor CV y Preview autenticados en Tailwind/Stitch.
- Trabajo realizado:
apps/web/src/lib/github/: cliente tipado paraGET /users/:usernameyGET /users/:username/repos, normalización de respuestas, detección de errores HTTP y rate limit público.- Transformación
repo → Project: nombre, descripción, lenguaje como stack,repoUrl,homepagecomo demo y metadatos de origen GitHub (sourceProvider,sourceRepositoryFullName,sourceImportedAt, etc.). apps/web/src/features/github/: UI GitHub Sync con estados idle, loading, success, empty, error y rate limited.- Integración autenticada: nueva vista interna
GitHubsin router; el Dashboard abre la vista desde “Sincronizar GitHub”. - Importación: los repos seleccionados se añaden al CV sin borrar proyectos existentes y evitando duplicados por
sourceRepositoryFullName; el guardado usa el flujo existenteonCVUpdate→PUT /cvs/me.
- Fuera de alcance mantenido: OAuth GitHub, login con GitHub, backend GitHub proxy, tokens GitHub, Jobs UI, PDF, PublicProfile, landing, backend, Prisma, Docker y legacy (
js/**,styles/**). - Validación prevista antes de cerrar:
apps/web:npm run typecheck,npm run lint,npm run build- raíz:
docker compose build web,docker compose up -d,curl http://localhost:8090,curl http://localhost:8090/api/health,docker compose down - smoke recomendado: buscar un usuario público, seleccionar repos e importar al CV.
- Próximo sprint recomendado:
feat/v2-jobs-and-pdfo separar primerofeat/v2-jobs-search.
- Objetivo: portar a V2 solo la UI de búsqueda de empleo tech en la rama
feat/v2-jobs-search, consumiendo el endpoint backend existente/jobs/search. - Contexto de partida: PR #46 dejó Tailwind/Stitch/AuthScreen; PR #47 dejó Dashboard/Editor/Preview; PR #48 dejó GitHub Sync público sin OAuth.
- Contrato usado:
GET /jobs/search?keywords=<texto>&location=<texto>keywordses obligatorio.- Respuesta estable:
{ results, fallbackWarning, source }. sourcepuede serjoobleomock; siJOOBLE_API_KEYno está configurada, el backend devuelve mock/fallback.
- Trabajo realizado:
apps/web/src/lib/api/client.ts: tipos frontend mínimos paraJobOffer,JobsSearchResponsey funciónapi.jobs.search.apps/web/src/features/jobs/: UI Jobs Search con formulario keywords/location, chips rápidos, tarjetas de resultados y estados idle/loading/success/empty/error.AuthenticatedShell: nueva vista internajobssin router y navegación “Empleo”.Dashboard: acción “Buscar empleo” activa y conectada a la vista Jobs.- Aviso visual cuando la respuesta viene de mock/fallback Jooble.
- Fuera de alcance mantenido: guardar ofertas favoritas, aplicar a ofertas, alertas, PDF, PublicProfile, landing, backend nuevo, Prisma, Docker y legacy (
js/**,styles/**). - Validación prevista antes de cerrar:
apps/web:npm run typecheck,npm run lint,npm run build- raíz:
docker compose build web,docker compose up -d,curl http://localhost:8090,curl http://localhost:8090/api/health,curl "http://localhost:8090/api/jobs/search?keywords=react&location=Bilbao",docker compose down
- Próximo sprint recomendado:
feat/v2-export-pdf.
- Objetivo: portar a V2 la exportación de CV a PDF en la rama
feat/v2-export-pdf, usando impresión nativa del navegador y sin implementar todavía PublicProfile real ni Landing. - Contexto de partida: PR #46 dejó Tailwind/Stitch/AuthScreen; PR #47 dejó Dashboard/Editor/Preview; PR #48 dejó GitHub Sync público; PR #49 dejó Jobs Search V2.
- Decisión técnica:
- Se usa
window.print()y CSS@media print. - Se evita
jsPDFy cualquier generación PDF binaria. - El QR se genera localmente en frontend con
qrcode, sin servicios externos. - Al no existir aún gestión de slug público real, la URL planificada usa
/p/<githubUsername-o-nombre-normalizado>.
- Se usa
- Trabajo realizado:
apps/web/src/lib/qr/: helper de QR local y helper de URL pública planificada.apps/web/src/features/export/: panel Exportar PDF, preview imprimible, bloque QR y acción de impresión.AuthenticatedShell: nueva vista internaexportsin router y navegación “Exportar”.Dashboard: acción “Exportar PDF” activa y conectada a la vista Export.apps/web/src/styles/index.css: estilos print mínimos para imprimir solo el área imprimible.
- Fuera de alcance mantenido: PublicProfile real, landing, backend nuevo, Prisma, Docker, legacy (
js/**,styles/**),jsPDF, generación PDF binaria y plantillas múltiples. - Validación prevista antes de cerrar:
apps/web:npm run typecheck,npm run lint,npm run build- raíz:
docker compose build web,docker compose up -d,curl http://localhost:8090,curl http://localhost:8090/api/health,docker compose down
- Próximo sprint recomendado:
feat/v2-public-profile.
- Objetivo: implementar perfil público V2 real en la rama
feat/v2-public-profile, conectando la URL/p/:slugcon el modelo PrismaPublicProfileexistente. - Contexto de partida: PR #46 dejó Tailwind/Stitch/AuthScreen; PR #47 Dashboard/Editor/Preview; PR #48 GitHub Sync; PR #49 Jobs Search; PR #50 Export PDF con QR local apuntando a
/p/<slug>. - Backend:
GET /public-profiles/meprotegido por Bearer para leer configuración pública del usuario.PUT /public-profiles/meprotegido por Bearer para guardar slug y publicar/despublicar.GET /public-profiles/:slugsigue siendo público y solo devuelve CV siisPublic = true.- Reutiliza el modelo Prisma existente
PublicProfile; no requiere cambio de schema ni migración. - Slug normalizado y validado en backend: minúsculas, números, guiones, mínimo 3 y máximo 60 caracteres.
- Frontend:
App.tsxdetecta/p/:slugsin React Router y renderiza una página pública sin exigir login.- Nueva feature
public-profile/: página pública read-only, empty states y panel autenticado de publicación. AuthenticatedShellañade vista interna “Público”; Dashboard activa la acción “Perfil público”.- Export PDF consulta la configuración pública y conecta el QR a
/p/:slugreal cuando el perfil está publicado.
- Decisión de privacidad: la página pública muestra los datos incluidos en el CV guardado, incluyendo email/teléfono si el usuario los ha rellenado y publica el perfil.
- Fuera de alcance mantenido: landing, custom themes, analytics, SEO avanzado, OpenGraph avanzado, dominio personalizado, Auth/OAuth nuevo, Docker, Prisma schema, legacy removal (
js/**,styles/**). - Validación prevista antes de cerrar:
apps/api:npm run typecheck,npm run lint,npm run buildapps/web:npm run typecheck,npm run lint,npm run build- raíz:
docker compose build,docker compose up -d,curl http://localhost:8090,curl http://localhost:8090/api/health,docker compose down
- Próximo sprint recomendado:
feat/v2-landing-page.
- Objetivo: documentar la paridad funcional entre el legacy vanilla JS y la V2 React/TypeScript antes de decidir si archivar o retirar legacy.
- Archivos revisados:
- Legacy:
index.html,public.html,js/application/AppRuntime.js,js/application/AuthenticatedCVApp.js,js/application/PublicPageRuntime.js,js/ui/AuthScreen.js,js/ui/AuthScreenTemplate.js,js/ui/GitHubIntegration.js,js/ui/GitHubBlockTemplate.js,js/ui/PreviewRenderer.js,js/ui/PreviewTemplate.js,js/ui/PrintCVRenderer.js,js/ui/PrintCVTemplate.js,js/ui/PublicCVRenderer.js,js/ui/JobSearchIntegration.js,js/services/AuthStorageService.js,js/services/GitHubProfileService.js,js/services/JobOffersService.js,js/services/PublicCVDataService.js,js/models/PortfolioCV.js,js/models/Project.js,styles/reset.css. - V2:
apps/web/src/app/App.tsx, featuresauth,cv,github,jobs,export,public-profile,apps/web/src/lib/api/client.ts,apps/api/src/routes/**,apps/api/prisma/schema.prisma. - Documentación:
docs/roadmap.md,docs/evidencias.md,apps/web/README.md,apps/api/README.md.
- Legacy:
- Resultado:
- V2 cubre el núcleo legacy y lo supera en backend real, PostgreSQL/Prisma, multiusuario, Docker, Tailwind/Stitch, perfil público real y QR conectado a
/p/:slug. - Estado global propuesto: Casi lista, quedan gaps menores.
- Gap bloqueante principal para retirar legacy: falta una landing V2 que sustituya la entrada pública/demo del legacy.
- V2 cubre el núcleo legacy y lo supera en backend real, PostgreSQL/Prisma, multiusuario, Docker, Tailwind/Stitch, perfil público real y QR conectado a
- Recomendación: mantener legacy vivo y read-only hasta cerrar
feat/v2-landing-page; después ejecutarchore/v2-final-demo-audity decidir entre archivar o retirar. - Próximo paso:
feat/v2-landing-page.
- Objetivo: implementar la landing pública V2 en la rama
feat/v2-landing-pagepara cerrar el gap principal detectado en la auditoría de paridad. - Trabajo realizado:
- Nueva feature
apps/web/src/features/landing/con hero, features, how-it-works, showcase visual y CTA final. App.tsxmantiene/p/:slugcomo ruta pública prioritaria y muestra Landing en/para usuarios no autenticados.- Los CTAs “Crear mi CV”, “Entrar” y “Empezar ahora” abren AuthScreen sin instalar router ni tocar backend.
- Se conserva el flujo autenticado existente: tras login/register se renderiza
AuthenticatedShell.
- Nueva feature
- Archivos afectados:
apps/web/src/app/App.tsx,apps/web/src/features/landing/LandingPage.tsx,README.md,apps/web/README.md,docs/roadmap.md,docs/evidencias.md,docs/audits/v2-legacy-parity-audit.md. - Resultado: V2 ya dispone de una entrada pública principal en
/, manteniendo/p/:slugy dejando legacy vivo hasta la auditoría final. - Validación prevista:
apps/web:npm run typecheck,npm run lint,npm run build- raíz:
docker compose build web,docker compose up -d,curl http://localhost:8090,curl http://localhost:8090/api/health,docker compose down
- Próximo paso:
chore/v2-final-demo-audit.
- Objetivo: validar si la V2 está lista para sustituir funcionalmente al legacy como demo principal antes de archivar legacy como read-only.
- Validaciones ejecutadas:
apps/api:npm run typecheck,npm run lint,npm run build.apps/web:npm run typecheck,npm run lint,npm run build.- raíz:
docker compose build,docker compose up -d,docker compose ps,curl http://localhost:8090,curl http://localhost:8090/api/health,curl http://localhost:8090/p/slug-inexistente,docker compose down. - Smoke semi-automatizado por API: register/login/logout, guardado de CV, Jobs Search, publicación/despublicación de PublicProfile y consulta pública.
- GitHub público:
octocatresponde200en perfil y repositorios desdeapi.github.com.
- Resultado:
- Estado global: Lista con observaciones menores.
- No se detectan bloqueantes técnicos.
- Docker local queda sano con web, api y postgres en
healthy. - Jobs Search responde con
source=mock, comportamiento esperado si Jooble no está configurado. - PublicProfile publica con
200y deja de mostrar el CV con404al despublicar.
- Hallazgos:
- Pendiente una revisión visual manual en navegador para CTA, Dashboard, Editor, selección GitHub e impresión nativa.
- Preview V2 se sincroniza al guardar, no con live typing exacto.
- Legacy sigue presente y debe archivarse read-only, no eliminarse.
- Recomendación: V2 puede ser demo principal; siguiente sprint
chore/archive-legacy-readonly. - Próximo paso: abrir PR de
chore/v2-final-demo-auditcontradev.
- Objetivo: marcar formalmente el legacy vanilla JS como read-only sin borrar, mover ni modificar archivos legacy.
- Documentos creados/modificados:
docs/legacy/legacy-readonly.md: estado, alcance, reglas read-only, archivos legacy y próxima decisión futura.docs/legacy/README.md: índice breve del estado legacy.docs/decisions/ADR-legacy-readonly.md: decisión arquitectónica de mantener legacy en sitio y documentarlo como read-only.README.md,apps/web/README.md,apps/api/README.md,docs/roadmap.md,docs/evidencias.md.
- Decisión:
- V2 pasa a ser la demo principal.
- Legacy queda como referencia histórica/read-only.
- No se implementan nuevas features en
index.html,public.html,js/**,styles/**,server/**nidata/**. - No se borra ni se mueve legacy en este sprint.
- Fuera de alcance: código, backend, frontend, Docker, Prisma,
docs/specs/**, borrado de legacy, movimiento de legacy y fixes funcionales. - Próximo paso:
chore/v2-final-cleanup-and-release-notes;chore/remove-legacy-after-v2-parityqueda reservado para una decisión explícita futura.
- Objetivo: crear la documentación final de cierre V2 para presentar EXPERTECH CV como demo principal.
- Documentos creados:
docs/releases/v2-demo-release-notes.md: resumen de release, funcionalidades incluidas, arquitectura, validaciones, limitaciones y próximos pasos.docs/releases/v2-demo-checklist.md: checklist operativo para preparar y ejecutar la demo.
- Documentos actualizados:
README.mdapps/web/README.mdapps/api/README.mddocs/roadmap.mddocs/evidencias.mddocs/legacy/README.mddocs/legacy/legacy-readonly.mddocs/audits/v2-final-demo-audit.md
- Decisión: V2 queda documentada como demo principal; legacy sigue read-only y no se elimina.
- Fuera de alcance: código, backend, frontend, Docker, Prisma, legacy real, specs, deploy y retirada legacy.
- Próximo paso recomendado:
chore/v2-demo-manual-browser-pass,test/e2e-v2-demo-flowodeploy/v2-stagingsegún prioridad.