Your robot rebuilt in moveable layers and running in the real Rive runtime. Every button below drives the same inputs your app will use.
statetalk lipsyncWith lip-sync on, the mouth follows talk (0–100), so you can feed it your speech volume. With it off, Forseo uses his built-in talking loop.
follow lookX lookYYour own home screen with the static image swapped for the live rig, and the speech bubble set to "Forseo". The small bubble version is what Forseo turns into on other pages.
The bubble starts hidden. Fire popIn when it appears and popOut when it's dismissed.
The bubble artboard at 64, 72 and 80 px, drawn 1:1 on your app background.
Two artboards in one file. Every state is switchable from code with simple inputs, and transitions blend smoothly from any state to any other.
| Input | Type | What it does |
|---|---|---|
state | Number | 0 idle · 1 listening · 2 thinking · 3 talking · 4 working · 5 sleeping (yawns going in, stretches coming out) |
happy | Trigger | Jump with sparkles, then back to the current state |
confused | Trigger | Head tilt and a question mark, then back |
wave | Trigger | Hello wave. Fire it on mount as the intro |
wake | Trigger | Wakes Forseo from sleep, even if state is still 5 |
talk | Number 0–100 | Mouth openness while talking, when lipsync is on |
lipsync | Boolean | On: mouth follows talk. Off: built-in talking loop |
follow | Boolean | Eyes and head follow lookX / lookY |
lookX lookY | Number −100–100 | Where to look, relative to Forseo's face |
| Input | Type | What it does |
|---|---|---|
state | Number | 0 idle · 1 listening · 2 thinking · 3 talking · 5 sleeping (4 shows as thinking) |
popIn popOut | Trigger | Appear and dismiss. The bubble starts hidden |
talk lipsync | Number / Boolean | Same as the main artboard |
import { Rive } from '@rive-app/canvas'; const forseo = new Rive({ src: 'forseo.riv', canvas: document.querySelector('#forseo'), artboard: 'Forseo', stateMachines: 'Forseo', autoplay: true, onLoad: () => forseo.resizeDrawingSurfaceToCanvas(), }); const input = (name) => forseo.stateMachineInputs('Forseo').find((i) => i.name === name); input('state').value = 2; // thinking input('happy').fire(); // one-shot reaction input('lipsync').value = true; input('talk').value = volume * 100; // each frame while speaking input('follow').value = true; input('lookX').value = 40; // -100 left … 100 right