NewTunnel just landed

Shaders, shipped as components.

Animated WebGL backgrounds you install as source. No runtime dependencies, and every parameter exposed as a prop.

Now playing06Tunnel

Plain WebGL1

Hand-written WebGL1, from fullscreen fragment shaders to 3D point clouds. No three.js and no runtime dependencies.

Installs as source

The shadcn CLI copies each shader into components/shaders. Edit the GLSL as much as you like.

Light on battery

Pauses in hidden tabs and offscreen, draws a still frame for reduced motion, and caps DPR at 2.

Cursor-reactive

Push, lens, swirl, ripple or glow under the pointer, with an optional spring follow.

Quick start

One command, then it’s yours.

Every shader is a shadcn registry item. The CLI copies the component, its preset and the shared engine into your project. Override any uniform through props, or open the files and change them.

  1. 01InstallAdd a shader with the shadcn CLI. The files land in components/shaders.
  2. 02MountDrop it into any positioned container. It fills the box behind your content.
  3. 03TuneOverride colours, motion and the cursor effect through props.
$
pnpm dlx shadcn@latest add https://funshader.com/r/metaballs.json
app/hero.tsx
import { MetaballsShader } from "@/components/shaders/metaballs/metaballs-shader";

export function Hero() {
  return (
    <section className="relative isolate min-h-svh overflow-hidden">
      {/* Fills the nearest positioned parent, behind your content. */}
      <MetaballsShader className="-z-10" />
      <h1>Hello, shader.</h1>
    </section>
  );
}
Tuning with props
<MetaballsShader
  speed={0.6}
  colors={["#010A0A", "#02302E", "#118A7E", "#7FE3C4"]}
  cursor={{ effect: "ripple", strength: 0.5 }}
  vignette={0.5}
/>