Quickstart
By the end of this page you'll have a gradient with a cursor trail running in your app, sized with CSS and driven by state. Pick your framework in any code block and every block follows; plain JavaScript works too.
Installing the package
Shaders is one package for every framework:
npm install shaders
Import the components from the entry point for your framework: shaders/vue, shaders/react, shaders/svelte or shaders/solid. Without a framework, the JavaScript API comes from shaders/js.
Rendering your first effect
Let's start with a gradient and put a cursor trail on top of it. Add this component anywhere in your app:
Move your cursor over the canvas to see the trail.
<Shader> renders a single <canvas>. The components inside it are layers, drawn in order like layers in Figma: the gradient first, then the trail on top. In plain JavaScript you bring the <canvas>, and each entry in components is a layer.
Sizing the canvas
The canvas has no size of its own. It takes whatever size you give <Shader> through class (className in React) or style:
The canvas resizes itself when its CSS size changes, so you don't need to call anything on resize. Style <Shader>, not the <canvas> inside it: the internal markup can change between releases. In plain JavaScript, call shader.resize() if you change the canvas size from script.
Setting props
Each component takes props the same way any component in your framework does. In Vue, attributes are kebab-case and non-string values need the : binding; in plain JavaScript they go in each component's props object:
colorSpace="oklch" blends the two colors through a perceptual color space, so the middle of the gradient stays bright instead of going gray. Every component's props, with defaults and ranges, are in the component docs, and the design editor exports any effect you build as code.
Driving a prop from state
Props accept your framework's state like any other prop. In plain JavaScript, give the component an id and pass new props to shader.update(). We'll wire the gradient's angle to a range input:
Drag the slider and the gradient turns on the next frame. Changing angle updates a value on the GPU; the effect doesn't recompile.
Cleaning up
The framework components clean up after themselves: when <Shader> unmounts, rendering stops and its GPU memory is freed. In plain JavaScript, call destroy() when the canvas leaves the page, for example on a route change in a single-page app:
shader.destroy()
Using server rendering
Shaders needs a browser with a GPU, so it can't render on the server. Each meta-framework handles this differently:
- Next.js: put
'use client'at the top of any file that renders a<Shader>. See Using Next.js. - Nuxt: wrap the
<Shader>in<ClientOnly>. See Using Nuxt. - SvelteKit: nothing to do, because
<Shader>renders nothing on the server and starts on the client. See Using SvelteKit. - SolidStart: load the component that renders a
<Shader>withclientOnly. See Using SolidStart.
Next steps
- Composing effects: stack and nest components, blend and mask layers.
- Layout and positioning: place the canvas behind or around your UI.
- Props and reactivity: bind state to props and animate them.
- Component docs: every component with a live preview and its props.