⚙️ Render determinístico
O HyperFrames renderiza o HTML em frames de forma determinística: dado o mesmo HTML e a mesma timeline, o vídeo sai idêntico. Para isso, não há acesso à rede durante a renderização.
Determinístico significa: o render não depende de nada que possa variar — não faz fetch, não carrega imagens remotas, não consulta APIs no meio do caminho. Cada frame é função pura do HTML + tempo.
É exatamente isso que garante que o vídeo seja reproduzível e que a animação bata com o áudio frame a frame.
Se um frame dependesse de uma requisição, o resultado mudaria conforme a latência, o estado do servidor ou os dados do momento. O render perderia a previsibilidade — e a sincronia com a narração quebraria.
🚫 Nunca o site ao vivo
Como consequência direta do render determinístico, o app jamais é carregado ao vivo dentro do vídeo. Nada de iframe apontando para a URL real durante a renderização.
- ✓ Screenshots reais salvos em
assets/shots/ - ✓ Imagens locais referenciadas no HTML do vídeo
- ✓ Tudo embutido antes do render começar
- ✓ Animação por cima da imagem estática
- ✗
<iframe src="https://app…">no vídeo - ✗ Carregar imagens via URL remota no render
- ✗ Esperar o app responder durante a renderização
- ✗ Depender de fontes via CDN (use as locais)
O screenshot estático entra dentro de uma moldura de navegador (barra + URL) e ganha cursor + zoom por cima. Para quem assiste, parece uma gravação de tela ao vivo — mas é imagem mais animação.
📸 Captura-se screenshots reais ANTES
A etapa que faz toda a diferença acontece antes do render: navega-se o app de verdade com o agent-browser e tira-se um screenshot por estado da jornada.
agent-browser set viewport 1280 800 e abrir a URL. O viewport é definido uma vez e mantido.
Preencher um campo, clicar num botão, esperar um resultado — a ação que aquele passo demonstra.
Cada estado vira um assets/shots/NN-id.png — a base visual daquele passo.
Junto do shot, mede-se a caixa real do elemento que o cursor vai mirar. Tudo isso vira steps.json.
Automatizado (capture.mjs + actions.json) para apps previsíveis, ou manual dirigindo o agent-browser passo a passo quando há login ou estados dinâmicos. Os detalhes ficam na Trilha 2: Captura.
🖼️ O viewport fixo vira o espaço de coordenadas
Este é o conceito mais importante do módulo: o viewport usado na captura define o sistema de coordenadas em que tudo é posicionado depois. Por isso ele é sagrado.
Se a captura foi feita num viewport de 1280×800, então o screenshot tem 1280×800 e qualquer coordenada (x, y) refere-se a esse espaço. O cursor, o zoom e a moldura trabalham todos nesse mesmo sistema.
Se o screenshot sai de um viewport e a bounding box de outro, as coordenadas não batem: o cursor cai no lugar errado. Por isso o viewport tem que ser idêntico em toda a captura.
📦 Bounding boxes viewport-relative
A posição de cada elemento-alvo não é estimada "no olho": vem de getBoundingClientRect, que devolve coordenadas reais relativas ao viewport.
- ✓ O cursor cai no centro exato do controle
- ✓ Funciona mesmo se o layout for responsivo
- ✓ O destaque/zoom enquadra o elemento certo
- ✓ É o que dá o ar profissional ao vídeo
- ✗ Coordenadas chutadas erram o controle
- ✗ Quebram a qualquer mudança de layout
- ✗ Não acompanham scroll ou tamanho do elemento
- ✗ Dão aquele aspecto amador de "quase lá"
🖱️ O cursor mira as boxes — consistência shot↔coordenada
Com os screenshots e as caixas em mãos, o cursor anima na timeline principal mirando o centro de cada bounding box. O segredo de acertar é a consistência: mesmo viewport, mesmo scroll.
O cursor é global (animado na timeline principal, não por cena), com o hotspot na ponta. A ponta desliza até o centro da box do alvo e, no clique, dispara pulse + ripple. Como a box e o shot vêm do mesmo viewport e scroll, a ponta cai exatamente sobre o que aparece na tela.
Sempre que o screenshot daquele passo e a bounding box do alvo saírem do mesmo viewport e do mesmo scroll, o cursor estará alinhado. Quebrar essa consistência é a causa nº1 de cursor "fora do lugar".
📋 Resumo do Módulo 1.2
- ✓ O render do HyperFrames é determinístico — sem rede
- ✓ Por isso nunca se carrega o site ao vivo no vídeo
- ✓ Captura-se screenshots reais ANTES, 1 por estado
- ✓ O viewport fixo vira o espaço de coordenadas
- ✓ Bounding boxes vêm de getBoundingClientRect (viewport-relative)
- ✓ O cursor mira as boxes; consistência shot↔coordenada é a regra