Skip to content
Hz
esc
  • Micro
    Magnetic buttonR01 · quickTo
  • Line-mask headlineR02 · SplitText
  • OdometersoonR03 · Timeline
  • Text scrambleR04 · ScrambleText
  • Copy-button morphsoonR05 · MorphSVG
  • Directional underlinesoonR06 · Core
  • Squash togglesoonR07 · Core
  • Sliding tab indicatorR08 · Flip
  • Layout & scroll
    Flip filter gridR09 · Flip
  • Card to detailsoonR10 · Flip
  • Pinned horizontal galleryR11 · ScrollTrigger
  • Stacking cardssoonR12 · ScrollTrigger
  • Height-auto accordionR13 · Core
  • Scroll-read highlightR14 · ScrollTrigger
  • Clip-path image revealsoonR15 · Core
  • SVG line drawsoonR16 · DrawSVG
  • Physics & delight
    Velocity marqueeR17 · ScrollTrigger
  • Inertia carouselR18 · Draggable · Inertia
  • Route transitionR19 · App Router
  • Cursor followerR20 · quickTo
  • Toast stacksoonR21 · Flip
  • Draggable bottom sheetsoonR22 · Draggable
  • Cursor image trailsoonR23 · Core
  • Preloader handoffsoonR24 · Timeline
  • Pages
    All recipesHome
  • Easing labTool
  • DocsInstall and usage
  • AboutWhat Hz is
Docs

Using Hz

Every recipe is one small, typed React component. Install it with the shadcn CLI or copy the file. Either way the code lives in your project and is yours to change.

Requirements

A Next.js project using the App Router, React 19, and two packages: gsap and @gsap/react. Demos use Tailwind classes, but the recipes themselves don't depend on Tailwind.

Terminal
$ npm i gsap @gsap/react

Install a recipe

With the shadcn CLI, one command adds the component file and its dependencies. Every recipe page has the exact command on its Install tab.

Terminal
$ npx shadcn@latest add https://hz.sounakpal.dev/r/magnetic-button.json

Prefer not to use the CLI? Open the recipe, press Copy on the code panel, and paste it into a file in your components folder.

Use it

Import it like any other component. Every prop is typed and has a default, so you only pass what you want to change.

app/page.tsx
import { MagneticButton } from "@/components/magnetic-button";
export default function Page() {
return (
<MagneticButton strength={0.4} className="rounded-full bg-black px-6 py-3 text-white">
Get started
</MagneticButton>
);
}

Knobs are props

The knobs on a recipe page map to the component's props, and their defaults are the values you see in the code. Tune them on the page, then copy: the code you get has your values baked in as the new defaults.

GSAP in the App Router

Anything that animates runs in the browser, so recipe files start with "use client". All setup happens inside useGSAP, which reverts tweens and ScrollTriggers when the component unmounts, so navigating between pages never leaks animations. Register plugins once, at the top of the file that uses them.

components/pinned-horizontal-gallery.tsx
"use client";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(ScrollTrigger, useGSAP);

Reduced motion

Every recipe checks prefers-reduced-motion and has a real fallback, not just a disabled effect. Each recipe page says exactly what happens, and the stage has a toggle so you can see it without changing your system settings.

Inside a recipe
useGSAP(() => {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
// animation setup
});

Copy as prompt

The Copy as prompt button copies the recipe, its rules and your tuned code as one block you can paste into Cursor, Claude or any AI editor, so it adapts the recipe instead of reinventing it.

FAQ

Is GSAP free?
Yes. Since 2025 GSAP and all its plugins, including SplitText, MorphSVG and Inertia, are free to use. See GSAP's own license for the details.
Why not Framer Motion?
Nothing wrong with it. Hz exists because there are few GSAP-first collections written properly for React and the App Router.
A recipe says “Coming soon”.
It's queued for a later release. Recipes ship in batches, each with its notes and registry entry. See what's ready.