Shader starter kit
The Shader Starter Kit demonstrates how to integrate WebGL shaders with [tldraw](https://github.com/tldraw/tldraw). It creates dynamic backgrounds that respond to canvas interactions, and includes four complete examples and a reusable `WebGLManager` base class for building custom shader effects.
To build with a shader starter kit, run this command in your terminal:
npm create tldraw@latest -- --template shaderUse cases
Use the shader starter kit to build:
Immersive creative tools
Layer animated, touch-responsive backgrounds behind your drawing UI for design or storytelling apps.
Data-rich dashboards
Highlight state changes or live metrics using GPU-driven gradients and particle systems that react to editor data.
Games and interactive experiences
Combine tldraw shapes with shader-based effects to build puzzle overlays, interactive maps, or ambient scenes.
Live events and streaming overlays
Drive real-time graphics for broadcast overlays or virtual stages that react to presenter actions.
Educational demos
Teach graphics concepts with interactive examples that expose shader parameters through the config panel.
How it works
WebGLManager lifecycle
The reusable WebGLManager class (src/WebGLManager.ts) creates and manages a WebGL2 context that is synchronized with the tldraw canvas. It owns the render loop and exposes lifecycle hooks—onInitialize(), onUpdate(), onRender(), and onDispose(). Each shader manager can focus on its effect-specific logic while sharing viewport coordination, resolution control, and animation timing. The Minimal, Rainbow, and Shadows examples extend this base class; the Fluid example uses a different architecture with its own simulation system.
Config panel system
The config panel components (src/config-panel/) provide ready-made UI controls for editing shader uniforms. Each panel stores settings in reactive atoms and persists them to localStorage, so your shader parameters survive reloads without extra wiring.
Example gallery
The template ships with four complete demos that follow the same pattern of manager, renderer, config panel, and GLSL files:
- Fluid simulation (
src/fluid/) — Navier-Stokes-based flow that turns pointer movement into velocity splats. Includes an in-depth guide. - Rainbow (
src/rainbow/) — Gradient animation that demonstrates time-based uniforms and color cycling. - Shadows (
src/shadow/) — Raymarched shadow effect using signed distance fields derived from canvas geometry. - Minimal (
src/minimal/) — Dark-mode-aware solid color shader that makes it easy to start your own effect, with a step-by-step walkthrough.
Switch between demos from the example menu next to the style panel to see how different managers plug into the same infrastructure.
Fluid simulation
A real-time fluid simulation based on Pavel Dobryakov's WebGL fluid implementation. Shape movements create dynamic flows in the simulation.
- Navier-Stokes fluid dynamics
- Shape movements create velocity-based splats
- Configurable physics and visual effects
See: src/fluid/ | Documentation
Rainbow
An animated gradient shader demonstrating time-based effects and uniform management.
See: src/rainbow/
Shadows
Dynamic shadow casting from tldraw shapes using raymarching and signed distance fields.
See: src/shadow/
Minimal
A bare-bones template for starting new shader projects. Renders a solid color that adapts to dark mode.
See: src/minimal/ | Documentation
Customization
Start from the minimal template
Copy the minimal shader to create a new effect:
cp -r src/minimal src/my-shaderThen update:
config.ts— Define uniforms and UI controls for your shader.fragment.glsl/vertex.glsl— Implement rendering logic.MyShaderManager.ts— ExtendWebGLManagerand coordinate buffers, uniforms, and lifecycle hooks.MyRenderer.tsx— Mount the manager from React and handle cleanup.MyConfigPanel.tsx— Customize the controls exposed to users.
Finally, register the new manager in src/App.tsx.
Extend WebGLManager hooks
Each manager can override lifecycle hooks to add render targets, resize behavior, or post-processing passes. Use onInitialize() to set up buffers, textures, and framebuffers; onUpdate() for per-frame uniform updates (such as time, resolution, or editor-driven state); and onRender() to issue draw calls. The base class also exposes helpers for handling pixel density and canvas resizes.
Integrate with tldraw data
Every manager receives the live tldraw editor instance, which lets you:
- Access shapes with
editor.getCurrentPageShapes(). - Subscribe to document changes through
editor.store.listen(). - Read the current camera via
editor.getCamera(). - Convert coordinates with
editor.pageToViewport(). - Track pointer data from
editor.inputs.getCurrentScreenPoint().
See src/fluid/FluidManager.ts for a full example of mixing editor state with GPU simulation.
Resources
- WebGL2 Fundamentals - WebGL tutorials
- The Book of Shaders - GLSL shader programming
- Shadertoy - Shader examples
Further reading
For multi-user shader environments, see the Multiplayer Starter Kit. To create custom shapes with advanced geometry and rendering, see Shape Utilities. For working with tldraw's reactive state system and event handling, see Editor State Management.
Building with this starter kit?
If you build something great, please share it with us in our #show-and-tell channel on Discord. We want to see what you've built!