원클릭으로
lenis-integration
Lenis smooth scroll setup with Next.js App Router, ScrollTrigger integration, React lifecycle management, and known issues.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Lenis smooth scroll setup with Next.js App Router, ScrollTrigger integration, React lifecycle management, and known issues.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Adapt designs to work across different screen sizes, devices, contexts, or platforms. Implements breakpoints, fluid layouts, and touch targets. Use when the user mentions responsive design, mobile layouts, breakpoints, viewport adaptation, or cross-device compatibility.
Review a feature and enhance it with purposeful animations, micro-interactions, and motion effects that improve usability and delight. Use when the user mentions adding animation, transitions, micro-interactions, motion design, hover effects, or making the UI feel more alive.
Amplify safe or boring designs to make them more visually interesting and stimulating. Increases impact while maintaining usability. Use when the user says the design looks bland, generic, too safe, lacks personality, or wants more visual impact and character.
Improve unclear UX copy, error messages, microcopy, labels, and instructions to make interfaces easier to understand. Use when the user mentions confusing text, unclear labels, bad error messages, hard-to-follow instructions, or wanting better UX writing.
Add strategic color to features that are too monochromatic or lack visual interest, making interfaces more engaging and expressive. Use when the user mentions the design looking gray, dull, lacking warmth, needing more color, or wanting a more vibrant or expressive palette.
Add moments of joy, personality, and unexpected touches that make interfaces memorable and enjoyable to use. Elevates functional to delightful. Use when the user asks to add polish, personality, animations, micro-interactions, delight, or make an interface feel fun or memorable.
| name | lenis-integration |
| description | Lenis smooth scroll setup with Next.js App Router, ScrollTrigger integration, React lifecycle management, and known issues. |
| trigger_terms | lenis, smooth scroll, smooth scrolling, scroll behavior |
npm install lenis
Create a reusable Lenis provider for the App Router:
'use client';
import { useEffect, useRef } from 'react';
import Lenis from 'lenis';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
export function LenisProvider({ children }: { children: React.ReactNode }) {
const lenisRef = useRef<Lenis | null>(null);
useEffect(() => {
const lenis = new Lenis({
lerp: 0.1, // from design-dna motion.scroll.lenisLerp
smoothWheel: true,
orientation: 'vertical',
});
lenisRef.current = lenis;
// Connect Lenis to GSAP ScrollTrigger
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
return () => {
lenis.destroy();
lenisRef.current = null;
};
}, []);
return <>{children}</>;
}
Wrap the App Router layout:
// app/layout.tsx
import { LenisProvider } from '@/components/lenis-provider';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<LenisProvider>{children}</LenisProvider>
</body>
</html>
);
}
Lenis replaces the browser's native scroll. ScrollTrigger must be told about Lenis scroll position:
// This is the critical wiring -- without it, ScrollTrigger won't work with Lenis
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
For custom scroll containers (not document-level), use scrollerProxy:
ScrollTrigger.scrollerProxy(container, {
scrollTop(value) {
if (arguments.length) {
lenis.scrollTo(value, { immediate: true });
}
return lenis.scroll;
},
getBoundingClientRect() {
return {
top: 0, left: 0,
width: window.innerWidth,
height: window.innerHeight,
};
},
});
Always destroy Lenis on unmount:
useEffect(() => {
const lenis = new Lenis({ lerp: 0.1 });
// ... setup ...
return () => {
lenis.destroy();
};
}, []);
Lenis persists across route changes in App Router (if in layout). Scroll position resets automatically on navigation. If you need to preserve scroll:
// Scroll to top on route change (default behavior)
lenis.scrollTo(0, { immediate: true });
| Option | Default | Description |
|---|---|---|
lerp | 0.1 | Smoothness (0 = instant, 1 = no smoothing). Use motion.scroll.lenisLerp |
smoothWheel | true | Enable smooth wheel scrolling |
orientation | 'vertical' | Scroll direction |
gestureOrientation | 'vertical' | Touch gesture direction |
wheelMultiplier | 1 | Wheel scroll speed multiplier |
touchMultiplier | 2 | Touch scroll speed multiplier |
infinite | false | Infinite scrolling mode |
{
"motion": {
"scroll": {
"smoothing": true,
"lenisLerp": 0.1
}
}
}
Map smoothing: false to skip Lenis initialization entirely.
Lenis intercepts scroll. Use lenis.scrollTo('#target') instead of native anchor behavior:
const handleAnchorClick = (e: React.MouseEvent, target: string) => {
e.preventDefault();
lenis?.scrollTo(target);
};
Stop Lenis when modals are open to prevent background scrolling:
// When opening modal
lenis.stop();
// When closing modal
lenis.start();
Fixed elements work normally with Lenis. Sticky elements work but verify with ScrollTrigger pinning -- Lenis can sometimes interfere with pin calculations. Test thoroughly.
If frame rate drops below 30fps, consider:
lerp to 0.15-0.2 (less interpolation work)smoothWheel: false on mobile via matchMediaLenis must be initialized client-side only. The 'use client' directive on the provider handles this. Never import Lenis in server components.
After completing the work, before returning to the user, ask:
"Returned to bench. Anything here you'd rant about?"
If the user responds, append the entry to the current project's .orca/design-rants-pending.md in this format:
## YYYY-MM-DD HH:MM — [verb-name]
[user's response verbatim]
Create .orca/ in the current project if absent. Do NOT write to ~/.claude/ or to the ORCA-OS source tree directly. Pending entries are swept and categorized later via /impeccable extract rants.