MilWebWhatsApp
Back to projects

Artisanal dairy showcase · WhatsApp ordering

RJS Laticínios

Catalog · WhatsApp orderingPersonal project · demo

Problem

Artisanal dairy producers sell by word of mouth and WhatsApp, without a proper storefront that showcases products professionally.

Solution

A storefront with a product catalog and orders closed straight on WhatsApp. It's a simple, fast base for the producer to sell online without relying only on social media.

How it was built

The stack deliberately skips the standard Next + Tailwind combo: SCSS Modules with one central _tokens.scss (palette, type scale, easings, breakpoints as Sass variables) plus shared mixins. For a brand with such a strong visual identity, with blue as the anchor color on a 60-30-10 ratio and yellow, green and orange only as sparing accents, never flat backgrounds, Tailwind utility classes tend to scatter design decisions across className all over the JSX. With SCSS Modules, every section ships its own scoped .module.scss, and the palette lives in one place: retuning the brand blue is a one-line edit in _tokens.scss, not a grep for bg-blue-500 across dozens of files.

The Pandito mascot isn't an image. It's an SVG component (Panda.tsx) authored in code, using radial gradients for fur volume on the white and black coat, cheek blush, and a small prop system (look, item, sleepy) that redraws the eyes and head in real time. InteractivePanda listens to mousemove across the whole page but throttles reads with requestAnimationFrame and only calls setState once the position delta clears a threshold. That avoids a re-render on every pixel of mouse movement, which matters for INP. After 8s of no movement the panda dozes off (eyes close, breathing slows, an animated Zzz appears), and an IntersectionObserver pauses that whole processing loop once the section leaves the viewport, so no CPU gets burned animating a mascot nobody's looking at.

Smooth scroll is Lenis synced with GSAP's ScrollTrigger: Lenis's raf feeds GSAP's ticker (gsap.ticker.add) instead of running two animation loops side by side, avoiding jank when parallax and smooth-scroll compete for the same frame. The Hero background is an entire farm scene in pure SVG (gradient sky, sun, clouds, layered hills, barn and silo) with zero raster images, and it moves via scrollTrigger.scrub with a subtle yPercent and scale, adding depth without a loading cost. Notably, the panda's own parallax uses Framer Motion's MotionValue instead of GSAP, and the code explicitly documents why: animating y via animate and via a style MotionValue on the same div conflicts and locks the element at opacity:0. That's why the entrance animation (fade and scale) and the mouse parallax live in separate motion.div wrappers.

One detail easy to miss: the navbar has a "Flavor" picker that swaps the entire palette (7 options: milk, chocolate, strawberry, grape, banana, coconut and fruit salad) via a data-flavor attribute on <html>, with each variant overriding CSS custom properties in globals.scss. The choice persists to localStorage and is applied before hydration by an inline script in layout.tsx's <head>, which avoids a flash of the default palette before the saved color reapplies. Switching flavors triggers a color-wipe animation (FlavorPicker) that originates from the button itself and washes the screen in the new color before fading out. It's purely decorative, but it reinforces the brand's playful identity at no performance cost, since it's all CSS and SVG, with no images.

SCSS Modules, not Tailwind

Palette and type scale centralized in _tokens.scss. Retuning the brand color is a one-line edit, not a JSX grep.

Interactive, lightweight SVG mascot

Pure-SVG panda that tracks the cursor with requestAnimationFrame throttling and dozes off after 8s idle.

Lenis + GSAP ScrollTrigger, synced

A single animation loop (Lenis raf feeds the GSAP ticker) avoids jank between smooth-scroll and parallax.

7-palette theme picker

data-flavor on <html> swaps CSS custom properties, persists to localStorage, and avoids a pre-hydration flash.

More screens

Hero with an SVG farm scene and the Pandito mascotInteractive panda tracking the cursorDairy product catalog

Stack

  • Next.js
  • TypeScript
  • Tailwind
  • Vercel

Ready to turn your idea into a digital product?

Tell me what you need. I reply fast and send a free quote, no strings attached.

  • Service contract
  • Post-launch support
  • You own the code
  • Free quote