Guide

Rive Animation for Ecommerce: The 2026 Implementation Guide

Rive is the animation engine behind modern website mascots. A practical look at Rive vs Lottie, file size, state machines, framework setup, and keeping Core Web Vitals green.

BBaidyanathMay 24, 202612 min readUpdated May 31, 2026
Yokaify

Modern website mascots, like the kind covered in the AI mascot strategy reference, almost all run on Rive. This is the hands-on companion to that: how Rive compares to Lottie, how the pieces fit together, how to keep the files small, how to wire it into your framework, and how to make sure the mascot never becomes the reason a page feels slow.

One Rive character, several states: the same file handles idle, attentive, and speaking.

What Rive is, and isn't

Rive is two things bundled. The first is a vector animation authoring tool — a desktop and web editor where designers build characters with bones, blend states, and procedural animation. The second is a runtime that loads the binary .riv file and drives the animation in a browser, native mobile app, or game engine.

The runtime is the part most engineers care about. Rive's web runtime is roughly 30-50 KB compressed (the WASM core plus a small JS wrapper), and it loads .riv files which are themselves typically 5-50 KB for a single-character mascot. Total page weight for a working mascot: 50-100 KB.

What Rive is not: a video player, a 3D engine, or a generic animation library. It is purpose-built for interactive vector animation with state-machine logic. If your animation is a 30-second logo loop with no interactivity, Lottie or a single CSS keyframe is simpler. If your animation needs to respond to events, change states, or react to inputs from JavaScript, Rive is the right runtime.

Rive vs Lottie: the honest comparison

FeatureRiveLottie
Typical mascot file size5-50 KB20-200 KB
Built-in state machine editorYesNo
GPU-composited renderingYesPartial
Frame-cost on mid-tier mobile< 1ms3-7ms
Native mobile runtimesYesYes
Designer tool maturityHigh (Rive Editor)High (After Effects + Bodymovin)
React integration@rive-app/react-canvaslottie-react / @lottiefiles/react-lottie
Vue / Svelte / Solid integrationYesYes
Server-side renderingPartialPartial
Vector quality at scaleYesYes
After Effects importNoYes
Free runtimeYesYes
Editor pricingFree / $14-79/mo teamFree (After Effects subscription)
LicenseMIT (runtime)MIT (runtime)
WASM-based runtimeYesNo
Native interaction eventsYesNo
prefers-reduced-motion handlingManualManual
2026 mascot ecosystem mindshareDominantLegacy

Pricing and feature data last verified:

The honest verdict: Rive wins on bundle size, performance, and state-machine-driven interactivity. Lottie wins on After Effects import (designers with existing AE workflows) and on the legacy ecosystem of pre-built animations. For new mascot work in 2026, Rive is the default; for "I have a 5-year-old Lottie animation I need to keep working," Lottie is fine.

There is a fuller comparison in the Rive vs Lottie for chat widgets piece.

The Rive web architecture

A running Rive animation in a browser has four pieces.

  1. The .riv file. A binary asset built in Rive Editor. Contains the artboard, the bones, the timelines, the state machine, and any embedded raster assets. Loaded over HTTP like any other static asset; cache aggressively.

  2. The WASM runtime (rive.wasm). The actual animation engine, compiled to WebAssembly. Loaded once per page; subsequent mascots share the runtime.

  3. The JS wrapper. Either @rive-app/canvas (vanilla JS), @rive-app/react-canvas (React), or the equivalent for your framework. Handles the canvas creation, the state-machine inputs, the play / pause / dispose lifecycle.

  4. A <canvas> element in the DOM. The render target. Width and height should be explicit (no CSS-based sizing; reserve the layout slot).

The four pieces work together: the JS wrapper creates the canvas, fetches the .riv file, hands it to the WASM runtime, the runtime drives the render loop, the canvas paints. Behavior events from the host page (scroll, dwell, click) flip state-machine inputs; the runtime resolves the new state and continues rendering.

React integration

'use client';

import { useRive, useStateMachineInput } from '@rive-app/react-canvas';

export function Mascot {
  const { rive, RiveComponent } = useRive({
    src: '/mascot.riv',
    stateMachines: 'MascotStateMachine',
    autoplay: true,
  });

// Optional: drive a state-machine input from React state
  const speakingInput = useStateMachineInput(rive, 'MascotStateMachine', 'isSpeaking');

return (
    <div style={{ width: 96, height: 96 }}>
      <RiveComponent />
    </div>
  );
}

Three rules.

Rule 1: explicit width and height on the wrapper. The <canvas> Rive renders into respects its parent's bounds; if the parent is auto-sized, the canvas resizes mid-load and breaks CLS. Set width and height either inline or via CSS that resolves before first paint.

Rule 2: 'use client' for the component. Rive owns canvas state; it cannot be a server component in Next.js App Router. The pattern is a server component for the page shell, a client component for the mascot.

Rule 3: dispose on unmount. useRive handles disposal automatically in React; manual cleanup is only needed for non-React or class-based integrations. If you forget to dispose in a non-React stack, the WASM heap leaks.

