Skip to main content

Generic rive

The generic Rive animation system allows you to create complex, interactive onboarding experiences entirely through JSON configuration using JEXL expression.

Your Rive animation must have a View Model with:

  • Input properties (triggers, booleans, numbers, strings)
  • Output properties (strings, images for dynamic content)
  • State machine with named states

How to Check Your Rive File

  1. Open your .riv file in Rive Editor
  2. Go to the View Model panel
  3. Verify all property names match your JSON config exactly (case-sensitive)
  4. Note the State Machine name (usually state_machine_1)

View Model Properties :

Property Types

All properties used in your animation must be declared in viewModelProperties:

STRING

"resultTitle": {
"type": "STRING",
"value": "{{data.cards[randomIndex].title}}"
}

IMAGE

"profileImage": {
"type": "IMAGE",
"value": "{{data.cards[randomIndex].image}}"
}
  • Supports absolute URLs: <https://example.com/image.png>
  • Supports relative paths: /assets/image.png

BOOLEAN

"isVisible": {
"type": "BOOLEAN",
"value": "{{answers.showProfile == 'yes'}}"
}
  • String values "true" and "false" are parsed correctly

NUMBER

"score": {
"type": "NUMBER",
"value": "{{answers.totalPoints}}"
}

Initial Values vs State-Based Updates

Initial Values (set on load)

"viewModelProperties": {
"userName": {
"type": "STRING",
"value": "{{answers.name}}"
}
}

State-Based Updates (set when state changes)

"stateFields": [
{
"stateName": "result screen",
"viewModelProperties": [
{
"key": "resultTitle",
"value": "{{data.results[selectedIndex].title}}"
}
]
}
]

State Management

Defining States

List all states you want to handle:

"states": ["intro", "question_1", "question_2", "result screen"]

State-Based Property Updates

When a state is entered, update properties:

"stateFields": [
{
"stateName": "question_1",
"viewModelProperties": [
{
"key": "questionText",
"value": "{{data.questions[0].text}}"
},
{
"key": "questionImage",
"value": "{{data.questions[0].image}}"
}
]
}
]

Triggers

Triggers are fired when users interact with your Rive animation.

Basic Trigger

"triggers": {
"button clicked": {
"execute": "{{moveToNextStep()}}"
}
}

Multi-Statement Triggers

Separate statements with semicolons:

"triggers": {
"card selected": {
"execute": "{{createAndRandomizeNumberProperty('cardIndex', 3); setRiveViewModelNumber('cardNumber', 1); setRiveViewModelBoolean('showResult', true)}}"
}
}

Trigger Best Practices

  1. Name triggers exactly as they appear in Rive (case-sensitive)
  2. Keep logic simple - use memory properties for complex state
  3. Test each trigger individually before combining

Data & Dynamic Content

Data Structure

Store your content in the data field:

"data": {
"cards": [
{
"name": "The Moon",
"result": {
"title": "Moon Howler",
"image": "https://example.com/moon.png",
"description": "Your profile..."
},
"questions": [
{
"text": "Question 1?",
"image": "/assets/q1.png"
}
]
}
]
}

Accessing Data with Memory Properties

  1. Create a memory property (in a trigger):
"execute": "{{createAndRandomizeNumberProperty('selectedCard', 3)}}"
  1. Reference it in data paths:
"value": "{{data.cards[selectedCard].result.title}}"

Dynamic Array Joining

"resultBulletPoints": {
"type": "STRING",
"value": "{{joinWithNewLines(data.cards[selectedCard].bulletPoints)}}"
}
KeyNotes
typeinteractiveAnimation
rendererwebgl
autoBindtrue
autoplaytrue
statesan array of valid states names for state change events. for example in tarot case states:["past_main","result screen"]
stateFieldsNote : Each state in the animation has its own stateFields config with specific viewModelProperties . When the Rive animation transitions to a state, it applies the corresponding view model properties defined for that state.
    "stateFields": [
      {
        "stateName": "result screen",
        "viewModelProperties": [
          {
            "key": "resultTitle",
            "value": "{{data.results[selectedIndex].title}}"
          }
        ]
      }
    ]
