Skip to content

Getting Started

Most people only need one package: @frapx/fx-canvas. It creates and manages a WebGL canvas over an existing DOM element and drives a fragment shader you provide — no scene graph, no cameras, no meshes.

Terminal window
pnpm add @frapx/fx-canvas
import { createShaderBackground, glsl } from "@frapx/fx-canvas";
createShaderBackground({
target: ".hero",
fragment: glsl`
precision highp float;
uniform vec2 u_resolution;
uniform vec2 u_pointerUv;
uniform float u_time;
void main() {
vec2 uv = gl_FragCoord.xy / u_resolution;
float glow = 0.5 + 0.5 * sin(u_time + uv.x * 8.0);
gl_FragColor = vec4(uv.x, u_pointerUv.y, glow, 1.0);
}
`
});

target is any CSS selector or element. @frapx/fx-canvas inserts a canvas into it, sizes it to match, and starts a render loop that supplies built-in uniforms — u_time, u_resolution, u_pointerUv, and more (see the @frapx/fx-canvas reference).

The render loop pauses automatically when the target scrolls offscreen or the tab is hidden — you don’t need to wire that up yourself. It also holds a static frame under the OS “prefers reduced motion” setting (respectReducedMotion, default true). Pass respectReducedMotion: false to keep animating and respond to the u_reducedMotion uniform, which is always supplied, inside the shader instead.

Add @frapx/react-canvas and use the <ShaderBackground /> component instead of calling createShaderBackground yourself:

Terminal window
pnpm add @frapx/fx-canvas @frapx/react-canvas
import { ShaderBackground } from "@frapx/react-canvas";
import { glsl } from "@frapx/fx-canvas";
const fragment = glsl`
precision highp float;
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 uv = gl_FragCoord.xy / u_resolution;
gl_FragColor = vec4(uv, 0.5 + 0.5 * sin(u_time), 1.0);
}
`;
export function HeroBackground() {
return <ShaderBackground fragment={fragment} className="hero-bg" />;
}