EXPERTECH CV es un proyecto frontend orientado a la creación de un currículum web interactivo para perfiles tech. Nace como MVP del módulo de JavaScript del bootcamp y se plantea como la base inicial de una evolución futura hacia EXPERTECH JOB.
Estado actual: V2 demo principal cerrada documentalmente + legacy read-only
Fase actual: chore/v2-final-cleanup-and-release-notes (release notes y checklist final de demo V2)
V2 es la demo principal del proyecto. Incluye React + TypeScript, backend Express, PostgreSQL + Prisma, Docker local, Landing Page pública en /, AuthScreen, Dashboard, Editor CV, GitHub Sync, Jobs Search, exportación PDF/QR y PublicProfile en /p/:slug.
El MVP legacy en vanilla JS queda conservado como referencia histórica en modo read-only. No se borra todavía y no debe recibir nuevas features.
| Área | Ubicación | Estado |
|---|---|---|
| Frontend V2 | apps/web |
Demo principal |
| Backend V2 | apps/api |
Backend principal |
| Docker local V2 | docker-compose.yml |
Stack principal |
| Legacy vanilla JS | raíz, index.html, public.html, js/**, styles/**, server/**, data/** |
Read-only |
Ver también:
Requisitos: Docker y Docker Compose.
# Desde la raíz del repo:
docker compose up --build # primera vez (construye imágenes)
docker compose up -d # arranques posteriores (en background)Servicios levantados:
| Servicio | URL local | Descripción |
|---|---|---|
web |
http://localhost:8090 | Frontend React servido por Nginx |
api |
http://localhost:3002 | Backend Express (acceso directo, dev) |
postgres |
localhost:5435 | PostgreSQL (acceso directo, dev) |
Nota: el frontend V2 se expone actualmente en
8090:80. Si ese puerto está ocupado en tu máquina, ajusta el mapeo de puertos local antes de levantar el stack.
# Parar el stack (conserva el volumen de DB):
docker compose down
# Parar y borrar el volumen (reset total de datos):
docker compose down -vEl comportamiento funcional del MVP sigue intacto: maqueta visual navegable, auth local básica para MVP con login/register, persistencia de usuarios y sesión en localStorage con fallback automático a sessionStorage o memoria, restauración de sesión al recargar, formulario funcional de perfil conectado al estado, preview recruiter-friendly sincronizada en tiempo real, integración pública básica con GitHub para enriquecer el CV con perfil y repositorios seleccionados manualmente, visualización dinámica de proyectos en la preview, trazabilidad mínima del origen de proyectos importados desde GitHub, sistema de avatar híbrido (local y GitHub) con límites de tamaño para evitar QuotaExceededError, exportación PDF basada en una vista específica de impresión con QR y una demo pública estática. Además, el bloque de búsqueda de empleo está conectado a Jooble mediante proxy local con degradación a mock cuando falla la API, contrato estable { results, fallbackWarning, source } y URL del proxy parametrizable (sin localhost:3001 hardcodeado en el frontend).
La meta de esta primera versión es permitir que una persona pueda:
- introducir y editar sus datos profesionales
- organizar su perfil como CV digital
- visualizar el resultado en formato web
- persistir la información en
localStorage - enriquecer el CV con información básica de GitHub
- preparar una presentación clara para recruiters
Fuera de alcance en esta fase:
- backend
- base de datos
- autenticación real
- panel recruiter multiusuario
- despliegue full-stack
- HTML5
- CSS3
- JavaScript
- arquitectura modular por capas simples:
application,ui,services,models,utils - Git y GitHub como flujo de control de versiones
.
|-- assets/
| |-- icons/
| `-- images/
|-- data/
| `-- public-cv.json
|-- docs/
| |-- docs_V2/
| |-- architecture-notes.md
| |-- evidencias.md
| |-- EXPERTECH_CV_hoja_de_ruta.md
| |-- git_guia_practica.md
| |-- roadmap.md
| `-- v2-react-backend-docker-plan.md
|-- js/
| |-- application/
| |-- models/
| |-- services/
| | `-- SafeStorageService.js
| |-- ui/
| |-- utils/
| | `-- projects.js
| |-- README.md
| |-- app.js
| `-- public.js
|-- server/
| |-- services/
| |-- README.md
| |-- package.json
| `-- server.js
|-- styles/
| |-- main.css
| |-- reset.css
| `-- README.md
|-- .gitattributes
|-- AGENTS.md
|-- index.html
|-- public.html
`-- README.md
- Hoja de ruta del proyecto
- Evidencias de desarrollo
- Guía práctica de Git
- Notas de arquitectura
- Roadmap operativo
- Plan V2 · React + TypeScript + Backend + Docker
- Release notes demo V2
- Checklist de demo V2
Documentación viva recomendada para seguir el estado real del repositorio:
README.mddocs/roadmap.mddocs/evidencias.mddocs/legacy/legacy-readonly.mddocs/releases/v2-demo-release-notes.mddocs/releases/v2-demo-checklist.mddocs/v2-react-backend-docker-plan.mdpara entender la dirección estratégica hacia V2
La hoja de ruta larga de docs/EXPERTECH_CV_hoja_de_ruta.md se mantiene como referencia estratégica del proyecto, no como fuente operativa principal del día a día.
La estrategia de ramas busca mantener orden, trazabilidad y aprendizaje práctico:
main: rama estable y publicabledev: rama de integraciónfeat/*ofeature/*: ramas de trabajo por funcionalidad
Flujo recomendado:
- partir de
dev - crear la rama de la feature activa
- desarrollar, validar y documentar en esa rama
- integrar en
dev - pasar a
mainsolo cuando el bloque esté estable
En este proyecto se está priorizando crear cada rama solo cuando vaya a utilizarse, para evitar ruido y mantener un proceso más didáctico.
La demo principal es V2. Para revisarla en local:
docker compose up --buildDespués abre http://localhost:8090.
El legacy sigue disponible para consulta histórica:
index.htmlpublic.htmljs/**styles/**server/**data/**
No lo modifiques en nuevas features salvo decisión específica.
Importante para la demo pública:
public.htmlcargadata/public-cv.jsonmediantefetch()- por eso debe validarse con servidor estático, Live Server o GitHub Pages
- abrir
public.htmlconfile://puede fallar aunque el código esté correcto
Comportamiento actual disponible:
- carga de una pantalla principal ya maquetada
- aplicación de estilos desde
styles/reset.cssystyles/main.css - layout responsive con bloques apilados en móvil
- distribución
editorizquierda /previewderecha en desktop - preview sticky solo en escritorio
- carga del script
js/app.jscon estado inicial del CV - factories base para
CandidateProfile,ProjectyPortfolioCV - creación de un estado inicial consistente mediante
createInitialCVState() - persistencia básica del CV en
localStorage - recuperación del CV guardado al volver a cargar la app
- utilidades mínimas de depuración expuestas en
window.cvAppDebug - formulario de perfil funcional en la columna de edición
- rehidratación del formulario al recargar la app
- feedback visual de guardado tras enviar el formulario
- render en vivo de nombre, titular y resumen en la preview
- sincronización inicial de la preview con el estado cargado desde
localStorage - fallbacks visuales cuando faltan datos del perfil
- ocultación automática del estado vacío de la preview cuando ya existe contenido real
- búsqueda de perfil público de GitHub desde un bloque independiente del formulario manual
- carga de perfil GitHub con avatar, nombre visible, bio y enlace público
- carga de repositorios candidatos y selección manual de repos destacados
- persistencia de
githubUsernamey de proyectos generados desde repositorios seleccionados - rehidratación del bloque GitHub a partir del estado persistido, manteniendo el flujo manual como fallback si la API falla
- render dinámico de proyectos destacados en la preview a partir de
cvState.projects - priorización de proyectos marcados como
featuredcuando existen - visualización de nombre, descripción, stack y enlaces dentro de cards de proyecto
- empty-state específico cuando no hay proyectos visibles en la preview
- persistencia de metadatos mínimos de origen para proyectos importados desde GitHub
- línea visual compacta de origen en la preview, por ejemplo
GitHub · owner/repo - limpieza del proyecto demo legado para que el bloque de proyectos no muestre contenido fantasma al quitar la selección GitHub
- pantalla de acceso con tabs de
login/register - registro local con email + contraseña y creación automática de sesión
- login local con email + contraseña
- persistencia de usuarios y sesión en
localStorage - restauración de sesión al recargar la aplicación
- logout visible y funcional desde la app autenticada
- botones visibles de Google y GitHub solo como preparación visual del siguiente MVP
- mensajes informativos en esos botones, sin OAuth real ni autenticación externa implementada
- sistema de avatar híbrido (subida de imagen local con resize por canvas o lectura desde GitHub)
- demo pública estática (
public.html) alimentada pordata/public-cv.json - runtime público modular para desacoplar la demo del
localStoragedel editor
- entra en la pantalla de acceso
- crea una cuenta local o inicia sesión con email y contraseña
- la sesión se restaura automáticamente si sigue existiendo en
localStorage - una vez autenticado, accede a la app principal del CV
- puede editar perfil, conectar GitHub, seleccionar repositorios y ver proyectos en la preview
La arquitectura actual ya no concentra toda la orquestación en app.js.
js/app.js: entry point mínimo y composition rootjs/application/AppRuntime.js: coordina auth, sesión, arranque global y logoutjs/application/AuthenticatedCVApp.js: coordina la app autenticada, el estado del CV y la sincronización entre módulosjs/application/PublicPageRuntime.js: coordina la demo pública estática del CVjs/services/: persistencia del CV, auth local MVP y servicios externos como GitHubjs/ui/: controladores UI y templates reutilizables
Templates UI ya extraídos del HTML principal:
js/ui/AuthScreenTemplate.jsjs/ui/PreviewTemplate.jsjs/ui/GitHubBlockTemplate.js
Esto deja index.html más cerca de un shell base y hace más clara la separación entre:
- auth / sesión
- estado del CV
- integración GitHub
- render visual
feat/project-setup: preparar la base del proyectofeat/layout-base: construir la arquitectura visual editor + previewfeat/domain-model: definir el modelo de datosfeat/local-storage: persistir el estado del CVfeat/editor-profile: crear formularios y edición del perfilfeat/live-preview: reflejar cambios en tiempo realfeat/github-integration: integrar perfil público y repositorios básicos desde GitHubfeat/projects-visualization: mejorar lectura y visualización de proyectos seleccionadosfeat/login-screen: preparar una pantalla de acceso y base de identidad de usuariofeat/github-project-sources: ampliar fuentes GitHub y atribución de proyectosfeat/export-pdf-qr: exportación PDF con vista específica de impresiónfeat/github-pages-public-preview: demo pública estática preparada para GitHub Pagesfeat/jooble-search-proxy-mvp: buscador de ofertas con proxy local y fallback mock- Bloque de hardening sobre
dev(PRs #22 a #30): listeners estables, proxy de jobs endurecido, fallback de storage, retirada de docs con secretos, refactor de utilidades de proyectos y.gitattributes docs/add-v2-react-backend-docker-plan: contrato técnico de migración a V2
Estado funcional adicional consolidado a partir del MVP base:
- PR #22
fix/stabilize-authenticated-app-listeners: separación limpia de listeners y soporte de re-login sin duplicar bindings - PR #23/#24 limpieza de
.claude/local en el repo - PR #25
fix/jobs-proxy-contract-and-security: contrato estable deJobOffersService, eliminación de_fallbackWarningsobre arrays, supresión delocalhost:3001hardcodeado en frontend, CORS configurable y rate limit en el backend - PR #26
security/remove-exposed-jooble-key-and-local-docs: retirada de documentación local con API key - PR #27
fix/storage-fallback-and-quota-handling:SafeStorageServicecon fallbacklocalStorage → sessionStorage → memoriay límites de avatar enProfileEditor - PR #28 limpieza secundaria de docs locales reintroducidas
- PR #29
refactor/extract-project-rendering-utils: extracción deisRenderableProjectygetVisibleProjectsajs/utils/projects.jscomo única fuente de verdad - PR #30
chore/add-gitattributes-line-endings:.gitattributesconservador y documentación viva al día
La última feature documental abierta sobre dev es docs/add-v2-react-backend-docker-plan, que añade el plan técnico explícito de la V2 del proyecto: migración a React + TypeScript, backend real con APIs, base de datos PostgreSQL, Dockerización y preparación de despliegue.
Sigue quedando fuera de este cierre:
- implementación real de cualquier fase V2
- backend serio con autenticación de producción
- base de datos y persistencia multiusuario
- Dockerización del stack
- despliegue real
Las features feat/github-integration, feat/projects-visualization, feat/login-screen, feat/github-project-sources, feat/export-pdf-qr, feat/github-pages-public-preview y feat/jooble-search-proxy-mvp dejan una base MVP sólida que el bloque de hardening posterior ha endurecido en estabilidad, seguridad y limpieza: auth local de demostración, integración pública con GitHub, representación recruiter-friendly de proyectos, trazabilidad mínima del origen importado, avatar híbrido con límites, exportación PDF útil, demo pública estática y buscador de empleo con proxy local seguro y contrato estable.
Limitaciones del legacy (aplican al MVP vanilla JS en la raíz, no a V2):
- la auth del legacy es local y orientada a demo; las contraseñas del legacy se guardan en
localStorageen texto plano (limitación explícita del MVP) - Google y GitHub no implementan OAuth real todavía en ninguna versión
- el
server/de la raíz es un proxy mínimo para Jooble; no es backend de producción - no hay validación avanzada de autoría o atribución en proyectos GitHub en el legacy
- no hay soporte para múltiples cuentas GitHub ni colaboraciones en esta fase
Limitaciones del backend V2 (apps/api/) post-Fase 6:
- contraseñas hasheadas con bcrypt; backend no guarda texto plano
- persistencia real en PostgreSQL con aislamiento por usuario (
ownerId) - sesiones en DB sin expiración automática todavía (Fase 8)
- sin rate limit ni logs estructurados todavía (Fase 8)
- token Bearer del frontend en
localStorage(migración a cookie httpOnly en Fase 8) - Docker Compose solo tiene el servicio de DB; frontend y backend todavía no dockerizados (Fase 7)
Orden recomendado a partir del estado actual:
- mergear el PR documental
docs/add-v2-react-backend-docker-planadev - abrir rama
chore/reconcile-main-before-v2para reconciliar la divergenciamain ↔ devy promocionar el MVP saneado amain - comenzar la Fase 2 del plan V2 (
feat/v2-react-ts-scaffold) sobre la baseline ya alineada
Siguiente bloque de trabajo según el plan V2:
chore/v2-demo-manual-browser-pass: revisión visual/manual final de la demo.test/e2e-v2-demo-flow: opcional, cubrir el flujo demo con tests E2E.deploy/v2-staging: opcional, preparar una URL pública/staging.chore/remove-legacy-after-v2-parity: retirar legacy solo con decisión explícita posterior.
Cada fase se ejecuta en su rama, con PR contra dev y validación mínima documentada. Consulta docs/v2-react-backend-docker-plan.md para el detalle completo.
David López Sotelo