Vitrine de laticínios artesanais · pedido no WhatsApp
RJS Laticínios
Problema
Produtores de laticínios artesanais vendem no boca a boca e no WhatsApp, sem uma vitrine própria que mostre os produtos com profissionalismo.
Solução
Vitrine com catálogo de produtos e pedido fechado direto no WhatsApp. É uma base simples e rápida para o produtor vender online sem depender só das redes sociais.
Como foi construído
A stack foge do combo padrão Next + Tailwind de propósito: SCSS Modules com um arquivo _tokens.scss central (paleta, tipografia, easings, breakpoints como variáveis Sass) e mixins compartilhados. Numa marca com identidade visual tão forte, com azul como cor-mãe na proporção 60-30-10 e amarelo, verde e laranja só como acento pontual, nunca fundo chapado, as utility classes do Tailwind tendem a espalhar decisões de design em className por todo o JSX. Com SCSS Modules cada seção carrega seu próprio .module.scss com escopo local, e a paleta vive num único lugar: mudar o tom do azul da marca é uma linha em _tokens.scss, não um grep por bg-blue-500 em dezenas de arquivos.
O mascote Pandito não é uma imagem. É um componente SVG (Panda.tsx) desenhado em código, com gradientes radiais para dar volume ao pelo branco e preto, blush nas bochechas e um sistema de props (look, item, sleepy) que redesenha os olhos e a cabeça em tempo real. O componente InteractivePanda captura mousemove na página inteira, mas throttla a leitura com requestAnimationFrame e só dispara setState quando o delta de posição passa de um limiar. Isso evita re-render a cada pixel de movimento do mouse, o que importa muito pro INP. Depois de 8s sem movimento o panda cochila (fecha os olhos, respiração mais lenta, some no Zzz animado), e um IntersectionObserver pausa esse processamento inteiro quando a seção sai da viewport, para não gastar CPU com um mascote que ninguém está vendo.
Scroll suave é Lenis sincronizado com GSAP ScrollTrigger: o raf do Lenis alimenta o ticker do GSAP (gsap.ticker.add) em vez de rodar dois loops de animação em paralelo, o que evita jank quando parallax e smooth-scroll competem pelo mesmo frame. O fundo do Hero é uma cena de fazenda inteira em SVG puro (céu com gradiente, sol, nuvens, colinas em camadas, celeiro e silo), sem nenhuma imagem raster, e se move em scrollTrigger.scrub com leve yPercent e scale, dando profundidade sem pesar o carregamento. Interessante notar que o parallax do próprio panda usa MotionValue do Framer Motion em vez de GSAP, e o código documenta explicitamente por quê: animar y com animate e com um MotionValue de style na mesma div gera conflito e trava o elemento em opacity:0. Por isso a entrada (fade e scale) e o parallax de mouse ficam em wrappers motion.div separados.
Um detalhe que passa despercebido: o site tem um seletor de "Sabor" na navbar que troca a paleta inteira (7 opções: leite, flocos, morango, uva, banana, coco e salada de frutas) via data-flavor no <html>, com cada variante sobrescrevendo as CSS custom properties em globals.scss. A escolha persiste em localStorage e é aplicada antes da hidratação por um script inline no <head> do layout.tsx, o que evita o flash da paleta padrão antes de reaplicar a cor salva. Trocar de sabor dispara uma onda de tinta (FlavorPicker) que nasce do próprio botão e cobre a tela com a cor nova antes de sumir. É puramente decorativo, mas reforça a identidade lúdica da marca sem custar performance, já que é tudo CSS e SVG, sem imagens.
SCSS Modules, não Tailwind
Paleta e tipografia centralizadas em _tokens.scss. Mudar a cor da marca é uma linha, não um grep no JSX.
Mascote SVG interativo e leve
Panda em SVG puro que segue o cursor com requestAnimationFrame throttling e cochila após 8s parado.
Lenis + GSAP ScrollTrigger sincronizados
Um único loop de animação (raf do Lenis alimenta o ticker do GSAP) evita jank entre scroll suave e parallax.
Seletor de tema com 7 paletas
data-flavor no <html> troca CSS custom properties, persiste em localStorage e evita flash antes da hidratação.
Mais telas
Stack
- Next.js
- TypeScript
- Tailwind
- Vercel