viewModelPropirties"viewModelProperties": {
      "resultTitle": { "type": "STRING" },
      "profileImage": { "type": "IMAGE" }
    }, **Note :**All properties used in your animation must be declared in viewModelProperties
triggers
Triggers are fired when users interact with your Rive animation.
Basic Trigger "triggers": {
  "button clicked": {
    "execute": "{{moveToNextStep()}}"
  }
} Multi-Statement Triggers Separate statements with semicolons:
"triggers": {
  "card selected": {
    "execute": "{{createAndRandomizeNumberProperty('cardIndex', 3); setRiveViewModelNumber('cardNumber', 1); setRiveViewModelBoolean('showResult', true)}}"
  }
}
dataStore your content in the data field:
"data": {
 "cards": [
 {
"name": "The Moon",
"result": {
"fallbackLimit": 4,
"profileTitle": "Anxiety Profile",
"profileName": "Moon Howler",
"cardDrawn": "Card drawn: The Moon",
"paragraph": "Your anxiety has deep, hidden roots, like the wolf’s howl echoing in the night. It makes you prone to:",
"image": "https://c.thefab.co/web-onboarding/mind/profile_image.webp",
"fallbackBulletPoints": [
   "Escapism",
    "Masking",
    "Attachment Wounds",
    "Cognitive Distortions"
],
   "bottomText": "But that’s your past... Aren’t you curious about your future?"
},
  "questionsData": [
    {
     "text": "The Moon is a mysterious and emotional card.",
      "image": "https://c.thefab.co/web-onboarding/mind/moon-illustration.webp"
    },
    {
      "text": "Which of these feels most connected to your past?",
       "image": "https://c.thefab.co/web-onboarding/mind/moon-illustration.webp"
    },
    {
     "subject": "Escapism",
      "text": "Do you retreat into fantasy or distractions when life feels heavy?",
      "image": "https://c.thefab.co/web-onboarding/mind/moon-frame1.webp"
    },
    {
       "subject": "Masking",
                  "text": "Do you hide your true feelings behind a smile?",
                  "image": "https://c.thefab.co/web-onboarding/mind/moon-frame2.webp"
     },
     {
        "subject": "Cognitive Distortions",
        "text": "Do your thoughts often expect the worst or doubt yourself?",
        "image": "https://c.thefab.co/web-onboarding/mind/moon-frame3.webp"
      },
      {
        "subject": "Attachment Wounds",
        "text": "Do past relationship hurts still affect your trust?",
        "image": "https://c.thefab.co/web-onboarding/mind/moon-frame4.webp"
       }
]
},
// more cards Note : For the result it has fallbackLimit Logic: If user provides fewer than this number of resonating answers, show fallbackBulletPoints Example: 4 means if user resonates with fewer than 4 questions, show generic bullet points
Full json example
{
"id": "fab_tarot",
"appId": "co.thefabulous.app",
"language": "en",
"seo": {
"title": "Fabulous",
"favicon": "https://c.thefab.co/web-onboarding/elixir/elixir-favicon.png",
"description": "Unlock your true potential with Elixir: Your daily guide to a purpose-driven, authentic life. Find your focus, live with intention."
},
"steps": [
{
"type": "interactiveAnimation",
"stepId": "tarot_animation",
"backgroundColor": "#1A235E",
"textColor": "#FFFFFF",
"animation": {
"renderer": "webgl",
"url": "/assets/rive/tarot_onboarding_v40.1.14.riv",
"stateMachine": "state_machine_1",
"autoplay": true,
"autoBind": true,
"states": [
"past_main",
"result screen"
],
"stateFields": [
{
"stateName": "past_main",
"viewModelProperties": [
{
"key": "introTitle",
"value": "Discover who you are and what drives your Anxiety"
},
{
"key": "title2",
"value": "Think about your childhood, Stranger. Then Pick a card."
}
]
},
{
"stateName": "result screen",
"viewModelProperties": [
{
"key": "resultProfileTitle",
"value": "{{data.cards[randomCardIndex].result.profileTitle}}"
},
{
"key": "resultProfileName",
"value": "{{data.cards[randomCardIndex].result.profileName}}"
},
{
"key": "resultCardDrawn",
"value": "{{data.cards[randomCardIndex].result.cardDrawn}}"
},
{
"key": "resultParagraph",
"value": "{{data.cards[randomCardIndex].result.paragraph}}"
},
{
"key": "profileImage",
"value": "{{data.cards[randomCardIndex].result.image}}"
},
{
"key": "resultBulletPoints",
"value": "{{joinWithNewLines(data.cards[randomCardIndex].result.fallbackBulletPoints)}}"
},
{
"key": "resultBottomText",
"value": "{{data.cards[randomCardIndex].result.bottomText}}"
}
]
}
],
"viewModelProperties": {
"introTitle": {
"type": "STRING"
},
"title2": {
"type": "STRING"
},
"title3": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[0].text}}"
},
"title4": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[1].text}}"
},
"introImage": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[0].image}}"
},
"question1": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[2].text}}"
},
"questionImage1": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[2].image}}"
},
"question2": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[3].text}}"
},
"questionImage2": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[3].image}}"
},
"question3": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[4].text}}"
},
"questionImage3": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[4].image}}"
},
"question4": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[5].text}}"
},
"questionImage4": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[5].image}}"
},
"question5": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[2].text}}"
},
"questionImage5": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[2].image}}"
},
"question6": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[3].text}}"
},
"questionImage6": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[3].image}}"
},
"question7": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[4].text}}"
},
"questionImage7": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[4].image}}"
},
"question8": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[5].text}}"
},
"questionImage8": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[5].image}}"
},
"question9": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[2].text}}"
},
"questionImage9": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[2].image}}"
},
"question10": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].questionsData[3].text}}"
},
"questionImage10": {
"type": "IMAGE",
"value": "{{data.cards[randomCardIndex].questionsData[3].image}}"
},
"cardName": {
"type": "STRING",
"value": "{{data.cards[randomCardIndex].name}}"
},
"resultProfileTitle": {
"type": "STRING"
},
"resultProfileName": {
"type": "STRING"
},
"resultCardDrawn": {
"type": "STRING"
},
"resultParagraph": {
"type": "STRING"
},
"resultBulletPoints": {
"type": "STRING"
},
"resultBottomText": {
"type": "STRING"
},
"profileImage": {
"type": "IMAGE"
}
},
"triggers": {
"card selected": {
"execute": "{{createAndRandomizeNumberProperty('randomCardIndex', 3); setRiveViewModelNumber('questions number', 4); setRiveViewModelBoolean('future or past', true); createNumberProperty('currentQuestion', 0)}}"
},
"explain": {
"execute": "{{incrementProperty('currentQuestion');}}"
},
"i will": {
"execute": "{{incrementProperty('currentQuestion');}}"
},
"not sure": {
"execute": "{{incrementProperty('currentQuestion');}}"
},
"this resonate": {
"execute": "{{incrementProperty('currentQuestion');}}"
},
"draw future card": {
"execute": "{{moveToNextStep()}}"
}
},
"data": {
"cards": [
{
"name": "The Moon",
"result": {
"fallbackLimit": 4,
"profileTitle": "Anxiety Profile",
"profileName": "Moon Howler",
"cardDrawn": "Card drawn: The Moon",
"paragraph": "Your anxiety has deep, hidden roots, like the wolf’s howl echoing in the night. It makes you prone to:",
"image": "https://c.thefab.co/web-onboarding/mind/profile_image.webp",
"fallbackBulletPoints": [
"Escapism",
"Masking",
"Attachment Wounds",
"Cognitive Distortions"
],
"bottomText": "But that’s your past... Aren’t you curious about your future?"
},
"questionsData": [
{
"text": "The Moon is a mysterious and emotional card.",
"image": "https://c.thefab.co/web-onboarding/mind/moon-illustration.webp"
},
{
"text": "Which of these feels most connected to your past?",
"image": "https://c.thefab.co/web-onboarding/mind/moon-illustration.webp"
},
{
"subject": "Escapism",
"text": "Do you retreat into fantasy or distractions when life feels heavy?",
"image": "https://c.thefab.co/web-onboarding/mind/moon-frame1.webp"
},
{
"subject": "Masking",
"text": "Do you hide your true feelings behind a smile?",
"image": "https://c.thefab.co/web-onboarding/mind/moon-frame2.webp"
},
{
"subject": "Cognitive Distortions",
"text": "Do your thoughts often expect the worst or doubt yourself?",
"image": "https://c.thefab.co/web-onboarding/mind/moon-frame3.webp"
},
{
"subject": "Attachment Wounds",
"text": "Do past relationship hurts still affect your trust?",
"image": "https://c.thefab.co/web-onboarding/mind/moon-frame4.webp"
}
]
},
{
"name": "The Tower",
"result": {
"fallbackLimit": 4,
"profileTitle": "Anxiety Profile",
"profileName": "Tower Falcon",
"cardDrawn": "Card drawn: The Tower",
"paragraph": "Your anxiety is fueled by sudden disruptions, like a falcon trying to nest in a crumbling tower. It makes you prone to:",
"image": "https://c.thefab.co/web-onboarding/mind/falcon_profile.webp",
"fallbackBulletPoints": [
"Hypervigilance",
"Fear of Change",
"Emotional Flashbacks",
"Safety-Seeking Behavior"
],
"bottomText": "But that’s your past... Aren’t you curious about your future?"
},
"questionsData": [
{
"text": "The Tower shows upheaval and transformation.",
"image": "https://c.thefab.co/web-onboarding/mind/tower_illustration.webp"
},
{
"text": "Which of these resonates with your past?",
"image": "https://c.thefab.co/web-onboarding/mind/tower_illustration.webp"
},
{
"subject": "Hypervigilance",
"text": "Do you feel on edge, waiting for something to go wrong?",
"image": "https://c.thefab.co/web-onboarding/mind/tower_frame1.webp"
},
{
"subject": "Fear of Change",
"text": "Does even good change make you feel uneasy?",
"image": "https://c.thefab.co/web-onboarding/mind/tower_frame2.webp"
},
{
"subject": "Emotional Flashbacks",
"text": "Do past hurts come back as if they are happening now?",
"image": "https://c.thefab.co/web-onboarding/mind/tower_frame3.webp"
},
{
"subject": "Safety-Seeking Behavior",
"text": "Do you avoid risks because stability feels safer?",
"image": "https://c.thefab.co/web-onboarding/mind/tower_frame4.webp"
}
]
},
{
"name": "Justice",
"result": {
"fallbackLimit": 4,
"profileTitle": "Anxiety Profile",
"profileName": "Inner Judge",
"cardDrawn": "Card drawn: Justice",
"paragraph": "Your anxiety is shaped by self-criticism and inner judgment, like a strict judge weighing every action. It makes you prone to:",
"image": "https://c.thefab.co/web-onboarding/mind/balance_profile.webp",
"fallbackBulletPoints": [
"Self-Criticism",
"Perfectionism",
"Fear of Unfairness",
"Difficulty Letting Go"
],
"bottomText": "But that’s your past... Aren’t you curious about your future?"
},
"questionsData": [
{
"text": "Justice is a card of truth and accountability.",
"image": "https://c.thefab.co/web-onboarding/mind/justice_illustration.webp"
},
{
"text": "Which of these feels familiar from your past?",
"image": "https://c.thefab.co/web-onboarding/mind/justice_illustration.webp"
},
{
"subject": "Self-Criticism",
"text": "Do you judge yourself more harshly than others do?",
"image": "https://c.thefab.co/web-onboarding/mind/justice_frame1.webp"
},
{
"subject": "Perfectionism",
"text": "Do you feel you must get everything exactly right?",
"image": "https://c.thefab.co/web-onboarding/mind/justice_frame2.webp"
},
{
"subject": "Fear of Unfairness",
"text": "Does unfair treatment weigh heavily on your mind?",
"image": "https://c.thefab.co/web-onboarding/mind/justice_frame3.webp"
},
{
"subject": "Difficulty Letting Go",
"text": "Do you struggle to release grudges or past wrongs?",
"image": "https://c.thefab.co/web-onboarding/mind/justice_frame4.webp"
}
]
}
]
}
}
}
],
"logic": []
}