genjutsu

Web

The five web modules: zero-dependency CSS, GSAP, Framer Motion, Three.js with React Three Fiber, and generative Canvas 2D.

All documentation

Selected from what your package.json already contains. If a library is there, its module loads and that choice is respected. If nothing is there, the zero-dependency module loads, and a dependency is proposed only when the thesis genuinely needs one.

css-native

The default when no animation library is present, and often the right answer even when one is.

It covers scroll-driven animation through animation-timeline, both scroll progress (scroll()) and view progress (view()) with animation-range and its named ranges. The View Transitions API in both flavours: same-document for SPAs, and cross-document for multi-page sites through @view-transition, including view-transition-name for shared elements and view-transition-class for styling a whole group.

Then @starting-style paired with transition-behavior: allow-discrete, which is what makes entrance animation from display: none work without JavaScript timing hacks. Anchor positioning for tooltips and popovers, with position-try-fallbacks treated as mandatory rather than optional. Container queries driving different animations at different component sizes. And the visual techniques: clip-path reveals and shape morphing, backdrop-filter, mix-blend-mode, mesh gradients approximated from layered radial gradients, and conic-gradient masking.

It carries a decision table for when to stop. Fewer than three animations, a scroll reveal, an enter or exit from display: none, a tooltip, a page transition: stay in CSS. A five-plus-step timeline, a stagger across a list of unknown length, an interruptible physics spring, an SVG shape morph: that is when a library earns its bytes.

Scroll-driven animation always ships behind @supports (animation-timeline: scroll()), and scroll-driven keyframes use animation-fill-mode: both, never forwards, which would lock the element in its end state on the way back up.

gsap

Loads when GSAP is already a dependency. Core, timelines, ScrollTrigger and the plugin set, plus the critical mistakes worth naming out loud.

Never proposed as a replacement for an existing library.

framer-motion

Loads when Motion for React is already a dependency. AnimatePresence and exit animation, layout animations, variant propagation and orchestration, gestures, and motion values for animating without triggering re-renders.

Also carries the comparison against the alternatives, so the answer to “should this be Framer Motion or CSS” is reasoned rather than habitual.

threejs-r3f

Three.js and React Three Fiber. Scene setup patterns, the R3F hook set, the essential Drei helpers, postprocessing, and the performance patterns that decide whether 3D on the web is viable or a frame-rate disaster.

canvas-generative

Algorithmic and generative art in Canvas 2D, and the module behind every mark on this site.

DPR-aware sizing so a canvas is sharp on a retina display, resize handling that re-renders rather than stretching, and delta-capped rAF loops. Noise selection: Perlin for terrain and clouds, simplex for flow fields and organic motion, Worley for cell and caustic patterns, with fractional Brownian motion for detail and seeding for reproducibility. Particle systems built on a pre-allocated pool with swap-and-shrink recycling, so nothing is allocated at runtime. Flow fields as a grid of noise-derived angles that steer particles. L-systems as string rewriting plus turtle graphics. Double buffering for trail effects.

Four prohibitions that decide whether a canvas piece is smooth or not: never clearRect when you want trails (fill translucently instead), never getImageData inside the loop because it stalls on a GPU readback, never skip DPR scaling, and never allocate inside update or render.