
Shaders is an open-source WebGPU component library for creating GPU effects in plain JavaScript, React, Vue, Svelte, and Solid.
Each effect is a component, and components can be stacked or nested into one canvas-rendered composition.
Props can update after initialization, follow pointer input, animate over time, or read values from another layer.
The registry cunrrently contains 199 components, including the structural Group component.
Features
- 199 canonical registry components across 10 categories.
- Plain JavaScript, React, Vue, Svelte, and Solid entry points.
- Layer stacking, nesting, blending, opacity, visibility, and masking.
- Runtime prop updates through
shader.update(). - Time-driven, pointer-driven, and layer-driven prop values.
- Layer transforms and component-aware bounding boxes.
- Row and column flow layout for
Group. - Output color-space and tone-mapping controls.
- Custom shader definitions with TypeScript and WGSL.
- WebGPU availability checks and terminal failure reporting.
- Browser editor, CLI, MCP integration, and agent skill.
How To Use Shaders
Installation
Plain JavaScript projects import the runtime from shaders/js. The package carries TypeGPU as a runtime dependency. Framework bindings use optional peer dependencies for React, Vue, Svelte, or Solid.
npm install shaders
Basic Usage
Give the canvas an explicit CSS size before initialization. Components render in array order. A later layer draws above earlier layers unless nesting changes the composition.
<canvas id="hero-shader"></canvas>
#hero-shader {
display: block;
width: 100%;
height: 400px;
}
import { createShader } from 'shaders/js'
const canvas = document.getElementById('hero-shader')
const shader = await createShader(canvas, {
components: [
{
type: 'LinearGradient',
id: 'background',
props: {
colorA: '#0f172a',
colorB: '#7c3aed',
angle: 45,
},
},
{
type: 'CursorTrail',
props: {},
},
],
})
Update Component Props At Runtime
Assign an id to any component that needs programmatic updates. update() accepts a partial props object. A static prop can also be replaced with a compatible dynamic prop driver.
shader.update('background', {
angle: 120,
colorB: '#06b6d4',
})
shader.update('background', {
angle: {
type: 'auto-animate',
mode: 'loop',
outputMin: 0,
outputMax: 360,
speed: 0.1,
},
})
Nest Components
Components that require child content can process a nested component tree.
const shader = await createShader(canvas, {
components: [
{
type: 'Blur',
props: {
intensity: 8,
},
children: [
{
type: 'LinearGradient',
props: {
colorA: '#111827',
colorB: '#a855f7',
},
},
],
},
],
})
Shared Layer Controls
| Property | Description |
|---|---|
blendMode | Controls how a layer composites with the layers below it. |
opacity | Sets layer opacity. |
visible | Removes a layer from composition when set to false. |
maskSource | References another component by id as a mask source. |
maskType | Selects the alpha or luminance channel used by the mask. |
transform | Applies offset, rotation, scale, anchor, and edge behavior. |
boundingBox | Positions, resizes, resamples, or clips components that declare bounding-box behavior. |
flow | Configures row or column layout on Group. |
absolute | Removes a child from an ancestor Group flow layout. |
Blend Modes
- Basic:
normal - Darkening:
multiply,darken,colorBurn,linearBurn - Lightening:
screen,lighten,colorDodge,linearDodge - Contrast:
overlay,softLight,hardLight - Difference:
difference,exclusion - Color:
hue,saturation,color,luminosity - Color-space blending:
normal-oklab,normal-oklch
Opacity And Visibility
opacity accepts values from 0 to 1.
visible: false removes the layer from the active composition. A layer with opacity: 0 continues to render. Hidden layers can act as mask sources.
Mask Layers
Give the mask component an id, set visible: false, and reference that ID through maskSource.
maskType accepts:
alphaalphaInvertedluminanceluminanceInverted
const shader = await createShader(canvas, {
components: [
{
type: 'Circle',
id: 'mask',
props: {
radius: 0.8,
visible: false,
},
},
{
type: 'LinearGradient',
props: {
colorA: '#22d3ee',
colorB: '#7c3aed',
maskSource: 'mask',
maskType: 'alpha',
},
},
],
})
Transform Layers
| Property | Default | Description |
|---|---|---|
offsetX | 0 | Horizontal offset. |
offsetY | 0 | Vertical offset. |
rotation | 0 | Rotation in degrees. |
scale | 1 | Layer scale. |
anchorX | 0.5 | Horizontal transform anchor from 0 to 1. |
anchorY | 0.5 | Vertical transform anchor from 0 to 1. |
edges | transparent | Edge handling outside the transformed layer. |
shader.update('background', {
transform: {
offsetX: 0,
offsetY: 0,
rotation: 12,
scale: 0.9,
anchorX: 0.5,
anchorY: 0.5,
edges: 'transparent',
},
})
Position Components With boundingBox
boundingBox is active only on components that declare bounding-box behavior. Partial objects are accepted and merged with a full-frame box. Dimensions use px or uv. A UV value of 1 represents the full size of the relevant canvas axis. lockAspect is an editor resize hint and has no renderer effect.
origin accepts top-left, top-center, top-right, center-left, center, center-right, bottom-left, bottom-center, and bottom-right.
| Property | Default |
|---|---|
x | { value: 0, unit: 'uv' } |
y | { value: 0, unit: 'uv' } |
width | { value: 1, unit: 'uv' } |
height | { value: 1, unit: 'uv' } |
origin | top-left |
rotation | 0 |
cornerRadius | None |
lockAspect | None |
shader.update('background', {
boundingBox: {
x: { unit: 'uv', value: 0.1 },
y: { unit: 'uv', value: 0.1 },
width: { unit: 'uv', value: 0.8 },
height: { unit: 'uv', value: 0.8 },
rotation: 12,
},
})
Group Flow Layout
Group can arrange measurable child components in a row or column. Set absolute: true on a child that should keep its own position outside the parent flow.
| Property | Default | Description |
|---|---|---|
mode | Required | none, column, or row. |
gap | None | Space between children in pixels or a dimensional value. |
align | center | Cross-axis alignment: start, center, or end. |
anchor | center | Pins the child block to a canvas anchor. |
anchorOffset | None | Pixel offset from the selected anchor. |
const shader = await createShader(canvas, {
components: [
{
type: 'Group',
props: {
flow: {
mode: 'row',
gap: 24,
align: 'center',
anchor: 'center',
},
},
children: [
{
type: 'Circle',
props: {
radius: 0.12,
color: '#22d3ee',
},
},
{
type: 'Circle',
props: {
radius: 0.12,
color: '#a855f7',
},
},
],
},
],
})
Dynamic Props
auto-animate
auto-animate changes a numeric or dimensional prop over time. easing applies to ping-pong mode.
| Property | Default | Description |
|---|---|---|
mode | Required | ping-pong or loop. |
outputMin | Required | Low output value. |
outputMax | Required | High output value. |
speed | 1 | Cycles per second. Negative values reverse loop direction. |
easing | sine | sine, linear, quad, expo, or bounce. |
waveform | Deprecated | Legacy sine or linear setting. Use easing. |
mouse-position
mouse-position drives a position prop from the pointer.
| Property | Default | Description |
|---|---|---|
x | mouse | Tracks pointer X or uses a fixed value from 0 to 1. |
y | mouse | Tracks pointer Y or uses a fixed value from 0 to 1. |
invertX | false | Reverses horizontal movement. |
invertY | false | Reverses vertical movement. |
smoothing | 0 | Follow lag from 0 to 1. |
momentum | 0 | Overshoot amount from 0 to 1. |
reach | 1 | Scales displacement from the origin point. |
originX | 0.5 | Horizontal displacement origin. |
originY | 0.5 | Vertical displacement origin. |
mouse
mouse maps one pointer axis to a numeric or dimensional prop.
| Property | Default | Description |
|---|---|---|
axis | Required | x or y. |
outputMin | Required | Output at axis position 0. |
outputMax | Required | Output at axis position 1. |
curve | 0 | Response curve from -1 to 1. |
smoothing | 0 | Follow lag from 0 to 1. |
momentum | 0 | Overshoot amount from 0 to 1. |
map
map uses another component’s rendered alpha or luminance as the control signal. The source component needs an id.
| Property | Default | Description |
|---|---|---|
source | Required | Source component id. |
channel | Required | alpha, alphaInverted, luminance, or luminanceInverted. |
inputMin | Required | Source value mapped to the low end. |
inputMax | Required | Source value mapped to the high end. |
outputMin | Required | Output for normalized input 0. |
outputMax | Required | Output for normalized input 1. |
curve | 0 | Response curve from -1 to 1. |
Output Color Space And Tone Mapping
colorSpace and toneMapping belong to the third ShaderOptions argument.
Output Color Space
p3-linearsrgb
Tone Mapping
linearreinhardcineonacesagxneutralhableunreal
const shader = await createShader(
canvas,
{
components: [
{
type: 'LinearGradient',
props: {
colorA: '#ff6b6b',
colorB: '#4ecdc4',
},
},
],
},
{
colorSpace: 'srgb',
toneMapping: 'aces',
}
)
JavaScript API Reference
PresetConfig
| Property | Type | Description |
|---|---|---|
components | ComponentConfig[] | Required component tree. |
structureVersion | number | Optional preset structure version. |
ComponentConfig
| Property | Type | Description |
|---|---|---|
type | string | Component type. |
id | string | Optional identifier for updates, masks, and mapped props. |
props | Record<string, any> | Component props and shared layer controls. |
children | ComponentConfig[] | Optional nested component tree. |
createShader()
createShader( canvas: HTMLCanvasElement, preset: PresetConfig, options?: ShaderOptions ): Promise<ShaderInstance>
ShaderOptions
Terminal onError values include unsupported, no-adapter, no-device, init-failed, device-lost, out-of-memory, gpu-error, render-failed, limit-exceeded, unrecoverable, and rebuild_failed.
components?: GpuShaderDefinition[]: Custom definitions referenced bytype.colorSpace?: 'p3-linear' | 'srgb': Output color space.toneMapping?: 'linear' | 'reinhard' | 'cineon' | 'aces' | 'agx' | 'neutral' | 'hable' | 'unreal': Tone-mapping operator.disableTelemetry?: boolean: Disables telemetry collection. Default:false.enablePerformanceTracking?: boolean: Enables performance tracking. Default:false.isPreview?: boolean: Preview-mode flag used by preview integrations.onReady?: () => void: Runs when rendering is ready.onError?: (reason: string) => void: Receives recoverable device-loss information and terminal GPU failures.observeElement?: boolean: Controls automatic resize and visibility observation. Default:true.gpu?: { device: GPUDevice; adapter: GPUAdapter }: Uses an externally managed WebGPU device and adapter.
ShaderInstance
| Method | Description |
|---|---|
getFailureReason() | Returns the terminal failure reason or null. |
update(componentId, props) | Updates props on the component with the matching id. |
resize(width?, height?) | Syncs rendering with the current canvas size or explicit pixel dimensions. |
pause() | Stops the animation loop and keeps the last rendered frame. |
resume() | Restarts the animation loop. |
destroy() | Stops the instance and releases renderer resources. |
WebGPU Availability And Debug Helpers
Environment-controlled debugging can use globalThis.__SHADERS_DEBUG__ = true or localStorage.setItem('shaders:debug', '1').
| Export | Description |
|---|---|
isWebGPUSupported() | Performs a synchronous WebGPU API presence check. Returns false during SSR. |
getWebGPUSupport() | Requests an adapter and caches { supported, reason? } for the page lifetime. |
setShadersDebug(enabled) | Forces diagnostic logging on or off. Pass null to restore environment-controlled behavior. |
isShadersDebug() | Returns the active diagnostic logging state. |
createPreview()
createPreview(canvas, options) creates a watermarked preview from a preview token or preset ID. Exactly one of shader or presetId is required. The returned instance includes the ShaderInstance methods plus setConfiguration(configuration).
| Option | Type | Description |
|---|---|---|
shader | string | Preview token. |
presetId | string | Preset identifier. |
apiBaseUrl | string | Optional API base URL. |
configuration | Record<string, unknown> | Initial key-prop overrides for presetId previews. |
version | string | Optional preset snapshot hash for presetId. |
createSharedDevice()
Normal shader instances reuse a lazily created page-level WebGPU device. createSharedDevice() is intended for application-owned device management, a specific adapter power preference, or interoperation with another WebGPU renderer.
powerPreference defaults to high-performance. The function returns null when a WebGPU device cannot be created.
createSharedDevice(options?: {
powerPreference?: GPUPowerPreference
}): Promise<{ device: GPUDevice; adapter: GPUAdapter } | null>
Framework Entry Points
Framework entry points expose <Shader>, <Preview>, <CustomShader>, and the generated component exports for that framework. WebGPU rendering begins in the browser. SSR integrations need client-side initialization.
| Environment | Import | Peer Requirement |
|---|---|---|
| JavaScript | shaders/js | Browser ESM environment with WebGPU. |
| React | shaders/react | React 18 or 19 and React DOM 18 or 19. |
| Vue | shaders/vue | Vue 3.5+. |
| Svelte | shaders/svelte | Svelte 5. |
| Solid | shaders/solid | Solid 1.8+. |
Built-In Components
- Textures (54): Aurora, Beam, Blob, BlockNoise, BlueNoise, BrickPattern, Checkerboard, Chevron, ColorWheel, ConicGradient, CurlNoise, DiamondGradient, DotGrid, ErosionNoise, FallingLines, FloatingParticles, FlowingGradient, FractalNoise, GaborNoise, Godrays, Grid, HexGrid, HTMLInCanvas, ImageTexture, IsometricCubes, LinearGradient, Marble, MeshGradient, MultiPointGradient, PerlinNoise, Plasma, Prism, RadialGradient, Ripples, Scratches, SimplexNoise, SineWave, SolidColor, Spiral, Strands, Stripes, StudioBackground, SunBurst, Swirl, Text, TriangularGrid, Truchet, VideoTexture, Voronoi, Waveform, WaveletNoise, Weave, WebcamTexture, WorleyNoise.
- Shapes (16): Arc, Circle, Crescent, Cross, Ellipse, Flower, Heart, Line, Parallelogram, Polygon, Ring, RoundedRect, Star, Teardrop, Trapezoid, Vesica.
- Shape Effects (23): BrushedMetal, CarbonFiber, Chrome, Crystal, Emboss, Frost, Glass, Goo, Heatmap, Hologram, Holographic, Irradiance, LightEdge, LiquidMetal, Nebula, Neon, Obsidian, Particles, Plastic, SmokeFill, ThinFilm, Voxels, Water.
- Stylize (31): Ascii, Chalkboard, ChromaticAberration, CompressionArtifacts, ContourLines, CRTScreen, DataMosh, Dither, DropShadow, Engraving, FilmGrain, Glitch, Glow, GradientMap, Halftone, KeyFrames, LensDistortion, LensFlare, LightLeak, ObjectTracker, Paper, ParticleField, Pixelate, ReflectivePlane, Sparkle, Stone, TimeTrail, VHS, Vignette, Watercolor, Wool.
- Interactive (16): Boids, ChromaFlow, CursorRipples, CursorTrail, Fog, GridDistortion, InkFlow, Liquify, MagneticFilings, ParticleFlow, PixelSort, PixelThrow, ReactionDiffusion, Shatter, Smoke, SmokeFlow.
- Distortions (22): BarShift, Bend, Bulge, ConcentricSpin, CornerPin, DisplacementMap, Flip, FlowField, FlutedGlass, Form3D, GlassTiles, Kaleidoscope, Mirror, Perspective, PolarCoordinates, RectangularCoordinates, Repeater, Spherize, Stretch, Surface3D, Twirl, WaveDistortion.
- Transitions (13): BarnDoors, BlockDissolve, CheckerWipe, DiamondWipe, IrisWipe, LinearWipe, NoiseDissolve, PagePeel, RadialWipe, RandomBars, RippleWipe, SliceWipe, VenetianBlinds.
- Blurs (9): AngularBlur, Blur, BokehBlur, ChannelBlur, DiffuseBlur, LinearBlur, ProgressiveBlur, TiltShift, ZoomBlur.
- Adjustments (14): BrightnessContrast, Duotone, Exposure, FilmStock, Grayscale, HueShift, Invert, Posterize, Saturation, Sharpness, Solarize, Tint, Tritone, Vibrance.
- Utilities (1): Group.
Custom Shader Components
Custom components use defineShader from shaders/std. A definition declares its component name, props, and pixel operation.
WGSL is the stable custom-shader option. The std primitives API is experimental.
import {
defineShader,
wgsl,
transformColor,
transformPosition,
} from 'shaders/std'
export const Halo = defineShader({
name: 'Halo',
props: {
color: {
default: '#ffd166',
transform: transformColor,
},
center: {
default: { x: 0.5, y: 0.5 },
transform: transformPosition,
},
radius: {
default: 0.6,
},
},
paint: wgsl`
let d = length((uv - center) * vec2f(aspect, 1.0)) / radius;
return vec4f(color.rgb, 1.0 - smoothstep(0.8, 1.0, d));
`,
})
Plain JavaScript Custom Components
Plain JavaScript passes custom definitions through ShaderOptions.components.
import { createShader } from 'shaders/js'
import { Halo } from './halo'
await createShader(
document.querySelector('canvas'),
{
components: [
{
type: 'Halo',
props: {
color: '#ffffff',
radius: 0.7,
},
},
],
},
{
components: [Halo],
}
)
Framework Custom Components
Framework projects mount a defineShader() result through <CustomShader>.
Design Editor, CLI, And AI Integrations
The browser editor builds component trees, edits props, drives values from pointer or timeline controls, and exports framework code.
CLI
npx shaders npx shaders connect npx shaders install npx shaders search "liquid chrome hero background" npx shaders preview <name> npx shaders update
Agent Skill
The agent skill can be installed directly.
npx shaders skill
MCP
The MCP installer configures compatible AI coding agents like Claude Code.
npx shaders@latest install-mcp
Alternatives & Related Resources
- Canvas UI: Fluid, Glass, and Shader Effects Over Live HTML
- Brightpixels: JavaScript Library for WebGPU HDR Text, Glow & Particles
- WebGL-Powered iOS-Style Liquid Glass Effects for JavaScript
- Recreate Balatro’s Animated Shader Effect with WebGL – balatroShader.js







