⚙️ Render determinista
HyperFrames renderiza el HTML en frames de forma determinista: con el mismo HTML y la misma timeline, el video sale idéntico. Para eso, no hay acceso a la red durante el renderizado.
Determinístico significa que el render no depende de nada que pueda variar: no hace fetch, no carga imágenes remotas ni consulta APIs durante el proceso. Cada frame es una función pura del HTML + tiempo.
Es exactamente lo que garantiza que el video se pueda reproducir y que la animación coincida con el audio frame a frame.
Si un frame dependiera de una solicitud, el resultado cambiaría según la latencia, el estado del servidor o los datos del momento. El render perdería previsibilidad y se rompería la sincronía con la narración.
🚫 Nunca el sitio en vivo
Como consecuencia directa del renderizado determinista, la app nunca se carga en vivo dentro del video. Nada de un iframe que apunte a la URL real durante el renderizado.
- ✓ Capturas de pantalla reales guardadas en
assets/shots/ - ✓ Imágenes locales referenciadas en el HTML del video
- ✓ Todo integrado antes de que comience el render
- ✓ Animación sobre la imagen estática
- ✗
<iframe src="https://app…">en el video - ✗ Cargar imágenes mediante una URL remota durante el renderizado
- ✗ Esperar a que la app responda durante el renderizado
- ✗ Depender de fuentes mediante CDN (usa las locales)
El screenshot estático se coloca dentro de un marco de navegador (barra + URL) y se le superponen un cursor y zoom. Para quien lo ve, parece una grabación de pantalla en vivo, pero es una imagen más animación.
📸 Se capturan screenshots reales ANTES
La etapa que marca toda la diferencia ocurre antes del render: se navega por la app real con agent-browser y se toma una captura de pantalla por cada estado del recorrido.
agent-browser set viewport 1280 800 y abrir la URL. El viewport se define una vez y se mantiene.
Completar un campo, hacer clic en un botón, esperar un resultado: la acción que demuestra ese paso.
Cada estado se convierte en un assets/shots/NN-id.png — la base visual de ese paso.
Junto con el shot, se mide el cuadro real del elemento al que apuntará el cursor. Todo eso se convierte en steps.json.
Automatizado (capture.mjs + actions.json) para apps predecibles, o control manual del agent-browser paso a paso cuando hay inicio de sesión o estados dinámicos. Los detalles están en la Ruta 2: Captura.
🖼️ El viewport fijo se convierte en el espacio de coordenadas
Este es el concepto más importante del módulo: el viewport usado en la captura define el sistema de coordenadas en el que se posiciona todo después. Por eso es sagrado.
Si la captura se hizo en un viewport de 1280×800, entonces la captura de pantalla mide 1280×800 y cualquier coordenada (x, y) se refiere a ese espacio. El cursor, el zoom y el marco trabajan todos en ese mismo sistema.
Si la captura de pantalla sale de un viewport y la bounding box de otro, las coordenadas no coinciden: el cursor cae en el lugar equivocado. Por eso el viewport debe ser idéntico en toda la captura.
📦 Bounding boxes relativas al viewport
La posición de cada elemento objetivo no se estima «a ojo»: viene de getBoundingClientRect, que devuelve coordenadas reales relativas al viewport.
- ✓ El cursor llega al centro exacto del control
- ✓ Funciona incluso si el diseño es responsivo
- ✓ El resaltado/zoom encuadra el elemento correcto
- ✓ Es lo que le da un aspecto profesional al video
- ✗ Las coordenadas estimadas no aciertan en el control
- ✗ Se rompen con cualquier cambio de diseño
- ✗ No siguen el desplazamiento ni el tamaño del elemento
- ✗ Dan ese aspecto amateur de "casi listo"
🖱️ El cursor apunta a las cajas — consistencia entre shot↔coordenada
Con los screenshots y las cajas listos, el cursor se anima en la timeline principal apuntando al centro de cada bounding box. El secreto para acertar es la consistencia: mismo viewport, mismo scroll.
El cursor es global (se anima en la timeline principal, no por escena), con el hotspot en la punta. La punta se desliza hasta el centro del cuadro del objetivo y, al hacer clic, activa pulse + ripple. Como el cuadro y el shot provienen del mismo viewport y scroll, la punta cae exactamente sobre lo que aparece en pantalla.
Siempre que la captura de pantalla de ese paso y el bounding box del objetivo provengan del mismo viewport y del mismo desplazamiento, el cursor estará alineado. Romper esa consistencia es la causa n.º 1 de que el cursor quede «fuera de lugar».
📋 Resumen del Módulo 1.2
- ✓ El render de HyperFrames es determinista: no hay red
- ✓ Por eso nunca se carga el sitio en vivo en el video
- ✓ Se capturan screenshots reales ANTES, 1 por estado
- ✓ El viewport fijo se convierte en el espacio de coordenadas
- ✓ Los bounding boxes vienen de getBoundingClientRect (relativos al viewport)
- ✓ El cursor apunta a los cuadros; la consistencia entre shot y coordenadas es la regla