Skip to content

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 .riv file 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 .riv file 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/webgl2
js
import { Rive, Layout, Fit, Alignment } from "@rive-app/webgl2";
// then the same `new Rive({...})` call as above

Which package?

PackageWhen to use
@rive-app/webgl2Default. Full feature support — mesh, blend modes, vector feathering.
@rive-app/canvasSmaller (Canvas2D). Use only if WebGL2 is unavailable on your target devices.
@rive-app/canvas-liteSmallest. No text / audio / scripting. Only if handoff.md confirms none are used.
@rive-app/webgl2-singleSame 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.height directly. Do not. It breaks the renderer. Let CSS size the container and call resizeDrawingSurfaceToCanvas() 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. Call r.cleanup() when the canvas leaves the DOM to free WASM memory.
  • Hot-linking from esm.sh in production without a fallback. For production, prefer npm + bundler or a self-hosted/CDN URL pinned to a version.
  • CORS errors when the .riv is 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.

Developer support for Lupian-delivered Rive animations