Caso de estudio
Este sitio: mi CV
CV estático bilingüe (Astro + Tailwind CSS) que expone 19 tools WebMCP a agentes de IA, hace búsqueda semántica en el dispositivo (multilingual-e5-small sobre WebAssembly) y publica llms.txt, mcp.json y agent.json, sin backend: cada tool, búsqueda y CV corre en el navegador con resume.json.
- Empresa
- Oscar Arenas
- Periodo
- 2025 – actualidad
- Mi rol
- Diseño, ingeniería y contenido
El problema
Los reclutadores y sus agentes de IA necesitan datos del CV que puedan leer, verificar y consultar, no solo un PDF.
Enfoque y arquitectura
Un único módulo de datos tipado alimenta todas las superficies (página, JSON-LD, resume.json, archivos del CV y tools para agentes); la búsqueda y las tools corren en el navegador contra los datos publicados.
-
Datos
- resume.ts y projects.ts: contenido tipado y bilingüe
- Validación con un esquema Zod antes de cada build (npm run validate)
-
En el build
- Embeddings de los pasajes calculados con multilingual-e5-small (int8)
- Astro genera las páginas EN/ES con JSON-LD, resume.json, llms.txt y tarjetas sociales
- Archivos del CV: Puppeteer imprime el PDF y html-to-docx genera el Word
-
Hosting
- Firebase Hosting sirve el build estático; el sitio no necesita un servidor de aplicación para funcionar
-
En el navegador
- Las tools WebMCP y los formularios HTML normales trabajan sobre los datos publicados
- Búsqueda semántica en un Web Worker: Transformers.js solo procesa la consulta del visitante
Cada paso es un archivo o un script del repositorio de este sitio.
Arquitectura
- Sitio estático en Astro, en inglés y español; un único módulo de datos tipado (resume.ts) alimenta el HTML, el JSON-LD, resume.json, los generadores de PDF/DOCX y las tools para agentes.
- 19 tools WebMCP: 16 tools imperativas (consultas de solo lectura y acciones de página) registradas con document.modelContext en un solo lote todo-o-nada y expuestas también como window.oscarResume, más 3 tools declarativas <form toolname> para las acciones que envía una persona (llamada, descarga del CV, contacto).
- Búsqueda semántica en el dispositivo: los embeddings de los pasajes (multilingual-e5-small, int8) se calculan en el build y en el navegador solo se procesa la consulta del visitante, con Transformers.js sobre WebAssembly (WASM), en un Web Worker.
- Descubrimiento para agentes sin navegador: llms.txt y llms-full.txt, resume.json con el contrato de las tools, .well-known/agent.json y la tarjeta .well-known/mcp.json del servidor MCP remoto de solo lectura.
- Sin backend: Firebase Hosting sirve archivos estáticos; cada tool, búsqueda y CV corre en el navegador. El Worker de Cloudflare es opcional y solo retransmite el formulario de contacto y replica las tools por MCP.
- Generación del CV: Puppeteer imprime la ruta /print/ a PDF (una versión general y dos por enfoque) y html-to-docx genera el archivo Word, en ambos idiomas, en cada versión; todos ellos, y el CV en Markdown, salen de un único modelo del CV (scripts/lib/cv-model.ts).
- Controles de calidad: pruebas unitarias con Vitest (incluido un presupuesto de 1,5K caracteres por salida de tool), pruebas end-to-end y de accesibilidad (axe) con Playwright, presupuestos de Lighthouse CI y una verificación de regresiones del CV, en GitHub Actions.
Decisiones clave y sus compromisos
- WebMCP y no scraping: un agente que llama a tools tipadas obtiene datos exactos y verificables y puede actuar (encaje, CV a medida, una solicitud de llamada preparada) en lugar de adivinar a partir del HTML; las anotaciones le dicen qué tools son de solo lectura.
- Embeddings en el dispositivo y no una API: la oferta pegada nunca sale del navegador, no hay clave que filtrar ni factura que vigilar, y el modelo de ~135 MB solo se descarga cuando el visitante lo pide (nunca sin consentimiento con ahorro de datos o una conexión medida).
- Tools declarativas solo para los formularios que envía una persona (contacto, llamada, descarga del CV): el navegador los rellena y el visitante pulsa el botón, así nada se envía en silencio; cada consulta de solo lectura es una tool imperativa que un agente puede ejecutar sin confirmación.
- Sin backend por defecto: todo corre en el navegador contra resume.json, así que el sitio sigue funcionando sin un servidor que mantener; el Worker de Cloudflare es opcional.
- El JSON-LD se genera con los mismos datos que la página, así buscadores y agentes ven los mismos datos que las personas.
- Un esquema Zod valida los datos del CV antes de cada build, así las fechas rotas o las traducciones faltantes detienen el build en lugar de publicarse.
- Construido con programación y revisión asistidas por IA (Claude Code), con TypeScript estricto y esa validación del contenido antes de cada build.
Resultado
19 tools para agentes y CV en 2 idiomas en PDF (3 versiones por enfoque), Word y Markdown, generados con los mismos datos en cada versión.
Datos clave
- 19 tools para agentes
- 2 idiomas, 10 archivos de CV por versión (6 PDF, 2 Word, 2 Markdown)
- Lighthouse Agentic Browsing: {{LIGHTHOUSE_AGENTIC}}
Tomados del CV, sin estimaciones.
Mi rol
Diseño, ingeniería y contenido
Stack
- Astro
- TypeScript
- Tailwind CSS
- Transformers.js
- WebMCP
- JSON-LD
- Puppeteer
- Playwright
- Vitest
- GitHub Actions
- Lighthouse CI
- Firebase Hosting
Enlaces
- Sitio en vivo resume-oscarenas.web.app/