AGRICULTUREREIMAGINED.

- CLIENT
- KAVITA AGRO
- TYPE
- INTERACTIVE COMMERCE
- YEAR
- 2026
- STATUS
- LIVE
02 / THE IDEA
The reseller needed to turn a catalog into a conversation.
An agricultural-drone landing page doesn't sell on its own — it has to deliver a ready quote to the right branch's WhatsApp, without inventing a single spec. No framework, no build step: hand-written HTML, CSS and JavaScript.
01 / CATALOG
26 pieces of equipment across 5 categories, each with per-field confirmation status. Category and drone-compatibility filters (T25P, T70P, T100) combined with AND logic.

02 / DRONES
Three DJI Agras models compared side by side: spraying, spreading, warranty. Animated counters are born from the HTML itself — with no JS, the final number is already right.

03 / BUDGET
A mini-cart with no store behind it: drones, equipment and services go into a budget that persists in localStorage across visits, with a live counter.

04 / ROUTING
On submit, the message goes out structured in blocks to the chosen unit's WhatsApp — 4 branches across MG, ES and RJ, with a default fallback.

CATALOG
DRONES
BUDGET
ROUTING
04 / UNDER THE HOOD
- USER→
- CATALOG→
- BUDGET→
- BRANCH ROUTING→
ZERO FRAMEWORKSemantic HTML5, plain CSS and vanilla JS, no build step. Cloudflare Workers serving static assets.+
Zero framework, on purpose: semantic HTML5, plain CSS and vanilla JavaScript, with no build step. You just open index.html in the browser. It's about 7,200 lines split across 3 files (script.js at 1,735 lines, styles.css at 4,239), a decision the README itself documents as a "self-contained landing", kept separate from Kavita's core system. Hosting today is Cloudflare Workers via wrangler.jsonc serving the files as static assets, with a leftover vercel.json that only permanently redirects www.kavita.com.br to kavita.com.br. It's the trace of a provider migration done without breaking the old domain.
DATA MODELCatalog as governed data: every item carries a confirmed/pending status. Nothing is invented.+
The equipment catalog (26 items across 5 categories: batteries, chargers and power, tank mixers, sprayer pumps and other accessories) lives in an ACCESSORIES array in script.js, but it's treated as governed data, not loose content. Every item carries a status field, which can be confirmado, pendente-imagem, pendente-especificacao or pendente-compatibilidade, and the project's rule, documented in its docs, is explicit: "nothing is invented". Specs without a confirmed source (an official DJI manual or an Agrobox technical page) stay flagged as pending instead of getting filled in with a guess. Category and drone-compatibility filters (T25P/T70P/T100) combine with AND logic, so an item only shows up when it matches both criteria at once.
BUDGET + ROUTINGlocalStorage budget with a silent fallback; REPRESENTATIVES maps 4 branches to 4 numbers.+
The quote builder works like a mini-cart with no store behind it. Visitors add drones, equipment and services to a budget that persists in localStorage across sessions (with a silent fallback if the browser blocks storage) and see a live item counter. On lead-form submit, the site assembles a structured message, split into "Drones", "Equipment and accessories" and "Services" blocks, then redirects via wa.me. The destination number changes per unit: a REPRESENTATIVES object maps 4 branches (Mateus/HQ, Itaperuna-RJ, Manhuaçu-MG, Cachoeiro de Itapemirim-ES) to 4 different WhatsApp numbers, falling back to a default if the visitor picks none.
PERFORMANCEpreload + fetchpriority on the hero, video pauses off-screen, rAF counters with hand-written easing, theme via matchMedia.+
Several performance and accessibility details that usually come from a framework were hand-built. The hero uses preload with fetchpriority="high" for the critical image and preconnect for Google Fonts. The hero background video pauses via IntersectionObserver when it leaves the viewport, saving CPU and battery, and won't even play if prefers-reduced-motion is on. The animated counters (DJI stat numbers) use requestAnimationFrame with a hand-written easeOutCubic easing, computed straight from the HTML's own text, so they work as pure progressive enhancement: with no JS, the final number is already correct. And the light/dark theme respects the system preference (matchMedia) on first visit, then persists the user's choice in localStorage.
BUILT WITH — HTML · CSS · JavaScript · VercelCODE ↗
05 / DETAILS
26
EQUIPMENT ITEMS
04
REGIONAL ROUTES
0
FRAMEWORKS
~7.200
HAND-WRITTEN LINES
06 / RESULT



FROM BEANTO CUP.
