Saltar al contenido

Colofón

Cómo está construido este sitio — stack, arquitectura, caché y seguridad.

Stack técnico

Frontend

Framework de React (App Router, SSR, SSG)
Biblioteca de UI — Server & Client Components
Tipado estático de extremo a extremo
CSS utility-first, configuración CSS-first (`@theme`) — modo oscuro vía class
Selector claro/oscuro con persistencia

i18n

Internacionalización EN/FR/ES (App Router, middleware)

Blog

Renderizado MDX integrado en Next.js
Parsing de frontmatter YAML
rehype / remark
Transformación de AST HTML + Markdown
Resaltado de sintaxis en el servidor

Backend

Caché stale-while-revalidate + rate-limiting en los endpoints de escritura y sensibles (contacto, testimonios, invalidación de caché, admin, informes CSP, health) + historial de disponibilidad de 30 días
Entrega por email de los mensajes del formulario de contacto — alojado en la UE, sin persistencia en el servidor

Despliegue y Observabilidad

Alojamiento — CDN global, HTTPS automático, despliegues de preview

CI/CD y Calidad

GitHub Actions
Pipeline de CI: build, lint, typecheck, pruebas unitarias, auditoría de seguridad npm, E2E Playwright, Lighthouse CI
Presupuestos de rendimiento y accesibilidad en cada PR, bloqueantes en caso de regresión
Auditoría WCAG 2.2 AA automatizada en 9 rutas — tolerancia cero para violaciones críticas
Dependabot
Actualizaciones npm semanales (5 grupos), Actions mensuales — versiones mayores de next-intl/framer-motion bajo revisión manual
Puntuación semanal de seguridad de la cadena de suministro — branch protection, SAST, dependency pinning, signed commits
Content Publish Safety
Verificación diaria de public.projects: ningún proyecto se publica sin sus tres idiomas

Decisiones de arquitectura

  • →One-page landing con secciones diferenciadas para habilidades, experiencia, servicios, proyectos y contacto — navegación por anclas.
  • →Selector de track en el cliente (cookie `track`): un único componente hero, con habilidades y servicios adaptados al perfil Salesforce o IT Ops.
  • →Páginas dedicadas para About, Certificaciones y Blog — accesibles desde la navbar, sin duplicarse en la landing.
  • →Server Components por defecto: solo los componentes interactivos (hero, selector de tema, formulario) están marcados como `use client`.
  • →Ninguna lectura de base de datos desde el cliente: el historial de disponibilidad y el panel de incidencias se leen en Redis desde el servidor. Las fichas de proyecto están versionadas en `content/` y se sirven de forma estática.
  • →Blog en MDX: artículos escritos en `.mdx` dentro de `content/blog/posts/{locale}/` — renderizado estático en el build, sin necesidad de base de datos.

Estrategia de caché

  • →Upstash Redis guarda el historial de disponibilidad (un registro al día, 30 días) , el panel de incidencias de la administración, y almacena en caché las vistas de `/status` con un TTL de 1 a 5 minutos.
  • →stale-while-revalidate: si el dato está en caché, se devuelve de inmediato mientras se dispara una revalidación asíncrona en segundo plano.
  • →Invalidación manual: el endpoint `POST /api/cache/invalidate` (protegido por secreto) permite purgar la caché tras una actualización de datos.
  • →RSS feed: `Cache-Control: public, max-age=3600, stale-while-revalidate=86400` — 1h en caché CDN, revalidado cada 24h.
  • →ISR (páginas HTML): no activado en el CDN de Vercel por decisión de seguridad — el nonce CSP generado por solicitud (eliminación de `'unsafe-inline'`) es incompatible con un HTML cacheado.

Seguridad

  • →CSP basada en nonce: `'unsafe-inline'` eliminado de `script-src`. Se genera un nonce criptográfico único por solicitud en el proxy (`proxy.ts`) y se aplica a los scripts de hidratación de Next.js; los scripts que estos cargan heredan la confianza mediante `'strict-dynamic'`. Cualquier script inline sin nonce es bloqueado por el navegador. No se autoriza ningún script, estilo ni marco de terceros: el sitio no carga ninguna herramienta de medición de audiencia ni widget externo.
  • →Cabeceras HTTP en `next.config.mjs`: HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy extendida, Cross-Origin-Opener-Policy (`same-origin`), Cross-Origin-Resource-Policy (`same-origin`), Report-To, Reporting-Endpoints. Fingerprinting del framework desactivado (`poweredByHeader: false`).
  • →Contenido de proyectos versionado: las fichas de proyecto y sus recursos se versionan en el repositorio y se sirven de forma estática — no se expone ninguna base de datos para esta parte.
  • →Rate-limiting vía Upstash Redis (ventana deslizante) en los endpoints sensibles: contacto (5 req/10 min), testimonios (3 req/24h), invalidación de caché (10 req/min), health check (30 req/min), informes CSP (20 req/min), panel admin (5 req/15 min — protección anti fuerza bruta). Si Redis no está configurado en producción, el limitador pasa a modo *fail-closed* (todas las solicitudes bloqueadas). Ante una caída transitoria de Redis, pasa a *fail-open* para no penalizar a los usuarios legítimos — excepto en `/admin`, donde el comportamiento sigue siendo *fail-closed*.
  • →Honeypot: campos ocultos en los formularios de contacto y testimonios — los bots que rellenan estos campos reciben un 200 silencioso.
  • →Validación de origen: las solicitudes API procedentes de orígenes desconocidos se rechazan en producción.
  • →CORS restringido: `/api/health` limitado únicamente al origen del sitio — las herramientas de monitorización operan servidor a servidor.
  • →security.txt disponible en `/.well-known/security.txt` (RFC 9116) — contacto de divulgación responsable.
  • →Ningún secreto en las variables `NEXT_PUBLIC_*` — todas las claves sensibles (token de Redis, credenciales de admin, secretos HMAC) permanecen estrictamente en el servidor.
  • →Validación externa (terceros neutrales): securityheaders.com · Mozilla Observatory — postura HTTP verificada de forma independiente al sitio.

Código fuente

El repositorio de este sitio es público — arquitectura, CI/CD, pruebas y seguridad consultables directamente en GitHub.