Bringing new tools into a workflow is always exciting—curiosity bumps up against the comfort of familiar methods. But when our longtime client, Chumbi Valley, came to us with their Valley Adventures project, we saw the perfect opportunity to experiment with Rive and craft cartoon-style animations that matched the playful spirit of the brand.
Rive is a powerful real-time interactive design tool with built-in support for interactivity through State Machines. In this guide, we’ll walk you through how we integrated a .riv file into a React environment and added mouse-responsive animations.
We’ll also walk through a modernized integration method using Rive’s newer Data Binding feature—our current preferred approach for achieving the same animation with less complexity and greater flexibility.
Animation Concept & File Preparation
Valley Adventures is a gamified Chumbi NFT staking program, where magical creatures called Chumbi inhabit an enchanted world. The visual direction leans heavily into fairytale book illustrations—vibrant colors, playful characters, and a whimsical, cartoon-like aesthetic.
To immediately immerse users in this world, we went with a full-section hero animation on the landing page. We split the animation into two parts:
an idle animation that brings the scene to life;
a cursor-triggered parallax effect, adding depth and interactivity.
Several elements animate simultaneously—background layers like rustling leaves and flickering fireflies, along with foreground characters that react to movement. The result is a dynamic, storybook-like experience that invites users to explore.
The most interesting—and trickiest—part of the integration was tying animations to mouse tracking. Rive provides a built-in way to handle this: by applying constraints with varying strengths to elements within a group that’s linked to Mouse Tracking, which itself responds to the cursor’s position.
However, we encountered a limitation with this approach: the HTML buttons layered above the Rive asset were blocking the hover state, preventing it from triggering the animation beneath.
To work around this, we used a more robust method that gave us finer control and avoided those problems altogether.
Here’s how we approached it:
Create four separate timelines, each with a single keyframe representing an extreme position of the animation group:
Far left
Far right
Top
Bottom
Add two animation layers, each responsible for blending between opposite keyframes:
Layer 1 blends the far-left and far-right timelines
Layer 2 blends the top and bottom timelines
Tie each layer’s blend amount to a numeric input—one for the X axis, one for the Y axis.
By adjusting the values of these inputs based on the cursor’s position, you can control how tightly the animation responds on each axis. This approach gives you a smoother, more customizable parallax effect—and prevents unexpected behavior caused by overlapping UI.
Once the animation is ready, simply export it as a .riv file—and leave the rest of the magic to the devs.
How We Did It: Integrating a Rive File into a React Project
Before we dive further, let’s clarify what a .riv file actually is.
A .riv file is the export format from the Rive editor. It can include:
vector graphics,
timeline animations,
a State Machine with input parameters.
In our case, we’re using a State Machine with two numeric inputs: Axis_X and Axis_Y. These inputs are tied to how we control animation in Rive, using values from the X and Y axes of the cursor’s position.
These inputs drive the movement of different elements—like the swaying leaves, fluttering fireflies, and even subtle character reactions—creating a smooth, interactive experience that responds to the user’s mouse.
Step-by-Step Integration
Step 1: Install the Rive React runtime
Install the official package:
npm install @rive-app/react-canvas
Step 2: Create an Animation Component
Create a component called RiveBackground.tsx to handle loading and rendering the animation.
This setup connects directly to the input values defined inside the State Machine, allowing us to update them dynamically in response to user interaction.
State Machine 1 — the name of your State Machine, exactly as defined in the Rive editor
Axis_X and Axis_Y — numeric inputs that control movement based on cursor position
0 — the initial (default) value for each input
☝️ Important: Make sure your .riv file includes the exact names: Axis_X, Axis_Y, and State Machine 1. These must match what’s defined in the Rive editor — otherwise, the animation won’t respond as expected.
Now you can use the RiveBackground like any other component:
<RiveBackground className="hero-background" />
Step 8: Preload the WASM File
To avoid loading the .wasm file at runtime—which can delay the initial render—you can preload it in App.tsx:
import riveWASMResource from '@rive-app/canvas/rive.wasm';
<link
rel="preload"
href={riveWASMResource}
as="fetch"
crossOrigin="anonymous"
/>
This is especially useful if you’re optimizing for first paint or overall performance.
Simple Parallax: A New Approach with Data Binding
In the first part of this article, we used a classic approach with a State Machine to create the parallax animation in Rive. We built four separate animations (top, bottom, left, right), controlled them using input variables, and blended their states to create smooth motion. This method made sense at the time, especially before Data Binding support was introduced.
But now that Data Binding is available in Rive, achieving the same effect is much simpler—just a few steps. Data binding in Rive is a system that connects editor elements to dynamic data and code via view models, enabling reactive, runtime-driven updates and interactions between design and development.
In this section, we’ll show how to refactor the original Rive file and code using the new approach.
Updating the Rive File
Remove the old setup:
Go to the State Machine.
Delete the input variables: top, bottom, left, right.
Remove the blending states and their associated animations.
Group the parallax layers:
Wrap all the parallax layers into a new group—e.g., ParallaxGroup.
Create binding parameters:
Select ParallaxGroup and add:
pointerX (Number)
pointerY (Number)
Bind coordinates:
In the properties panel, set:
X → pointerX
Y → pointerY
Now the group will move dynamically based on values passed from JavaScript.
The Updated JS Code
Before we dive into the updated JavaScript, let’s quickly define an important concept:
When using Data Binding in Rive, viewModelInstance refers to the runtime object that links your Rive file’s bindable properties (like pointerX or pointerY) to your app’s logic. In the Rive editor, you assign these properties to elements like positions, scales, or rotations. At runtime, your code accesses and updates them through the viewModelInstance—allowing for real-time, declarative control without needing a State Machine.
With that in mind, here’s how the new setup replaces the old input-driven logic:
Data Binding is a major step forward for interactive Rive animations. Effects like parallax can now be set up faster, more reliably, and with cleaner logic. We strongly recommend this approach for new projects.
Final Thoughts
So why did we choose Rive over Lottie for this project?
Interactivity: With Lottie, achieving the same level of interactivity would’ve required building a custom logic layer from scratch. With Rive, we got that behavior baked into the file—plug and play.
Optimization: Rive gives you more control over each asset inside the .riv file, and the output tends to be lighter overall.
Our biggest takeaway? Don’t be afraid to experiment with new tools—especially when they feel like the right fit for your project’s concept. Rive matched the playful, interactive vibe of Valley Adventures perfectly, and we’re excited to keep exploring what it can do.
If you’re used to ASP.NET apps when you think about apps that are JavaScript heavy, “front end apps” or TypeScript focused, it can be confusing as to “where does .NET fit in?”
You need to consider the responsibilities of your various projects or subsystems and the multiple totally valid ways you can build a web site or web app. Let’s consider just a few:
This may have a Web API, Razor Pages, with or without the MVC pattern.
You maybe have just added JavaScript via <script> tags
Maybe you added a script minimizer/minifier task
Can be confusing because it can feel like your app needs to ‘build both the client and the server’ from one project
A mostly JavaScript/TypeScript frontend app where the HTML could be served from any web server (node, kestrel, static web apps, nginx, etc)
This app may use Vue or React or Angular but it’s not an “ASP.NET app”
It calls backend Web APIs that may be served by ASP.NET, Azure Functions, 3rd party REST APIs, or all of the above
This scenario has sometimes been confusing for ASP.NET developers who may get confused about responsibility. Who builds what, where do things end up, how do I build and deploy this?
VS2022 brings JavaScript and TypeScript support into VS with a full JavaScript Language Service based on TS. It provides a TypeScript NuGet Package so you can build your whole app with MSBuild and VS will do the right thing.
NEW: Starting in Visual Studio 2022, there is a new JavaScript/TypeScript project type (.esproj) that allows you to create standalone Angular, React, and Vue projects in Visual Studio.
The .esproj concept is great for folks familiar with Visual Studio as we know that a Solution contains one or more Projects. Visual Studio manages files for a single application in a Project. The project includes source code, resources, and configuration files. In this case we can have a .csproj for a backend Web API and an .esproj that uses a client side template like Angular, React, or Vue.
Thing is, historically when Visual Studio supported Angular, React, or Vue, it’s templates were out of date and not updated enough. VS2022 uses the native CLIs for these front ends, solving that problem with Angular CLI, Create React App, and Vue CLI.
If I am in VS and go “File New Project” there are Standalone templates that solve Example 2 above. I’ll pick JavaScript React.
Then I’ll click “Add integration for Empty ASP.NET Web API. This will give me a frontend with javascript ready to call a ASP.NET Web API backend. I’ll follow along here.
It then uses the React CLI to make the front end, which again, is cool as it’s whatever version I want it to be.
Then I’ll add my ASP.NET Web API backend to the same solution, so now I have an esproj and a csproj like this
Now I have a nice clean two project system – in this case more JavaScript focused than .NET focused. This one uses npm to startup the project using their web development server and proxyMiddleware to proxy localhost:3000 calls over to the ASP.NET Web API project.
Here is a React app served by npm calling over to the Weather service served from Kestrel on ASP.NET.
This is inverted than most ASP.NET Folks are used to, and that’s OK. This shows me that Visual Studio 2022 can support either development style, use the CLI that is installed for whatever Frontend Framework, and allow me to choose what web server and web browser (via Launch.json) I want.
Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.