Vanilla Web (default)
The default safe path for any Lupian-delivered .riv. Works in plain HTML, WordPress, Webflow-style builders, Shopify, custom stacks, and inside any other framework that lets you drop a <script> block.
Use this when
- You have a
.rivfile from Lupian and a page that accepts a<script>or "Custom HTML" embed. - You do not need framework-specific reactivity around the animation (e.g. React state controlling inputs).
- You are not sure which recipe to pick — start here.
What you need
- The
.rivfile hosted at a known URL (see Hosting assets & CORS). - The state machine name from
handoff.md. - A spot on the page where you can put HTML + a
<script>.
Paste this
Drop this into your page. Replace YOUR_FILE_URL and "State Machine 1" with the values from handoff.md.
html
<div style="position:relative; width:100%; aspect-ratio:16/9;">
<canvas
id="rive-canvas"
style="width:100%; height:100%; display:block; touch-action:none;"
></canvas>
</div>
<script type="module">
import { Rive, Layout, Fit, Alignment }
from "https://esm.sh/@rive-app/webgl2";
const canvas = document.getElementById("rive-canvas");
const r = new Rive({
src: "YOUR_FILE_URL", // e.g. "/animations/hero.riv"
canvas,
autoplay: true,
stateMachines: "State Machine 1", // from handoff.md
layout: new Layout({
fit: Fit.Contain,
alignment: Alignment.Center,
}),
onLoad: () => r.resizeDrawingSurfaceToCanvas(),
onLoadError: (err) => console.error("Rive load error:", err),
});
window.addEventListener("resize", () => r.resizeDrawingSurfaceToCanvas());
</script>That is the entire integration.
npm version (Vite, Webpack, etc.)
If you have a bundler, install the package and import locally:
bash
npm install @rive-app/webgl2js
import { Rive, Layout, Fit, Alignment } from "@rive-app/webgl2";
// then the same `new Rive({...})` call as aboveWhich package?
| Package | When to use |
|---|---|
@rive-app/webgl2 | Default. Full feature support — mesh, blend modes, vector feathering. |
@rive-app/canvas | Smaller (Canvas2D). Use only if WebGL2 is unavailable on your target devices. |
@rive-app/canvas-lite | Smallest. No text / audio / scripting. Only if handoff.md confirms none are used. |
@rive-app/webgl2-single | Same as webgl2, with WASM inlined in the JS. Useful in Framer or other CDN-cached environments. See Framer. |
If unsure, use @rive-app/webgl2.
Wiring inputs and events
See State machine inputs & events for the full pattern. Short version:
js
r.on("load", () => {
const inputs = r.stateMachineInputs("State Machine 1");
const isHover = inputs.find(i => i.name === "isHovering");
canvas.addEventListener("mouseenter", () => isHover.value = true);
canvas.addEventListener("mouseleave", () => isHover.value = false);
});Common mistakes
- Setting
canvas.width/canvas.heightdirectly. Do not. It breaks the renderer. Let CSS size the container and callresizeDrawingSurfaceToCanvas()on load and on resize. - Forgetting
resizeDrawingSurfaceToCanvas()on resize. The animation will look blurry or pixelated. See Wrong size or blurry. - Wrong state machine name. Names are case-sensitive.
"state machine 1"≠"State Machine 1". The animation will load silently but not respond. - No
cleanup()on SPA route changes. Callr.cleanup()when the canvas leaves the DOM to free WASM memory. - Hot-linking from
esm.shin production without a fallback. For production, prefer npm + bundler or a self-hosted/CDN URL pinned to a version. - CORS errors when the
.rivis on a different origin. See Hosting assets & CORS.
If stuck, send this to Lupian
- A link to the page (or a screen recording).
- The exact filename you are loading and the URL it lives at.
- The state machine name as you wrote it in code.
- Any console errors (open DevTools, screenshot the console).
- See Ask Lupian for help for the full intake list.
Related
- State machine inputs & events
- Hosting assets & CORS
- Troubleshooting
- Deep API reference: rive.app/docs

