diff --git a/Concepts.md b/Concepts.md
index 4cff445..c3e10fe 100644
--- a/Concepts.md
+++ b/Concepts.md
@@ -1,8 +1,9 @@
| Term | Meaning |
|---|---|
-| **Asset** | Named thing with a type (`scene`, `camera`, `sprite`, `text`, `behavior`, `collider`, `container`, `texture`, `animation`, `statemachine`) and typed properties. Assets have **no position**. |
-| **Texture** | An uploaded image. Scenes, textures, animations and state machines are the four types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). |
+| **Asset** | Named thing with a type (`scene`, `camera`, `sprite`, `text`, `behavior`, `collider`, `container`, `texture`, `animation`, `statemachine`, `shader`) and typed properties. Assets have **no position**. |
+| **Texture** | An uploaded image. Scenes, textures, animations, state machines and shaders are the five types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). |
| **State machine** | A named set of **states**, edited as nodes in its own tab. A behavior puts it into a state with `Set state` and branches on it with `State branch`; each behavior instance keeps its own current state. See [State machines](State-machines). |
+| **Shader** | A node graph that becomes the GLSL a sprite is drawn with, edited in its own tab. A sprite wears it through `shader`; the numbers the graph declares are rows below that dropdown. See [Shaders](Shaders). |
| **Text** | An asset that draws a line of text (`text`, `fontSize`, `color`, `align`) — titles, HUD readouts, button labels. Its content is an ordinary property, so a `Properties` node of type Text with `text` switched to Set changes it while playing. |
| **Enabled** | Every placeable asset has the switch `enabled` (default on). A disabled object is not drawn, does not collide and its behavior does not run — **and neither does anything parented below it**. Switching one instance off is a normal override, which makes a container a *screen*: switch it on to show it, off to hide it. From a graph, `Properties` with `enabled` switched to Set does it, and `Is enabled` asks (including the parents); a behavior hears the switch as `On enable` / `On disable`. |
| **Scene object** | An asset placed into a scene: a link to the asset + a **position** (`x`, `y`, `z`) + sparse **overrides** of the asset's properties + an optional **parent** (another object of the scene). Scenes cannot be placed. |
diff --git a/Development.md b/Development.md
index 0e3c02f..0939108 100644
--- a/Development.md
+++ b/Development.md
@@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
# code is lost (tail's is reported), so a red run reads as green
npm run build # writes dist/ and regenerates index.html
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
-node tools/seed-e2e.mjs && node tools/e2e.mjs # 671 editor checks, screenshots in /tmp/gm-e2e-*.png
+node tools/seed-e2e.mjs && node tools/e2e.mjs # 700 editor checks, screenshots in /tmp/gm-e2e-*.png
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
./e2e.sh start [GM_STEPS] # the same run detached, see below
./e2e.sh status # live progress, or the last run's result
@@ -150,4 +150,4 @@ widths to find click points. The **render device is not in this repo** — `/dev
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
-WebGL 2.0, and the same 671 checks as here.
+WebGL 2.0, and the same 700 checks as here.
diff --git a/Home.md b/Home.md
index 6a061e3..b7177a1 100644
--- a/Home.md
+++ b/Home.md
@@ -16,6 +16,7 @@ Live: · Widget playground: `), `src/viewport/shaders.ts` wraps the result in a filter
+and `src/viewport/ShaderLibrary.ts` caches it per asset. The rows come from
+`shaderParamDefs(graph)` in `src/core/properties/shaders.ts`; `schemaForAsset` and
+`schemaForObject` (`PropertySchema.ts`) append them to a sprite's schema, which is why both take
+the project.
diff --git a/_Sidebar.md b/_Sidebar.md
index a03ef91..36e85de 100644
--- a/_Sidebar.md
+++ b/_Sidebar.md
@@ -7,6 +7,7 @@
- [Textures](Textures)
- [Animations](Animations)
- [State machines](State-machines)
+- [Shaders](Shaders)
- [Containers](Containers)
- [Keyboard](Keyboard)