Next.js integration

Next.js App Router with Rive is straightforward but has two gotchas.

Gotcha 1: dynamic import to keep the mascot off the LCP path. The Rive runtime is 30-50 KB and adds to your initial JS bundle if statically imported. The fix:

// app/components/MascotLoader.tsx
'use client';
import dynamic from 'next/dynamic';

const Mascot = dynamic( => import('./Mascot').then((m) => m.Mascot), {
  ssr: false,
  loading:  => <div style={{ width: 96, height: 96 }} aria-hidden />,
});

export { Mascot };

This pushes the Rive runtime to a separate chunk, loaded after the LCP event.

Gotcha 2: the .riv file in public/. Place the file in public/mascot.riv and reference it with an absolute path (/mascot.riv). Importing the binary as a module works in some configurations but breaks Turbopack and some webpack setups; public/ is the portable path.

The deeper Next.js pattern, including SSR / streaming-rendering compatibility, is in the Rive in Next.js — use client patterns article.

Other framework integrations

Vue. @rive-app/canvas works directly with Vue 3 — wrap the canvas creation in onMounted / onUnmounted lifecycle hooks. The community vue-rive wrapper is also available but adds a dependency.

Svelte. Same pattern as Vue — @rive-app/canvas in onMount / onDestroy. Svelte's bundle output is small enough that the framework overhead is minimal.

Solid. @rive-app/canvas directly. Solid's reactivity model maps cleanly to state-machine inputs.

Vanilla JS / Shopify Liquid / WordPress. @rive-app/canvas via a <script> tag. The pattern for Shopify (which has no native module bundler in the theme runtime) is in the Rive in Shopify article.

What a Rive state machine does

The state machine is what makes Rive useful for mascots. Without it, you have a sequence of timelines that play in order — a video, basically. With it, you have a graph of states the runtime moves between based on what the visitor is doing.

Inputs from the page flip the mascot between states; the runtime animates the blend in between.

A typical mascot state machine has 4-7 states:

  • Idle (default — gentle breathing, occasional blink)
  • Attentive (the mascot has noticed the visitor — turn head, eye contact)
  • Speaking (the agent is delivering a message — mouth animation, gesturing)
  • Celebrating (visitor converted — fireworks, jump)
  • Dismissed (visitor closed the chat — wave goodbye, fade)
  • Sleeping (long idle — eyes closed, gentle bob)

Inputs to the state machine — boolean flags or numeric values JavaScript can flip — drive transitions. A trigger from the agent ("the visitor just scrolled past 50%") flips an isAttentive boolean; the runtime resolves the new state and animates between idle and attentive over a 200ms blend period.

The state-machine editor is in Rive's authoring tool. The handoff to engineering is a .riv file plus a documented list of input names and their semantic meanings. The deep dive is in the Rive state machines article.

File size discipline

The 50 KB budget for a Rive mascot is achievable but requires discipline.

Use vector primitives, not embedded raster. A character drawn in Rive's vector tools is 5-15 KB. The same character with a raster face import is 80-200 KB. Most file-size problems trace back to a single embedded high-res image.

Limit the number of bones. A mascot with 25 bones renders fast but compiles to a larger .riv file than the same character with 12 bones. Each bone costs roughly 0.5-1 KB.

Compress the .riv over HTTP. Rive files compress well with gzip / brotli; ensure your CDN serves them with the right encoding header.

Defer non-critical states. If your mascot has 12 states but only 5 fire on the typical visit, consider splitting into two .riv files and lazy-loading the rare states.

The full optimization checklist is in the Rive file size optimization article.

How to keep a mascot from hurting Core Web Vitals

A mascot is a common reason a site slips on Core Web Vitals. Five rules keep it clean.

The mascot loads after the page is ready, in a slot that was reserved before it arrived.
  1. Reserve the layout slot before the canvas loads. Explicit width and height on the wrapper. Skip this and CLS goes from 0 to 0.04 the moment the canvas mounts.

  2. Defer mascot initialization to after LCP. Use requestIdleCallback or a setTimeout(..., 200) after the LCP event. The mascot does not contend with the hero image for paint.

  3. Don't block hydration on the mascot. The mascot is a client component; the rest of the page should hydrate first. The dynamic pattern above handles this in Next.js.

  4. Pause when off-screen. Use IntersectionObserver to pause the mascot's animation when it's outside the viewport. Wasted GPU cycles cost INP on mid-tier mobile devices.

  5. Honor prefers-reduced-motion. Start in a static frame if the OS setting requests reduced motion.

Implemented correctly, the mascot adds 0 ms to LCP, 0-4 ms to INP, and 0 to CLS. Implemented carelessly, it adds 80-200 ms to LCP, 30-50 ms to INP, and 0.02-0.06 to CLS — enough to fail a Core Web Vitals check.

Further reading

Frequently asked questions

An animation runtime and authoring tool optimized for interactive vector animation. Uses a binary .riv format with a built-in state-machine system. Web runtime is roughly 30-50 KB compressed.

Last updated May 31, 2026.