📋 As 11 regras do Render Contract
O Render Contract do CLAUDE.md lista 11 regras não-negociáveis para composições Hyperframes. Quebrar qualquer uma faz o render falhar ou sair com bug visual. É o equivalente a "tem que ter Doctype" no HTML.
📜 As 11 regras
- Root div precisa de id, data-composition-id, data-start="0", data-width, data-height
- Elementos visíveis temporizados precisam de class="clip" — exceto <video> e <audio>
- Todo elemento temporizado precisa de data-start, data-duration, data-track-index
- data-start pode referenciar outro clip: "intro + 2", "intro - 0.5"
- <video> deve ser muted; áudio vai em <audio> irmão
- Toda composição registra uma timeline GSAP pausada em window.__timelines
- Duração = tl.duration(). Se timeline < vídeo, o vídeo trunca
- Nunca .play(), .pause() ou set .currentTime manualmente em mídia
- Nunca animar width/height/top/left diretamente em <video> — wrap em <div>
- Sub-composições usam <template> com data-composition-src
- Determinismo: sem Date.now(), sem Math.random() unseeded, sem fetch de rede
⏱️ window.__timelines e GSAP
Cada composição registra uma GSAP timeline pausada em window.__timelines["composition-id"]. A chave deve bater exatamente com o data-composition-id.
📝 Pattern mínimo
<div id="my-scene" data-composition-id="my-scene" data-start="0" data-width="1920" data-height="1080">
<h1 class="clip" data-start="0" data-duration="3" data-track-index="0">Olá</h1>
</div>
<script>
(function() {
const tl = gsap.timeline({paused: true});
tl.from("#my-scene h1", {opacity: 0, y: 40, duration: 0.6, ease: "expo.out"});
tl.set({}, {}, 3); // estende duração para 3s
window.__timelines = window.__timelines || {};
window.__timelines["my-scene"] = tl;
})();
</script>
🎬 data-start, data-duration, data-track-index
Três atributos que definem quando um clip aparece, quanto dura e em qual track. Suportam timing relativo para composições ganharem legibilidade.
data-start
Quando o clip aparece. Pode ser número (2.5) ou referência a outro id ("intro + 2").
data-duration
Quanto tempo o clip fica visível. Em segundos (pode ter decimais).
data-track-index
Camada vertical. Clips no mesmo track não podem se sobrepor em tempo.
⚠️ Armadilha
Dois clips com data-track-index="0" sobrepostos em tempo = erro de lint. Use tracks diferentes (0, 1, 2...) ou ajuste timing.
📦 Sub-composições com template
Sub-composições são carregadas via <template> com data-composition-src. As timelines se linkam automaticamente ao parent.
📝 Como carregar sub-composição
<template data-composition-src="compositions/intro.html"
data-start="0"
data-duration="5"
data-track-index="0"></template>
⚠️ Nunca
Não chame masterTL.add(childTL). O framework já faz isso automaticamente baseado no data-composition-src.
🎞️ Por que video não leva clip
Tags <video> e <audio> são a única exceção à regra de class="clip". Adicionar class="clip" em <video> quebra o elemento. Animar width/height diretamente congela frames.
✓ FAZER
- ✓<video muted> sem class="clip"
- ✓Áudio em <audio> irmão
- ✓data-start e data-duration normalmente
- ✓Wrap em <div> e animar o wrapper
✗ NÃO FAZER
- ✗class="clip" no <video>
- ✗Animar width/height no <video> direto
- ✗Chamar .play()/.pause() manualmente
- ✗Setar .currentTime no seu código
💡 data-has-audio
Se quiser que o áudio nativo do <video> entre no mixer, adicione data-has-audio="true". Por padrão o mixer ignora áudio de videos e usa apenas <audio> irmãos.
✅ Verificação visual de frames
Lint passar ≠ design funcionar. Um render "bem-sucedido" com rosto cortado, texto desalinhado ou cena na palavra errada é render quebrado — e lint não pega nada disso.
🔍 Protocolo de verificação
# 1. Render draft
npx hyperframes render --quality draft --output renders/draft.mp4
# 2. Puxar frame por cena (ajuste timestamps para suas cenas)
mkdir -p renders/frames
for t in 1 3 5 7 9 11; do
ffmpeg -y -ss $t -i renders/draft.mp4 -frames:v 1 -q:v 2 "renders/frames/t${t}.png"
done
# 3. Abrir cada PNG e verificar:
# - Rostos não cortados
# - Texto alinhado e sem overlap
# - Cenas na palavra correta
# - Nenhum frame em branco
⚠️ Regra de ouro
Nunca entregue sem ter OLHADO cada frame-chave. Se encontrou bug, corrige, re-renderiza, re-verifica. Só então roda o --quality standard e entrega.
📋 Resumo do Módulo
Próximo Módulo:
2.2 - Pitch Deck + Vídeo Sizzle