✳ Nairobi, Kenya
- WhatsApp+254 799 756 331
- Emailhello@muvevi.com
- LinkedInlinkedin.com/in/muvevi
- GitHubgithub.com/mutua-muvevi
- Twitter / X@muvevi
Available for freelance & full-time roles.
Let's build something great.
GSAP ScrollTrigger + Lenis in Next.js App Router
— the right way
Every tutorial gets the Lenis + ScrollTrigger wiring wrong. Here's the exact setup that avoids jitter, scroll conflicts, and the memory leaks nobody warns you about.
Getting Lenis and GSAP's ScrollTrigger to play nicely in Next.js App Router took me longer than I'd like to admit. The core issue: ScrollTrigger fires on native scroll events by default, but Lenis intercepts and re-dispatches them — so without explicit wiring, the two fight each other and you get stuttering, incorrect trigger points, and animations that fire at the wrong scroll position.
The fix is three lines in your LenisProvider:
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => lenis.raf(time * 1000));
gsap.ticker.lagSmoothing(0);The first line tells ScrollTrigger to recalculate positions every time Lenis scrolls. The second feeds Lenis into GSAP's RAF loop so it runs at exactly the same tick — no double-RAF, no drift. The third disables GSAP's default lag smoothing which would otherwise introduce invisible latency.
There's also a cleanup concern. In React Strict Mode, your effect runs twice. If you initialise Lenis inside useEffect without a guard, you end up with two instances competing for scroll control. The fix is an instanceRef to hold the Lenis instance and a cleanup return that calls lenis.destroy() and ScrollTrigger.getAll().forEach(t => t.kill()).
For page transitions, you'll want to lenis.stop() before the exit animation and lenis.start() after the entrance — otherwise Lenis intercepts scroll during the transition and produces visual glitches.
One last thing that trips people up: gsap.context(). If you initialise ScrollTrigger animations inside a gsap.context() scoped to a ref, the triggers are automatically killed when ctx.revert() fires. But Lenis itself lives outside that context, so you must destroy it separately in the provider's cleanup.