/* global React, ReactDOM */ const { useState, useEffect, useRef } = React; /* ---------------- Nav ---------------- */ function Nav() { const [scrolled, setScrolled] = useState(false); const [activeLink, setActiveLink] = useState(null); // no link active until user clicks one useEffect(() => { const on = () => setScrolled(window.scrollY > 40); window.addEventListener("scroll", on, { passive: true }); on(); return () => window.removeEventListener("scroll", on); }, []); const links = [ { href: "#work", label: "Work" }, { href: "#services", label: "Services" }, { href: "#process", label: "Process" }, { href: "#capabilities", label: "Capabilities" }, { href: "#contact", label: "Contact" }, ]; return ( ); } function ArrowSm() { return ( ); } function ArrowLg({color = "white"}) { return ( ); } /* ---------------- Hero Lamp ---------------- */ // Two tags — one for each theme — always in DOM. // CSS shows/hides them via [data-theme] selector. // No JS state, no re-renders, no animation glitches. function HeroLamp() { return ( ); } /* ---------------- Hero ---------------- */ function Hero() { return (
Digital agency · Est. 2020 · Dhaka, BD
Live Digital Services

We design brands
that actually
move markets.

A note from the studio

Grabsoft is a 40-strong team of researchers, strategists, designers and engineers building digital products, brands and growth engines for ambitious teams across 35+ countries.

Combined client valuation
M+
Products launched
+
); } function SwatchDot() { return ( ); } function AnimatedNum({ to, duration = 1400 }) { const ref = useRef(null); const [val, setVal] = useState(0); useEffect(() => { const el = ref.current; if (!el) return; let started = false; const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting && !started) { started = true; const start = performance.now(); const tick = (now) => { const t = Math.min(1, (now - start) / duration); const eased = 1 - Math.pow(1 - t, 3); setVal(Math.round(to * eased)); if (t < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); } }); }, { threshold: 0.4 }); io.observe(el); return () => io.disconnect(); }, [to, duration]); return {val}; } /* ---------------- Marquee ---------------- */ function Marquee() { const items = ["UI/UX Design", "Branding", "Web Development", "App Engineering", "Software Systems", "SEO & Growth", "Media Buying", "2D / 3D Motion"]; const row = ( {items.map((s, i) => ( {s} ))} ); return ( ); } window.Nav = Nav; window.Hero = Hero; window.HeroLamp = HeroLamp; window.Marquee = Marquee; window.AnimatedNum = AnimatedNum; window.ArrowSm = ArrowSm; window.ArrowLg = ArrowLg; /* ---------------- Video Reel ---------------- */ function VideoReel() { const [playing, setPlaying] = useState(true); const [unmuted, setUnmuted] = useState(false); const VIDEO_ID = "Nxb2KYTWLrM"; const params = new URLSearchParams({ autoplay: "1", mute: unmuted ? "0" : "1", loop: "1", playlist: VIDEO_ID, controls: "0", modestbranding: "1", rel: "0", playsinline: "1", iv_load_policy: "3", enablejsapi: "1", }); const src = `https://www.youtube-nocookie.com/embed/${VIDEO_ID}?${params.toString()}`; return (
The studio reel · 2025

Six years of shipping, in ninety seconds.

{playing ? ( ) : ( )}
LIVE · grabsoft studio reel
Watch on YouTube ↗
); } window.VideoReel = VideoReel;