Documentation

Quickstart (React)

Install the npm package

npm install shaders

Import some components

import { Shader, LinearGradient, CursorTrail } from 'shaders/react'

Your first shader

Let's create a very simple shader:

<Shader className="w-full h-64">
  <LinearGradient colorA="#0f172a" colorB="#7c3aed" />
  <CursorTrail />
</Shader>

<Shader> renders a <canvas> element. Child components are visual layers evaluated top to bottom, blended together on the GPU. In this example, we render the linear gradient first, and then the cursor trail effect on top of that.

Sizing the canvas

The <canvas> has no intrinsic size. The className or style you apply to <Shader> controls the canvas size and position.

{/* Fill the viewport */}
<Shader className="w-screen h-screen">
  <LinearGradient />
</Shader>

{/* Fixed dimensions */}
<Shader style={{ width: '600px', height: '400px' }}>
  <LinearGradient />
</Shader>

{/* Fluid with aspect ratio */}
<Shader className="w-full aspect-video">
  <LinearGradient />
</Shader>

Applying a className or style to the <Shader> tag is preferred over trying to target the <canvas> element directly, as the internal DOM structure may change in the future.

Configuring components

Pass props directly to configure each component. All props use camelCase:

<Shader className="w-full h-64">
  <LinearGradient
    colorA="#ff6b6b"
    colorB="#4ecdc4"
    angle={45}
    colorSpace="oklch"
  />
</Shader>

Props also accept state — useState and any other reactive value work exactly as you'd expect:

import { useState } from 'react'
import { Shader, LinearGradient } from 'shaders/react'

export default function MyShader() {
  const [angle, setAngle] = useState(0)

  return (
    <>
      <Shader className="w-full h-64">
        <LinearGradient colorA="#ff6b6b" colorB="#4ecdc4" angle={angle} />
      </Shader>

      <input
        type="range"
        min={0}
        max={360}
        value={angle}
        onChange={e => setAngle(Number(e.target.value))}
      />
    </>
  )
}

When angle changes, the shader updates on the GPU instantly — no recompilation, no flicker.

Browse the Component Docs for the full prop reference on every component.

Using with Next.js / SSR

Shaders only works client-side, as it needs a GPU to run. See the Next.js / SSR guide for how to set it up with server-side rendering.

Next steps