Version Banner — Auto-aviso de nueva versión tras deploy
Descripción general
El Version Banner es un componente React sticky que detecta en tiempo real cuando se ha desplegado una nueva versión del workspace CreaRack Pro y avisa al usuario con un banner no intrusivo en la parte superior del viewport.
Implementado en la sesión s69 (18-05-2026) como «Opción B» del plan de notificación de versiones: polling cliente → sin WebSockets, sin dependencias extra, compatible con Cloudflare Pages.
Motivación
Los usuarios podían tener el workspace abierto durante horas (o días). Tras un deploy, trabajaban sobre código viejo sin saberlo, lo que podía producir inconsistencias con APIs o comportamientos inesperados. La solución fuerza una decisión informada del usuario sin interrumpir datos no guardados.
Arquitectura
Flujo completo
[CF Pages build]
└─ node scripts/generate-version.mjs
└─ escribe public/version.json { commit_sha, commit_sha_full, build_at }
[Browser, cada 60s]
└─ fetch('/version.json', { cache: 'no-store' })
└─ compara commit_sha con el valor inicial
├─ igual → nada
└─ diferente → muestra <VersionBanner />
Archivos implicados
| Archivo | Rol |
|---|---|
scripts/generate-version.mjs | Script Node.js que genera public/version.json en cada build |
public/version.json | Artefacto de build (gitignoreado); contiene commit_sha + build_at |
src/components/VersionBanner.tsx | Componente React con polling + UI del banner |
src/layouts/SecondaryLayout.astro | Monta <VersionBanner client:load /> en todas las páginas |
Componente VersionBanner.tsx
Props: ninguna (self-contained).
Estado interno:
initial: VersionInfo | null— versión capturada al cargar la página.latest: VersionInfo | null— última versión obtenida por polling.dismissed: boolean— el usuario ha pulsado «Más tarde».
Comportamiento:
- Se desactiva automáticamente en
localhost(evita falsos positivos en dev). - Intervalo de polling: 60 segundos (
POLL_MS = 60_000). - Usa
{ cache: 'no-store' }para evitar que la CDN de Cloudflare sirva el JSON cacheado. - El banner no fuerza recarga — el usuario elige «Recargar ahora» o «Más tarde».
- «Más tarde» hace
dismissed = true; si tras otro poll hay otra versión nueva distinta, el banner reaparece. - Accesibilidad:
role="status"+aria-live="polite".
Script generate-version.mjs
Escrito en ESM puro (Node.js ≥18). Se ejecuta como paso previo a astro dev y astro build.
Resolución del SHA:
- Si existe la env var
CF_PAGES_COMMIT_SHA(inyectada por Cloudflare Pages en build), la usa directamente. - Fallback:
git rev-parse HEADmedianteexecSync. - Si falla ambos:
'unknown'.
Salida (public/version.json):
{
"commit_sha": "3e6a472",
"commit_sha_full": "3e6a47239ed9a364e01643d29b5b978f0f44571d",
"build_at": "2026-05-18T13:03:01.000Z"
}
El archivo está en .gitignore (se regenera en cada build; committearlo causaría ruido en el historial).
Integración en el layout
SecondaryLayout.astro monta el componente con la directiva client:load, que garantiza hidratación inmediata al cargar la página:
<AppLayout title={title} description={description}>
<VersionBanner client:load />
<div class="app">
...
</div>
</AppLayout>
Como SecondaryLayout es el layout base de todas las páginas del workspace que extienden AppLayout, el banner queda disponible globalmente.
UX y diseño
- Posición:
position: fixed; top: 0; z-index: 9999— encima de cualquier otro elemento. - Color: mezcla
color-mix(in srgb, var(--accent) 92%, black)para heredar el tema activo. - Iconografía: SVG inline (estilo Lucide) con el icono de «refresh» circular.
- Botones: clases CSS centralizadas
.btn.primary.sm(Recargar) y.btn.ghost.sm(Más tarde). - Información mostrada:
commit_shainicial →commit_shanuevo (ej.27aa041 → 3e6a472).
Decisiones de diseño (Opción B vs. alternativas)
| Alternativa | Descartada porque |
|---|---|
| Opción A — SSE / WebSocket push | Requiere worker CF durable o server-sent events; complejidad desproporcionada para workspace interno |
| Opción B (esta) — Polling cliente 60s | Simple, sin estado servidor, compatible con CF Pages estático. Latencia máxima = 60s |
| Opción C — Service Worker + cache busting | Mayor complejidad de setup; requiere gestionar versiones del SW |
Limitaciones conocidas
- Latencia máxima de 60 s entre deploy y aviso visible. Aceptable para workspace interno.
- Si el usuario tiene varias pestañas abiertas, cada una hace su propio polling (no coordinación entre tabs).
- En
localhostel banner nunca aparece (by design). - Si
version.jsonno está presente (primera build sin el script),fetchdevuelve 404 →initialquedanull→ banner nunca se muestra (fallo silencioso seguro).
Historial
| Sesión | Commit | Descripción |
|---|---|---|
| s69 | 3e6a472 | Implementación inicial completa |
Véase también
- [[workspace—que-es-workspace]]