Página de Destino Cinematográfica com Scrub — O Template Dourado
Construa uma landing page premium e consciente da marca, onde o vídeo hero responde ao mouse e o resto da página guia o visitante através de um arco narrativo de 5 batidas. O usuário fornece um vídeo, opcionalmente um logotipo + foto do produto + contexto de marca — esta skill cuida da extração de paleta, seleção de tipografia, RTL/LTR, scaffolding, a re-codificação do vídeo com todos os keyframes, o efeito mouse-scrub, a biblioteca de seções e a verificação.
Por que esta skill existe
A implementação de referência está em https://github.com/hoodini/bamba — um site RTL israelense para o snack "במבה" onde um vídeo de bebê acompanha o cursor pela página inteira enquanto 4 seções distintas abaixo (receita amarela brilhante, álbum de nostalgia creme, preços escuros contemplativos, final vermelho de ação) guiam o visitante através de anseio → alegria → nostalgia → contemplação → ação.

Cada regra nesta skill foi extraída dessa construção. Os itens em a seção de regras rígidas são TODOS conquistados com muito esforço — eles substituem os padrões genéricos de "bom código".
Galeria de seções (o que você está construindo)
O hero fica no topo. Abaixo dele, escolha 4 seções da biblioteca, ordenadas para seguir o arco narrativo. Cada uma é totalmente opaca (sem vazamento do vídeo) e tem sua própria identidade de marca:
| Batida | Tipo | Referência |
|---|---|---|
| 1 — Anseio | Hero (vídeo mouse-scrub) | ![]() |
| 2 — Alegria | Sol — gradiente de acento primário brilhante, SVGs de motivo flutuante, tipografia fantasma gigante, cartões de estatísticas | ![]() |
| 3 — Nostalgia | Álbum — papel creme, micropadrão pontilhado, bento polaroid com foto real do produto | ![]() |
| 4 — Contemplação | Torrado — escuro com brilhos de acento radial, três cartões de preço cada um com TRATAMENTO visual DIFERENTE | ![]() |
| 5 — Ação | Sinal — acento forte de sangria total (vermelho/laranja/verde), manchete massiva + CTA, painel contido em vidro | ![]() |
Para marcas técnicas/SaaS, troque os tipos de seção conforme necessário (veja a biblioteca de seções abaixo) — mas sempre termine com uma seção Sinal.
Como usar esta skill
-
Coloque os ativos em um diretório de trabalho limpo:
- Vídeo hero (qualquer container —
.mp4,.mov,.webm) - Logotipo (SVG fortemente preferido; PNG com transparência aceitável)
- 1-3 imagens do produto/assunto (JPG/PNG, transparente ideal)
- Vídeo hero (qualquer container —
-
Confirme com o usuário (brevemente — proponha padrões, siga em frente):
- Nome do produto + meta-tagline
- Código do idioma (direciona RTL/LTR + escolha de fonte)
- Contexto da marca — era, público, núcleo emocional, sensação da paleta
- Opcional: hexes explícitos da paleta, batidas do arco narrativo
-
Execute o fluxo de trabalho abaixo em ordem. Todas as fases são obrigatórias. Não pule a re-codificação ffmpeg — essa é a mágica que faz o scrub parecer suave.
-
Verifique antes de relatar conclusão. A Fase 9 tem 12 verificações. Execute todas elas.
ENTRADAS — colete estas do usuário
PRODUCT_NAME: "<ex: Bamba / Hope the Cheetah / Acme CRM>"
TAGLINE: "<a meta-mensagem — ex: 'não é um lanche, são memórias para a vida'>"
LANGUAGE: "<he | en | ar | es | fr | ja | ...>"
IS_RTL: "<true | false>" # he/ar/fa = true; todo o resto = false
HERO_VIDEO_FILE: "<nome exato do arquivo no diretório atual — ex: baby2.mp4>"
LOGO_FILE: "<nome exato do arquivo — deixe em branco se não houver>"
PRODUCT_IMAGE_FILE: "<nome exato do arquivo — deixe em branco se não houver>"
BRAND_CONTEXT: |
<2-4 frases: era que evoca, quem é o público, o núcleo emocional,
a identidade visual (quente/fria/divertida/séria). Direciona paleta + motivos.>
PALETTE: "<opcional — hexes separados por vírgula se substituindo>"
NARRATIVE_ARC: "<opcional — 5 batidas emocionais; a IA propõe se em branco>"
O modelo de texto completo (com o mesmo bloco YAML e corpo do prompt) está em references/GOLDEN_PROMPT.md — cole-o no Claude com o YAML preenchido quando você não tiver acesso direto à skill em tempo de execução.
Fase 0 — Planeje o design (produza um briefing de ≤200 palavras antes de codificar)
Antes de escrever qualquer código, produza:
-
Paleta extraída de 5 cores:
background(tinta mais escura),cream(texto branco quente — NUNCA#FFFFFF),accent(cor primária da marca),accent2(cor secundária da marca),support(tom terciário). Extraia do logotipo + imagem do produto se nenhumPALETTEfoi fornecido. A paleta deve ser internamente coesa — toda quente OU toda fria, nunca misturada. Marcas quentes (comida, natureza, nostalgia, animais) → sem azuis, teals, mentas, cianos. Marcas frias (tecnologia, finanças, médico, sci-fi) → sem tons quentes, exceto um pequeno acento. -
Trindade tipográfica (exibição / corpo / acento manuscrito) para o idioma:
he: Rubik (exibição) + Assistant (corpo) + Suez One (acento)en: Anton (exibição) + Inter (corpo) + Caveat (acento)ar: Cairo (exibição) + Tajawal (corpo) + Reem Kufi (acento)es/fr/it/de: Anton ou Bebas Neue (exibição) + Inter (corpo) + Caveat (acento)ja: Noto Sans JP peso 900 (exibição) + Noto Sans JP (corpo) + Yusei Magic (acento)- Outro: escolha três Google Fonts correspondentes ao script, com os mesmos papéis
exibição-preto / corpo-limpo / manuscrito-script.
-
Arco narrativo — 5 batidas emocionais que mapeiam para
BRAND_CONTEXT. Combine cada uma com um tipo de seção da biblioteca de seções.
Em seguida, execute — não peça confirmação.
Fase 1 — Preparação dos ativos (a etapa mágica)
1a. Verifique ffmpeg
which ffmpeg # ou: Get-Command ffmpeg no PowerShell
Se ausente, pare e diga ao usuário para instalar (brew install ffmpeg / Windows: http://ffmpeg.org).
1b. Re-codifique o vídeo hero com cada quadro como um keyframe
Os navegadores só podem buscar instantaneamente para keyframes — o vídeo padrão tem ~1 keyframe a cada 250 quadros, o que faz o mouse-scrub gaguejar horrivelmente. Este único comando é a diferença entre premium e amador:
ffmpeg -y -i <HERO_VIDEO_FILE> -g 1 -keyint_min 1 -c:v libx264 -preset slow -crf 20 -pix_fmt yuv420p -an hero.mp4
Verifique a saída: hero.mp4 deve ter 5-50 MB. Se > 50 MB, re-execute com -crf 25; se > 80 MB com -crf 28. Remova o áudio (-an) — o hero é silencioso.
1c. Copie o logotipo + imagem do produto
cp <LOGO_FILE> public/logo.<ext>
cp <PRODUCT_IMAGE_FILE> public/product.<ext> # se fornecido
Fase 2 — Scaffolding
npm create vite@latest site -- --template react-ts
cd site
npm install
npm install lucide-react
npm install -D tailwindcss@3 postcss autoprefixer
npx tailwindcss init -p
mkdir -p public
mv ../hero.mp4 public/hero.mp4
# Mova também o logotipo + imagem do produto para public/
Fase 3 — Configuração do Tailwind
Substitua tailwind.config.js inteiramente. Use a paleta extraída e as fontes apropriadas para o idioma:
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
background: '<tinta/escuro>',
cream: '<branco quente — NUNCA #FFFFFF>',
accent: '<cor primária da marca>',
accent2: '<secundária>',
support: '<terciária>',
},
fontFamily: {
sans: ['<fonte do corpo>', 'system-ui', 'sans-serif'],
display: ['<fonte de exibição>', 'sans-serif'],
accent: ['"<fonte manuscrita>"', 'cursive'],
},
},
},
plugins: [],
}
Fase 4 — index.html
Substitua inteiramente. Respeite IS_RTL. Inclua sempre o link do favicon apontando para o logotipo:
<!DOCTYPE html>
<html lang="<LANGUAGE>" dir="<rtl|ltr>">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<link rel="apple-touch-icon" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="<URL do Google Fonts para as três fontes escolhidas>" rel="stylesheet">
<title><PRODUCT_NAME> — <TAGLINE></title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Fase 5 — index.css (o sistema de design)
Substitua inteiramente. Cada utilitário abaixo é estrutural. Os nomes assumem a paleta quente extraída anteriormente; para uma marca fria, troque as menções a "amarelo"/"vermelho" nas sombras pelos tons de acento reais.
Deve incluir:
html { scroll-behavior: smooth; }+section[id] { scroll-margin-top: 90px; }para que seções âncoradas não fiquem sob a navegação fixa.bodybackground = corbackground(fallback se o vídeo falhar). Cursor =crosshair. Fonte padrão = sans do corpo..liquid-glass/.liquid-glass-strong— backdrop-blur + saturar + borda clara interna + destaque de borda gradiente mascarada. A variante forte usa um brilho interno tingido comaccent..glass-pill— pílula arredondada compacta com o mesmo tratamento de vidro para itens de navegação e pequenos emblemas..cta-primary— CTA da marca:linear-gradient(135deg, accent-light, accent, accent-shade)+ sombra de brilho na cor de acento que intensifica no hover + elevaçãotranslateY(-1px)..brand-mark— quadrado/círculo pequeno para marcas de logotipo minúsculas se nenhum SVG for fornecido..grid-bg— grade sutil de 1px com máscara de desvanecimento radial, usada sob seções escuras..reveal/.revealed— revelação de scroll do IntersectionObserver:opacity 0 → 1+translateY 28 → 0ao longo de 0.9s comcubic-bezier(0.16, 1, 0.3, 1)..scrim-top/.scrim-bottom— sobreposições de gradiente para o hero apenas.- Fundos por seção, nomeados pela sensação, não pela cor:
.sun-section— gradiente de acento primário brilhante + textura pontilhada sutil (a batida "alegria / abrindo o saco")..album-section— papel branco quente, tons de acento radiais + micropadrão pontilhado, máscara de borda de desvanecimento..roast-section— escuro com brilhos de acento + accent2 radiais em cantos opostos + textura de grade mascarada..signal-section— acento forte de sangria total (frequentemente vermelho/laranja/verde) para o final de ação.
.polaroid— cartão branco, preenchimento14px 14px 44px 14px, sombra suave em camadas, hover eleva paratranslateY(-6px) rotate(0)..polaroid-tape= faixa de fita amarela/acento posicionada absolutamente no centro superior, rotacionada -4°, com dicas laterais tracejadas..stamp— pílula de borda tracejada na cor de acento, maiúscula, espaçamento entre letras0.18em..ribbon— emblema de preços/popular comclip-pathtriângulo inferior, sombra escura..highlight-circle— oval com sensação desenhada à mão desenhada via::after: borda de cor de acento rotacionada de 3px ao redor de um<span>inline. Use-a ao redor da palavra mais importante em títulos grandes (um por título no máximo).- Filtro de motivo decorativo:
.peanut-svg/.<motivo>-svgcomdrop-shadow. - Respeite
prefers-reduced-motion: reduce— desative a animação de revelação + scroll suave dentro da consulta de mídia.
Fase 6 — Arquitetura do App.tsx
A arquitetura é inegociável. Acerte na primeira vez:
6a. Importações
import { useEffect, useRef, useState } from 'react';
import {
Menu, X, ArrowLeft, ArrowRight, ArrowDown, ArrowUp, MousePointer2,
// …mais 4-8 ícones temáticos da marca (Heart, Sparkles, Cookie, PawPrint, Cpu, Leaf, …)
} from 'lucide-react';
6b. Componentes reutilizáveis definidos dentro do App.tsx
useReveal<T>()— hook do IntersectionObserver retornando uma ref; adiciona a classerevealedno primeiro intersect (threshold 0.15).GlassCard— wrapper com o hook de revelação, propstrongopcional, aceita className.Motif— um único componente SVG decorativo temático paraBRAND_CONTEXT(amendoim para comida, pata para animais, circuito para tecnologia, folha para natureza, gota para bebida, raio para energia). Flutua com baixa opacidade em 3-6 lugares por seção escura/brilhante.ScrollToTopButton— fixobottom-6 left-6em RTL /bottom-6 right-6em LTR. Aparece quandowindow.scrollY > window.innerHeight * 0.6. Rola suavemente para o topo. Rótulo curto apropriado ao idioma ("לראש" / "Topo" / "أعلى" / "Inicio").
6c. Efeito mouse-scrub (o coração)
const videoRef = useRef<HTMLVideoElement>(null);
const stateRef = useRef({ targetTime: 0, isSeeking: false });
useEffect(() => {
const video = videoRef.current;
if (!video) return;
const handleLoaded = () => {
const mid = video.duration / 2;
video.currentTime = mid;
stateRef.current.targetTime = mid;
};
const handleSeeked = () => {
const s = stateRef.current;
s.isSeeking = false;
if (Math.abs(s.targetTime - video.currentTime) > 0.01) {
s.isSeeking = true;
video.currentTime = s.targetTime;
}
};
const handleMouseMove = (e: MouseEvent) => {
const s = stateRef.current;
const d = video.duration;
if (!d || isNaN(d)) return;
const normalized = e.clientX / window.innerWidth;
// Se o assunto se mover "para trás" em relação ao cursor e parecer errado, opcionalmente
// use `1 - (e.clientX / window.innerWidth)` — PERGUNTE ao usuário primeiro.
s.targetTime = Math.max(0, Math.min(d, normalized * d));
if (!s.isSeeking) { s.isSeeking = true; video.currentTime = s.targetTime; }
};
video.addEventListener('loadedmetadata', handleLoaded);
video.addEventListener('seeked', handleSeeked);
window.addEventListener('mousemove', handleMouseMove);
return () => {
video.removeEventListener('loadedmetadata', handleLoaded);
video.removeEventListener('seeked', handleSeeked);
window.removeEventListener('mousemove', handleMouseMove);
};
}, []);
A proteção isSeeking é crítica — sem ela, o mousemove dispara mais rápido do que o navegador pode decodificar e você obtém um estouro da fila de busca e gagueira visível.
6d. Navegação clicável com scroll-spy
const navItems: { label: string; target: string }[] = [
{ label: '<demo>', target: 'top' },
{ label: '<recipe>', target: 'sun' },
{ label: '<nostalgia>',target: 'album' },
{ label: '<pricing>', target: 'roast' },
{ label: '<get it>', target: 'signal' },
];
// Scroll spy state
const [activeSection, setActiveSection] = useState('top');
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) setActiveSection(entry.target.id);
});
}, { threshold: 0.5 });
document.querySelectorAll('section[id]').forEach(s => observer.observe(s));
return () => observer.disconnect();
}, []);
Fase 7 — Biblioteca de seções (escolha 4-5 após o hero)
Cada seção usa useReveal + GlassCard + Motif internamente. O conteúdo é específico da marca, mas o layout vem de modelos:
Sol — receita / abertura do saco / funcionalidades principais
- fundo: gradiente diag de
accentparaaccent2, máscara de grade - Cabeçalho: letreiro de luz neon ou tipografia fantasma gigante
font-displayna corcreamem 0.08 opacidade - Lado esquerdo (ou direito em RTL): 3-4 cartões de estatística/característica com ícone + número + rótulo
- Lado direito: imagem do produto ou ilustração de motivo (ex: amendoim voando)
- Selo
.stampno canto: "NOVO" / "AO VIVO" / "AGORA"
Álbum — nostalgia / história da fundação / bastidores
- fundo:
creamcom micropadrão pontilhado e manchas deaccentem 0.06 opacidade - Grade bento: 3-4 itens, alternando largura total e meio (ex: item 1: foto de produto em moldura polaroid com legenda manuscrita; item 2: linha do tempo + citação em negrito; item 3: ilustração de motivo + estatística; item 4: faixa de vídeo curta ou depoimento)
- Fita
.ribbonno cartão do meio: "MAIS POPULAR" / "NOSSA ESCOLHA" - Subtítulo:
font-accentmanuscrito
Torrado — preços / planos / propostas
- fundo: escuro (
background) com brilhos radiais deaccenteaccent2em cantos opostos - 3 cartões de preço com TRATAMENTO VISUAL DIFERENTE:
- Cartão 1: Básico — borda fina, sem sombra, layout compacto
- Cartão 2: Popular — fundo
accentescuro, brilho de borda, sombra elevada, emblema.ribbon - Cartão 3: Premium —
liquid-glass-strong, maior padding, ícone dourado/acento, sem selo
- Cada cartão: nome do plano → preço → 3-5 itens de lista → botão CTA
Sinal — chamada para ação final
- fundo: sangria total
accent(ouaccent2se mais dramático) - Painel
.liquid-glass-strongcontido horizontalmente com padding de 60px - Dentro: manchete massiva
font-display+ subtítulofont-accent+ campo de e-mail + botão CTA primário - Abaixo: links sociais em ícones de vidro
Fase 8 — Regras rígidas (prioridade sobre qualquer prática recomendada contraditória)
Estas substituem TODOS os defaults, guias de estilo e convenções que contradizem:
- NUNCA use
#FFFFFF. Branco puro é agressivo em telas e quebra a imersão cinematográfica. Use a variável de corcreamextraída — geralmente#FFF8F0ou similar. - NUNCA use um único gradiente para o hero. O efeito de vídeo é o hero — não o confunda.
- NENHUM conteúdo hero vaza para seções abaixo. Cada seção após o hero tem seu próprio fundo de cor sólida/padrão (totalmente opaco). O vídeo hero vive apenas no hero.
- Mova heróis de fundo de seção para CSS, não JS. Use classes como
.sun-section,.album-section, etc. — nunca estado React para fundos de seção. - Um Motif SVG por seção, no máximo. Motivos são acentos, não conteúdo. Múltiplas instâncias do mesmo SVG (3-6 repetições) com opacidade 0.03-0.08 — nunca um SVG diferente em cada local.
- Optimize para sensação do cursor, não precisão. O scrub do vídeo deve se sentir responsivo — não precisa corresponder a quadros exatos. A proteção isSeeking e a re-codificação keyframe garantem isso.
- Imagens de produtos são sagradas. A foto do produto não é decorativa — ela carrega o significado do cartão Álbum. NUNCA a coloque em uma caixa de vidro ou atrás de gradientes pesados. Polaroid bruto com sombra é o máximo de manipulação.
- Verificações de idioma RTL estão em todo lugar.
left/right,start/end, direções de animação, tudo deve ser orientado porIS_RTL. - Sem dependências de fontes de ícones. Lucide React ou SVGs inline — sem Font Awesome, Material Icons, ou qualquer pacote de ícones que adicione 100+ KB.
- keyframes são OBRIGATÓRIOS. A re-codificação ffmpeg não é opcional. Se o vídeo for muito grande, aumente
-crf— mas NUNCA pule-g 1 -keyint_min 1. - A rolagem para o topo é obrigatória. O botão flutuante com rolagem suave deve estar em todas as páginas com mais de uma viewport de altura.
- A navegação fixa sempre tem fundo.
bg-background/80 backdrop-blur-md— nunca transparente, mesmo no hero.
Fase 9 — Verificação (12 verificações — execute TODAS)
# 1. O vídeo existe e é reproduzível
ls -lh public/hero.mp4
ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=noprint_wrappers=1 public/hero.mp4
# 2. ffmpeg re-codificou (verifique se há keyframes próximos)
ffprobe -v error -select_streams v:0 -show_frames -of csv=p=0 public/hero.mp4 | grep -c 'I'
# 3. Logotipo presente
ls -lh public/logo.*
# 4. Build limpo
npm run build 2>&1 | tail -5
# 5. Servidor de desenvolvimento inicializa
npm run dev -- --host &
sleep 3
curl -s http://localhost:5173 | head -20
Depois de executar, verifique manualmente:
- 6. O vídeo hero ocupa 100vw × 100vh
- 7. O scrub do mouse funciona — mova o cursor da esquerda para a direita, o vídeo avança/retrocede suavemente
- 8. Todas as 4-5 seções após o hero são totalmente opacas (sem vazamento do vídeo)
- 9. Cada seção tem sua própria sensação de cor/tipografia/layout
- 10. A navegação fixa destaca a seção ativa
- 11. O botão de rolagem para o topo aparece após rolar 60% da página
- 12.
dircorresponde ao documento — RTL inverte a direção do texto e da animação
Referências
references/GOLDEN_PROMPT.md— Modelo de prompt completo com o bloco YAML, para uso fora do runtime da skillassets/— Screenshots de cada tipo de seção para referência visualsite/— Projeto de saída (sobrescrito a cada execução)








