diff --git a/docs.json b/docs.json
index 75a74145..0be0eab4 100644
--- a/docs.json
+++ b/docs.json
@@ -27,7 +27,7 @@
"pricingVoyagerYearly": "$304",
"pricingEnterpriseYearly": "$1,440",
"versionMajorWebGL2": "2",
- "versionWebGL2": "2.38.3",
+ "versionWebGL2": "2.40.0",
"supportForm": "https://forms.rive.app/support?utm_medium=support_page",
"supportFormEducational": "https://forms.rive.app/education?utm_medium=support_page"
},
diff --git a/feature-support.mdx b/feature-support.mdx
index cfec3727..ad7cd9e6 100644
--- a/feature-support.mdx
+++ b/feature-support.mdx
@@ -24,13 +24,17 @@ When a feature requires API changes, migration notes will be included below.
### Runtimes
- Choose between @rive-app/webgl2 and @rive-app/canvas, with guidance on performance, package size, and when to use canvas-lite.
+ The recommended package for most web projects. Uses the Rive Renderer, so it supports every Rive Editor feature, including vector feathering. See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl).
- For better performance and the latest features, like vector feathering, we recommend using the WebGL2 runtime, which uses the Rive Renderer.
+ Uses the browser's Canvas2D renderer. Does not support vector feathering at this time. See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl) for the tradeoffs.
+
+
+ The recommended package for most React projects. Uses the Rive Renderer, so it supports every Rive Editor feature, including vector feathering. See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl).
+
+
+ Uses the browser's Canvas2D renderer. Does not support vector feathering at this time. See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl) for the tradeoffs.
-
-
@@ -53,12 +57,12 @@ When a feature requires API changes, migration notes will be included below.
- The `@rive-app/webgl` runtime is deprecated. For better performance and the latest features, use `@rive-app/webgl2`.
+ The `@rive-app/webgl` runtime is deprecated as of `v2.37.0`. Use `@rive-app/webgl2` (recommended for most content), or `@rive-app/canvas` if your Rive graphics do not require vector feathering.
- The `@rive-app/react-webgl` runtime is deprecated. For better performance and the latest features, use `@rive-app/react-webgl2`.
+ The `@rive-app/react-webgl` runtime is deprecated as of `v4.30.0`. Use `@rive-app/react-webgl2` (recommended for most content), or `@rive-app/react-canvas` if your Rive graphics do not require vector feathering.
diff --git a/runtimes/getting-started.mdx b/runtimes/getting-started.mdx
index 4597e5a2..c77b1a72 100644
--- a/runtimes/getting-started.mdx
+++ b/runtimes/getting-started.mdx
@@ -85,7 +85,7 @@ Check out the runtime subpages for steps on how to get started!
- [webgl2](https://www.npmjs.com/package/@rive-app/webgl2)
- [canvas-lite](https://www.npmjs.com/package/@rive-app/canvas-lite)
- **See [Canvas vs WebGL](/runtimes/web/canvas-vs-webgl) for package guidance and sizing tradeoffs.**
+ **See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl) for package guidance and sizing tradeoffs.**
diff --git a/runtimes/web/canvas-vs-webgl.mdx b/runtimes/web/canvas-vs-webgl.mdx
index 74747cb2..868291b3 100644
--- a/runtimes/web/canvas-vs-webgl.mdx
+++ b/runtimes/web/canvas-vs-webgl.mdx
@@ -1,73 +1,76 @@
---
title: "Canvas vs WebGL2"
-description: "Choose between `@rive-app/webgl2` and `@rive-app/canvas`, with guidance on performance, package size, and when to use canvas-lite."
+description: "Choose between the @rive-app/webgl2 and @rive-app/canvas runtime packages."
---
-### Choose a runtime
+Rive's web runtime comes in two main packages: [`@rive-app/webgl2`](https://www.npmjs.com/package/@rive-app/webgl2) and [`@rive-app/canvas`](https://www.npmjs.com/package/@rive-app/canvas). They expose the same API. The only difference is how they draw.
-For web, start by choosing one of these two packages:
+**For most use cases, use `@rive-app/webgl2`.** It draws with the Rive Renderer, the same renderer as the Rive Editor, so everything you can author in Rive renders the way you designed it. `@rive-app/canvas` uses the browser's own 2D renderer, which brings its own advantages (particularly for performance), but it does not yet support every Editor feature.
-- [`@rive-app/webgl2`](https://www.npmjs.com/package/@rive-app/webgl2)
-- [`@rive-app/canvas`](https://www.npmjs.com/package/@rive-app/canvas)
+Switching is a one-line import change, so you can try both and measure against your own content.
-They share the same high-level API, so switching packages does not require changing how you create a `new Rive({...})` instance. The key differences are the renderer and package size; read the sections below to decide what is best for your use case, and compare package sizes on [Runtime Sizes](/runtimes/runtime-sizes/).
+## Comparison
-### `@rive-app/webgl2` (recommended)
+| | `@rive-app/webgl2` (recommended) | `@rive-app/canvas` |
+| --- | --- | --- |
+| Draws with | The [Rive Renderer](https://rive.app/renderer?utm_source=docs&utm_medium=content) on WebGL2 | The browser's [Canvas2D](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) API |
+| [Vector Feathering](/editor/fundamentals/fill-and-stroke#vector-feathering) | ✅ Supported | ❌ Not yet supported; planned for a future release |
+| Editor fidelity | ✅ The same renderer the Rive Editor uses | 🟡 Matches for nearly all content (see [Fill Rules](#fill-rules)) |
+| Blend modes | 🟡 All blend modes, but anything other than **Normal** is expensive (see [Performance](#performance)) | ✅ All blend modes, at no extra cost |
+| Graphics per page | 🟡 Bound by the browser's WebGL context limit (see [WebGL Context Limits](#webgl-context-limits)) | ✅ No practical limit |
-Use `@rive-app/webgl2` if you want the best rendering quality and performance in most cases.
+## Other notable tradeoffs
-```bash
-npm install @rive-app/webgl2
+### WebGL Context Limits
+
+Note that if you're using `@rive-app/webgl2`, browsers cap how many WebGL contexts a page can hold at once. The exact number varies by browser and device, and the oldest context is typically dropped once the cap is reached — which limits how many `new Rive({...})` instances you can run. See [WebGL Context Limits](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_context_limits) for more details.
+
+If you show several graphics on one page, set `useOffscreenRenderer: true` on each Rive object. Every instance then shares a single offscreen context instead of creating its own, which keeps you under the cap:
+
+```javascript
+const r = new rive.Rive({
+ src: "https://cdn.rive.app/animations/vehicles.riv",
+ canvas: document.getElementById("canvas"),
+ useOffscreenRenderer: true,
+});
```
-- Uses the [Rive Renderer](https://rive.app/renderer?utm_source=docs&utm_medium=content) for the best rendering performance
-- Supports Rive Renderer-only features (for example, vector feathering)
+This limit does not apply to `@rive-app/canvas`.
-
- WebGL has browser limits on concurrent contexts, which can limit how many `new Rive({...})` instances you can run at once. If you display many graphics on the same page, set `useOffscreenRenderer: true` for each Rive object.
- This moves rendering work to a shared offscreen WebGL context instead of creating as many separate contexts on visible canvases, which helps avoid context-limit issues and improves stability when many Rive instances are active.
-
-
- Enabling the draft
- [WEBGL_shader_pixel_local_storage](https://www.wikihow.tech/Enable-WebGL-Draft-Extensions-in-Google-Chrome)
- extension in Chrome improves rendering performance. Without it, Rive falls
- back to an MSAA-based WebGL2 path. We are actively working with browser
- vendors to make this enabled by default.
-
+### Fill Rules
-### `@rive-app/canvas`
+`@rive-app/canvas` uses the Canvas2D renderer, which offers the non-zero and even-odd [fill rules](/editor/fundamentals/fill-and-stroke#fill-rule), so Rive's clockwise fill rule draws as non-zero. The result is identical unless a path has self-intersecting, reversed, or overlapping contours. This applies to both fills and clipping paths.
-Use `@rive-app/canvas` when your graphics are less complex and you want a smaller runtime package.
+## Performance
-```bash
-npm install @rive-app/canvas
-```
+Today, `@rive-app/webgl2` draws through a multisample anti-aliasing (MSAA) path.
+
+The Rive Renderer has a faster path to draw that relies on a GPU capability Metal and Vulkan already expose to native apps. On web browsers, it comes from [`WEBGL_shader_pixel_local_storage`](https://www.khronos.org/registry/webgl/extensions/WEBGL_shader_pixel_local_storage/), a draft WebGL extension that Rive is helping to standardize. As browsers adopt it, `@rive-app/webgl2` will pick it up automatically and draw faster.
+
+Until then, blend modes are where you may notice a difference. On the MSAA path, any blend mode other than **Normal** forces the renderer to re-read the frame as it draws, and that cost adds up quickly on mobile browsers. `@rive-app/canvas` has no equivalent cost, because Canvas2D blends natively.
+
+In practice:
-- Uses the browser's built-in [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) renderer
-- Smaller package size than the WebGL2 renderer option
-- Good for simpler vector/raster graphics
+- Blend modes on mobile are the case where `@rive-app/canvas` can be meaningfully faster. If your file leans on them and does not use Vector Feathering, it is worth comparing the two.
+- Measure on real devices. Swapping packages is a one-line change, so testing both is cheap.
-### More options after your runtime choice
+## Canvas Package Variants
-For the canvas-based runtime option, you can alternatively use these variants based on packaging needs.
+Two variants of the canvas package are available if you have specific bundling needs.
-#### `@rive-app/canvas-lite` variant
+### `@rive-app/canvas-lite`
-The canvas version of our runtime supports a `-lite` variant for smaller package size.
+[`@rive-app/canvas-lite`](https://www.npmjs.com/package/@rive-app/canvas-lite) is the smallest Rive web package. It has the same API and renderer as `@rive-app/canvas`, but drops the text, layout, audio, and scripting engines to save space.
-- Example: [`@rive-app/canvas-lite`](https://www.npmjs.com/package/@rive-app/canvas-lite)
-- Use this package when you want the smallest runtime footprint
-- This package variant removes some features (for example, text, layout, audio, and scripting engines)
+Use it when your files do not rely on those features. If a file does use them, the affected content will not appear.
-#### `@rive-app/canvas-single` variant
+### `@rive-app/canvas-single`
-The canvas version of our runtime supports a `-single` variant, which bundles `rive.wasm` directly into the JavaScript file.
+[`@rive-app/canvas-single`](https://www.npmjs.com/package/@rive-app/canvas-single) bundles `rive.wasm` directly into the JavaScript file, so loading Rive takes one network request instead of two.
-- Example: [`@rive-app/canvas-single`](https://www.npmjs.com/package/@rive-app/canvas-single)
-- Use this package if you want to avoid a separate WASM network request
-- Expect a larger JS bundle compared to the standard package
+Use it when you want to avoid a separate WASM request. The tradeoff is a larger JavaScript bundle.
-### Deprecated package
+## Deprecated Package
-`@rive-app/webgl` is deprecated and will no longer receive updates after `v2.37.0`. Prefer `@rive-app/webgl2`.
+`@rive-app/webgl` is deprecated and receives no updates after `v2.37.0`. Move to `@rive-app/webgl2`, or to `@rive-app/canvas` if your file does not need the Rive Renderer. Neither move requires API changes — see the [migration guide](/runtimes/web/migration-guides).
diff --git a/runtimes/web/faq.mdx b/runtimes/web/faq.mdx
index 1d01de21..ac892be4 100644
--- a/runtimes/web/faq.mdx
+++ b/runtimes/web/faq.mdx
@@ -20,7 +20,7 @@ Read more on [what CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
Yes! You may notice that starting in `v2.0.0` of the web runtimes, the size of the `rive.wasm` file requested on the browser increased. This was due to including a new dependency in the WASM build for a text engine that supports the powerful and flexible [Rive Text](/editor/text/) feature.
-However, if you don't have a need to use the native Rive Text feature (or prefer to use imported SVG text), you can use the [@rive-app/canvas-lite](/runtimes/web/web-js#canvas-vs-webgl) which provides the same API and similar rendering capabilities as `@rive-app/canvas`, with a smaller package.
+However, if you don't have a need to use the native Rive Text feature (or prefer to use imported SVG text), audio, layouts, or scripting, you can use the [@rive-app/canvas-lite](/runtimes/web/canvas-vs-webgl#rive-app-canvas-lite) which provides the same API and similar rendering capabilities as `@rive-app/canvas`, with a smaller package.
### Why did the canvas width/height attribute values change?
diff --git a/runtimes/web/web-js.mdx b/runtimes/web/web-js.mdx
index 47a91b41..54832131 100644
--- a/runtimes/web/web-js.mdx
+++ b/runtimes/web/web-js.mdx
@@ -22,14 +22,12 @@ This guide documents how to get started using the Rive web runtime library. The
Follow the steps below to integrate Rive into your web app.
-The following instructions describe using the `@rive-app/webgl2` package. Rive provides web-based packages like WebGL2, Canvas, and Lite versions.
-
-See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl) for guidance on which package is the correct choice for your use case.
+These instructions use `@rive-app/webgl2`, the package we recommend for most projects. It draws with the Rive Renderer, the same renderer as the Rive Editor, so it supports everything you can author in Rive including [Vector Feathering](/editor/fundamentals/fill-and-stroke#vector-feathering). Rive also publishes Canvas2D packages with a different set of tradeoffs — see [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl). The packages share the same API surface, so you can switch to a different one easily if needed.
- We recommend always using the [latest version](https://www.npmjs.com/package/@rive-app/webgl2) when possible. The versions listed below and in the examples may differ from the latest. You van find the latest
+ We recommend always using the [latest version](https://www.npmjs.com/package/@rive-app/webgl2) when possible. The versions listed below and in the examples may differ from the latest. You can find the latest
version on [npmjs](https://www.npmjs.com/package/@rive-app/webgl2?activeTab=versions).
@@ -79,7 +77,7 @@ See [Canvas vs WebGL2](/runtimes/web/canvas-vs-webgl) for guidance on which pack
- Not using [Rive Text](/editor/text/), [Rive Layouts](/editor/layouts/), [Rive Scripting](/scripting/), or [Rive Audio](/editor/events/audio-events)? Consider using [@rive-app/canvas-lite](/runtimes/web/canvas-vs-webgl#rive-app-webgl2-lite) instead, which is a smaller package variant of our canvas runtime.
+ Not using [Rive Text](/editor/text/), [Rive Layouts](/editor/layouts/), [Rive Scripting](/scripting/), or [Rive Audio](/editor/events/audio-events)? Consider using [@rive-app/canvas-lite](/runtimes/web/canvas-vs-webgl#rive-app-canvas-lite) instead, which is a smaller package variant of our canvas runtime.
@@ -161,7 +159,7 @@ Bringing it all together, here's how to load a Rive graphic in a single HTML fil
canvas: document.getElementById("canvas"),
autoplay: true,
autoBind: true,
- // artboard: "Arboard", // Optional. If not supplied the default is selected
+ // artboard: "Artboard", // Optional. If not supplied the default is selected
stateMachines: "bumpy",
onLoad: () => {
// Ensure the drawing surface matches the canvas size and device pixel ratio
@@ -195,10 +193,10 @@ Under the hood, Rive creates various low-level objects (such as artboard instanc
Fortunately, the high-level JavaScript API simplifies this process. You don't need to track every object created during the Rive instance lifecycle. Instead, you can clean up all associated objects with a single method call.
-To clean up a Rive instance and free up resources, simply call the following method on your Rive instance:
+To clean up a Rive instance and free up resources, call the following method on your Rive instance:
```javascript
-const riveInstance = new Rive({...));
+const riveInstance = new Rive({...});
...
// When ready to cleanup
riveInstance.cleanup();