cookbookcanonicalOWNER-2026-07-10

Cookbook — HOS-Webdoc Scroll-Kit Patterns · cb-patterns-hosweb

Owner directive (2026-07-10), canonical. "Bring all the pages with their concepts inside a folder with divided .MD … following every HOS methodology" — the scroll kit is the proven HOS methodology for app-shell scroll surfaces, mirrored Webdoc→HOSv6. [src: wiki/development/prompts-archive/by-topic/knowledge-management-and-concept-modeling.md:540]

Official docs

Patterns cookbook over our own kit: HOS-Webdoc/web/src/lib/scroll/ + web/src/components/scroll/ (Lenis+GSAP modern-scroll kit, 20+ modules). Library pins per cb-lenis, cb-gsap, cb-nextjs, cb-react, cb-tailwind.

Our proven patterns

  1. Scroller resolution is centralized. "The single place that knows WHERE the page scrolls": both HOS apps scroll a nested <main className="flex-1 overflow-y-auto">, not window/body; resolveScroller() walks up to [data-scroll-root], main. Every trigger uses it. [src: HOS-Webdoc/web/src/lib/scroll/scroller.ts:1]
  2. One provider, one RAF. SmoothScrollProvider mounts Lenis once in the root layout (autoRaf:false, GSAP ticker drives lenis.raf, scrollScrollTrigger.update); smooth scroll survives navigation. [src: HOS-Webdoc/web/src/components/scroll/SmoothScrollProvider.tsx:3]
  3. RouteScrollReset on App Router navigation — scroll to top (or #hash), then re-measure triggers, avoiding stale pin-spacers between pinned pages. [src: HOS-Webdoc/web/src/components/scroll/RouteScrollReset.tsx:3]
  4. Single plugin register module. GSAP + SplitText/MorphSVG/DrawSVG/ScrollTo registered once, re-exported from one client-only module; killAllScrollTriggers exported for teardown. [src: HOS-Webdoc/web/src/lib/scroll/register.ts:1]
  5. Data-driven module library. Every module takes ModuleProps { section, theme } — "Modules are data-driven (props, not children) so the same component re-skins per venture"; DEFAULT_SCRUB = 1 standardizes scrub feel. [src: HOS-Webdoc/web/src/lib/scroll/types.ts:12]
  6. Capability env, SSR-guarded. prefersReducedMotion() (static resting states + no Lenis), supportsWebGL() (gates lazy WebGL modules to CSS siblings), isTouch() (native overflow for marquee/horizontal/infinite). [src: HOS-Webdoc/web/src/lib/scroll/env.ts:1]
  7. Module inventory (components/scroll/modules): DepthParallax, Hero3D, HorizontalScroll, ParallaxLayers, PinnedReveal, PlainSection, ShaderDistortion, StickyStack, TextClipReveal, VelocityMarquee + webgl/ siblings — compose pages from these before writing new ones. [src: HOS-Webdoc/web/src/components/scroll/modules/index.ts:1]

Gotchas

  • Nested-main: any third-party snippet assuming window scroll (including ScrollTrigger defaults) silently breaks — always pass the resolved scroller. [src: HOS-Webdoc/web/src/lib/scroll/scroller.ts:8]
  • Observer/Flip TS1149 casing conflict — do not register them; use ScrollTrigger implementations instead. [src: HOS-Webdoc/web/src/lib/scroll/register.ts:19]
  • Per-frame class churn causes reflow — the RUN-015 perf pass fixed a per-frame reflow and added a reduced-motion gate; style per frame only via CSS custom properties. [src: runs/RUN-015-autoloop.json:88]
  • Server components must not import the register module — plugins touch window. [src: HOS-Webdoc/web/src/lib/scroll/register.ts:11]

Budgets

All module and page work is gated by bm-001-web-perf (fps/LCP/CLS/a11y) and, for splat surfaces, bm-002-splat-budget.

Composition

See also

Linked from — 9 cards