Vitrine premium · Espelho Virtual (try-on) · WhatsApp
AURÉA Joalheria
Problema
Joalherias autorais vendem por foto no Instagram, sem uma vitrine elegante e sem o cliente conseguir “experimentar” a peça.
Solução
Vitrine editorial white-label com Espelho Virtual que prova brincos e colares pela câmera em tempo real (MediaPipe, 100% no navegador) e leva ao WhatsApp já com a referência da peça.
Como foi construído
A ÁUREA nasce com uma restrição de produto explícita: não é e-commerce. Não há carrinho, checkout nem gateway de pagamento, e toda intenção de compra converge para o WhatsApp do atelier. Essa regra está documentada no AGENTS.md do projeto ("Modelo de produto: VITRINE → WhatsApp... Não adicione carrinho/checkout sem pedido explícito") e é reforçada em código: um único módulo, src/lib/whatsapp.ts, monta toda mensagem, e o AGENTS.md proíbe montar links wa.me na mão em qualquer componente. A função productMessage() serializa a peça em três linhas fixas (Nome, Referência e Valor via formatCents()) para o vendedor identificar o item na hora, sem precisar abrir o site.
A peça de maior risco técnico é o Espelho Virtual em /experimentar: try-on de brincos e colares pela câmera, 100% no navegador, sem enviar vídeo a nenhum servidor. O VirtualMirror.tsx carrega o @mediapipe/tasks-vision (FaceLandmarker, delegate GPU) sob demanda via CDN e roda a detecção num loop de requestAnimationFrame, lendo landmarks fixos da malha facial (orelhas nos índices 234/454, queixo em 152, olhos em 33/263) para calcular largura do rosto e ângulo de inclinação da cabeça a cada frame. Um detalhe que só aparece em produção: os logs do MediaPipe e do TFLite ("XNNPACK delegate...") saem por console.error, e o overlay de dev do Next trata isso como erro. O código intercepta e filtra especificamente essas mensagens benignas por regex, sem silenciar erros reais.
As joias não são fotos recortadas sobre o rosto. São desenhadas vetorialmente em canvas a cada frame, em src/lib/mirror/draw.ts, com gradientes radiais para simular metal e pérola e um ponto especular fixo para dar brilho. A posição bruta dos landmarks é ruidosa, então uma suavização exponencial (EMA, fator 0.35) amortece o jitter frame a frame antes de desenhar. Cada tipo de peça tem constantes de encaixe calibradas manualmente como frações da distância entre orelhas (EARRING_DROP, NECK_SIDE_INSET, NECK_CENTER_DROP...). É ajuste fino de olho, não geometria derivada automaticamente, e fica documentado como "calibre aqui" no próprio arquivo.
O restante do site é pensado para white-label: cor, marca, contato e textos vivem só em theme.config.ts e copy.ts (Tailwind v4 sem tailwind.config, variáveis --store-* espelhadas nos dois lugares), e nenhuma peça de catálogo depende de banco de dados. Cada card de produto usa um componente Showcase, que é um efeito de vitrine de museu em CSS 3D puro (transform-style: preserve-3d, seis camadas em profundidades distintas de translateZ, tilt que segue o cursor via Framer Motion useSpring). Ele simula peça sob vidro e holofote sem WebGL nenhum, e é desativado automaticamente sob prefers-reduced-motion.
Try-on 100% client-side
FaceLandmarker do MediaPipe roda inteiramente no navegador. Nenhum frame de vídeo sai do dispositivo do cliente.
Um único ponto de verdade pro WhatsApp
Todo link wa.me passa por waUrl() ou productWaUrl(). Montar a URL na mão em componentes é proibido.
Joia desenhada, não recortada
Brincos e colares são vetores em canvas com gradiente e EMA de suavização, não fotos coladas sobre o rosto.
White-label sem tocar componente
Marca, cores, contato e catálogo trocam de loja para loja mexendo em dois arquivos de config.
Mais telas
Stack
- Next.js
- React 19
- TypeScript
- Tailwind v4
- MediaPipe
- Framer Motion


