npx claudepluginhub darkroomengineering/cc-settingsThis skill uses the workspace's default tool permissions.
Set up Lenis for smooth scrolling. Both satus and novus include Lenis pre-wired — only set this up manually for projects that didn't start from a Darkroom template.
Implements scroll animations, parallax, pinning, scrubbing, horizontal scroll, and reveals using GSAP ScrollTrigger or Framer Motion in JavaScript, React, or Next.js.
Guides Locomotive Scroll implementation for smooth scrolling, parallax effects, viewport detection, sticky elements, horizontal scrolling, and GSAP ScrollTrigger integration in immersive websites.
Implements scroll-driven animations using GSAP ScrollTrigger: triggers, pinning, scrubbing timelines, parallax, and pinned sections.
Share bugs, ideas, or general feedback.
Set up Lenis for smooth scrolling. Both satus and novus include Lenis pre-wired — only set this up manually for projects that didn't start from a Darkroom template.
Read package.json:
dependencies.next → Next.js / satus mount pointdependencies["react-router"] → React Router / novus mount pointbun add lenis@latest
Check first: run bun info lenis to get the current version, and check package.json to see if it's already installed.
Both stacks use the same ReactLenis provider. The difference is where it's mounted.
// components/lenis/index.tsx (satus) or components/lenis/index.tsx (novus)
'use client' // satus only — RR doesn't need this directive
import { ReactLenis } from 'lenis/react'
interface LenisProps {
children: React.ReactNode
}
export function Lenis({ children }: LenisProps) {
return (
<ReactLenis
root
options={{
duration: 1.2,
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
orientation: 'vertical',
smoothWheel: true,
}}
>
{children}
</ReactLenis>
)
}
// app/layout.tsx
import { Lenis } from '@/components/lenis'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Lenis>{children}</Lenis>
</body>
</html>
)
}
// app/root.tsx
import { Lenis } from '~/components/lenis'
export default function Root() {
return (
<html>
<body>
<Lenis>
<Outlet />
</Lenis>
</body>
</html>
)
}
Both starters already ship Lenis wired up — check
components/lenis/and the root layout/root file before doing this manually.
import { useLenis } from 'lenis/react'
function Component() {
const lenis = useLenis()
const scrollToSection = () => lenis?.scrollTo('#section-id', { duration: 1.5 })
return <button onClick={scrollToSection}>Scroll</button>
}
useLenis(({ scroll, velocity, direction }) => {
// React to scroll
})
import { useLenis } from 'lenis/react'
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
useLenis(() => {
ScrollTrigger.update()
})
/docs lenis before implementing — APIs change.