<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Oussama Afassi</title>
    <description>The latest articles on Forem by Oussama Afassi (@oussama_afassi_5dfb8eacb9).</description>
    <link>https://forem.com/oussama_afassi_5dfb8eacb9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3910393%2Fe7d1bdb6-763f-4d89-9f12-12aae3b9c27d.jpg</url>
      <title>Forem: Oussama Afassi</title>
      <link>https://forem.com/oussama_afassi_5dfb8eacb9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/oussama_afassi_5dfb8eacb9"/>
    <language>en</language>
    <item>
      <title>I built a website for developers to preview .riv files and debug Rive ViewModels</title>
      <dc:creator>Oussama Afassi</dc:creator>
      <pubDate>Tue, 05 May 2026 12:00:00 +0000</pubDate>
      <link>https://forem.com/oussama_afassi_5dfb8eacb9/i-built-a-website-for-developers-to-preview-riv-files-and-debug-rive-viewmodels-33l4</link>
      <guid>https://forem.com/oussama_afassi_5dfb8eacb9/i-built-a-website-for-developers-to-preview-riv-files-and-debug-rive-viewmodels-33l4</guid>
      <description>&lt;p&gt;If you've ever shipped a &lt;strong&gt;Rive&lt;/strong&gt; animation in a real app, you know the moment.&lt;/p&gt;

&lt;p&gt;You wire up the &lt;code&gt;.riv&lt;/code&gt;, hook up the &lt;strong&gt;ViewModel&lt;/strong&gt;, push inputs into the &lt;strong&gt;state machine&lt;/strong&gt;, and… something's off. A trigger isn't firing. A boolean is stuck. The state machine is taking the wrong transition. The animation looks like it's playing but the values you read back don't match what you set.&lt;/p&gt;

&lt;p&gt;So you do what I did for way too long. You start spamming &lt;code&gt;console.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Rebuild. Reload. Trigger the interaction. Watch the logs scroll past at 60fps. Squint. Add another log. Rebuild. Reload.&lt;/p&gt;

&lt;p&gt;I did this for about a month. Then I decided to build a tool for it.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://rive.best" rel="noopener noreferrer"&gt;&lt;strong&gt;rive.best&lt;/strong&gt;&lt;/a&gt; — drop a &lt;code&gt;.riv&lt;/code&gt;, see everything inside, change values live.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjm84n763fgyzz4vtsgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjm84n763fgyzz4vtsgc.png" alt="rive.best — Rive debugger UI" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why debugging Rive is painful
&lt;/h2&gt;

&lt;p&gt;The Rive runtime is genuinely great, but the developer experience for &lt;em&gt;inspecting&lt;/em&gt; a &lt;code&gt;.riv&lt;/code&gt; from the outside is rough.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ViewModel Instance properties are opaque.&lt;/strong&gt; You only see what you've explicitly logged. There's no "show me everything" panel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State machines are a black box at runtime.&lt;/strong&gt; You can read inputs, but the active state isn't easy to surface without writing your own state-change listener.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linear animations are worse.&lt;/strong&gt; A single artboard can carry a dozen animations and the only way to know which is doing what is by name and trial-and-error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Rive editor is for designing, not poking at runtime values mid-integration.&lt;/strong&gt; Once you export the &lt;code&gt;.riv&lt;/code&gt;, you're on your own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can spin up a throwaway sandbox project every time, but that's twenty minutes of plumbing per file and you end up half-rebuilding the same junk inspector again and again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What rive.best does
&lt;/h2&gt;

&lt;p&gt;Drag any &lt;code&gt;.riv&lt;/code&gt; onto the page. It instantly shows you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every &lt;strong&gt;artboard&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Every &lt;strong&gt;state machine&lt;/strong&gt; on each artboard.&lt;/li&gt;
&lt;li&gt;Every &lt;strong&gt;ViewModel Instance property&lt;/strong&gt; — booleans, numbers, strings, colors, enums, triggers, nested ViewModels, and lists.&lt;/li&gt;
&lt;li&gt;Every linear &lt;strong&gt;animation&lt;/strong&gt; (in case the file doesn't use a state machine at all).&lt;/li&gt;
&lt;li&gt;A live, tailing &lt;strong&gt;event log&lt;/strong&gt; of state changes, plays, pauses, loops, and your custom Rive events.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The part that mattered most to me: &lt;strong&gt;you can change every value live&lt;/strong&gt;. Toggle a boolean, drag a number, fire a trigger, pick a color, and the canvas reacts in real time. No rebuild, no reload, no more &lt;code&gt;console.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pin the properties you care about to a sticky watch list so they stay on top while you flip through scenarios. Filter the event log with a regex when there's too much noise. Switch artboards and state machines from the sidebar without ever leaving the page.&lt;/p&gt;

&lt;p&gt;Files stay in your browser. Nothing is uploaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://rive.best" rel="noopener noreferrer"&gt;&lt;strong&gt;rive.best&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you work with Rive day-to-day, drop your weirdest &lt;code&gt;.riv&lt;/code&gt; files in and tell me what breaks.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rive</category>
      <category>frontend</category>
      <category>animation</category>
    </item>
  </channel>
</rss>
