Detrás de escena
Cómo construí este sitio
Este sitio también es parte de mi portafolio: el mismo enfoque de entrega automatizada e infraestructura como código que ofrezco a mis clientes, aplicado aquí. Todo el código es público.
Arquitectura
Un sitio estático servido desde el borde de Cloudflare, con tres funciones pequeñas para lo que necesita un servidor.
- Astro genera HTML estático en español (raíz) e inglés (/en/), con Tailwind CSS. No hay base de datos.
- El contenido (servicios, proyectos, perfil, testimonios) son archivos YAML en el repositorio, validados con esquemas: contenido inválido rompe el build. Lo edito desde un panel de administración (Keystatic) con inicio de sesión de GitHub: cada cambio guardado es un commit que se despliega solo.
- El CV en PDF y las imágenes Open Graph se generan en cada build a partir del mismo contenido, así que nunca se desactualizan.
- Cloudflare Pages sirve el sitio en *.pages.dev. Tres Pages Functions: /api/contact valida el formulario, verifica Turnstile y envía el correo con Resend; /api/event guarda los eventos de conversión en Workers Analytics Engine; /api/keystatic da el inicio de sesión con GitHub del panel.
- Analítica sin cookies con Cloudflare Web Analytics, por eso no hay banner de consentimiento.
Pipeline
GitHub Actions verifica cada cambio antes de publicarlo.
- Lint (ESLint y Prettier), chequeo de tipos y pruebas unitarias (Vitest) de los manejadores HTTP.
- Lighthouse CI en cada página: falla por debajo de 95 en rendimiento.
- Pruebas end-to-end con Playwright sobre el build de producción: rutas en ambos idiomas, formulario, eventos de conversión, accesibilidad con axe, SEO y una guarda de privacidad que busca teléfonos y nombres de clientes en el HTML y el PDF.
- En cada pull request: tofu fmt, validate y plan (publicado en el PR) y un despliegue de vista previa con su propia URL.
- Al fusionar en main: tofu apply y despliegue a producción.
Infraestructura como código
OpenTofu define todo lo que el sitio necesita en Cloudflare, en infra/.
- El proyecto de Cloudflare Pages y la configuración de sus funciones: secretos como variables de entorno (incluida la clave que cifra la sesión del panel, generada por OpenTofu) y el dataset de Analytics Engine.
- El widget de Turnstile (protección contra spam sin CAPTCHAs molestos), cuya clave secreta va directo a la función de contacto.
- El sitio de Web Analytics.
- El estado vive en un bucket privado de Cloudflare R2; la decisión está documentada en un ADR.
- Ningún secreto está en el repositorio: vienen de los secretos de GitHub Actions y de Cloudflare.