rebreak-monorepo/docs/RIVE_ANIMATOR_BRIEF.md
chahinebrini 5d6c322129 wip: KeyboardAwareSheet migrations + Snake/Tetris UI + iron.png + useMe live-update
Sheets via neuer KeyboardAwareSheet-Composable (in Modal pattern, auto-grow
mit Tastatur, paddingBottom-Lift): EditMail, AddDomain, CreateRoom, ConnectMail.
GameOverScreen behält Spring-Slide-In, nutzt RN Keyboard.addListener für Lift.

- KeyboardAwareSheet.tsx — universal modal with sheet-grow + keyboard-padding
- react-native-keyboard-controller installiert + KeyboardProvider in Root
- Snake: time + ScoreProgressBar + useSnakeSounds (haptic, audio TODO)
- Tetris: title weg, Buttons zentriert, kein Pressable mit style-fn
- DPad-Buttons 60→48, more bg, no scale
- useMe: pub-sub listener pattern für app-weite avatar/nickname-Updates
- dm.tsx: resolveAvatar wrap (iron.png-Warning)
- Mail-error-humanizer + locales

Recovery-Doc-Update in docs/internal/RECOVERY_LOG_2026-05-10.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 23:59:25 +02:00

9.5 KiB

Rive Animator Brief — Lyra Avatar Emotion States

Ready-to-publish — copy section between the dividers below into your job-post on Dribbble / Fiverr / Twitter / Rive Discord.


🎯 Project: Rebreak — Lyra Avatar Animation

I'm hiring a Rive-animator to extend Lyra, the AI-companion of Rebreak — a recovery app for people working through gambling addiction (German market, planned DiGA-listing in healthcare).

Critical context: This is a sensitive recovery-app, NOT a playful game. Lyra is a warm, present companion — never cute-mascot, never childish, never dramatic. Subtle > exaggerated.

Budget: $100 USD, ~1 week target. Self-qualify before applying.

What I have (current .riv)

  • File: lyra-avatar.riv (264 KB) — will be shared after engagement-confirmation
  • Artboard name: Artboard
  • State machine name: State Machine 1, default state idle
  • Existing animation timelines (extracted via strings):
    • Idle Loop — wired as idle
    • idle to Pose 1 + Pose 1 loop — wired as happy (2-phase: app manually switches via 900ms JS-timer)
    • 01 Wave 1 — wired as empathy
    • 01 Wave 2 — exists, NOT wired (orphan)
    • WALK — placeholder, currently aliased as thinking (please replace with proper thinking-pose animation)
    • Kedip (Indonesian "blink") — orphan from template
  • Runtime: rive-react-native ^9.0.1 (export against this compatible Rive editor version)
  • Avatar usage: appears at 40px (small list), 112px (chat-header), 160px (onboarding hero) — must read clearly even at 40px

⚠️ Critical naming contract — do NOT rename existing names

The React code calls timelines directly by name (not via state-machine inputs). If you rename a timeline, the app silently breaks (no animation plays, no error). This means:

  • Keep: Artboard artboard, State Machine 1 SM-name, idle default-state, Idle Loop timeline name
  • New emotion-states must use exactly these timeline names (snake_case): sad, joy, confusion, calm, surprise, listening, thinking (replacing WALK)
  • For multi-phase emotions (e.g. dramatic intro → loop): use <state> intro + <state> loop pattern, just like existing idle to Pose 1 + Pose 1 loop
  • Bonus (+$X if you propose): expose state-machine inputs (SetEmotion enum-trigger) so we can transition imperatively. Optional — named-timelines remain the primary contract.

Deliverables — emotion states

You'll add these to the existing state-machine. Total: 6 new states + 1 placeholder-replacement (thinking).

Tier 1 — must-have (4 states, baseline budget)

Internal name (timeline) Trigger in app Eyes Brow Mouth Body
thinking (REPLACE WALK) LLM is generating response look up-and-to-side, slow blink one slightly raised gently closed, slight pursed finger-near-temple pose if possible, head tilt ~5°
listening User mid-typing OR voice-recording open, attentive, natural blink neutral relaxed gently closed, micro-Mona-Lisa upturn subtle head nod every ~3s
calm Breathing exercise / meditation active half-closed neutral relaxed slight serene smile very slow up/down breathing loop (~4s cycle to match 4-7-8 breathing pace)
sad User describes loss/relapse/shame softened, slight downcast, lower lid raised inner-up, slight angle closed, neutral or micro-downturn tiny head tilt down (~5°), slow breathing

Tier 2 — nice-to-have (2-3 more states, push budget if you can)

Internal name (timeline) Trigger in app Visual direction
joy Streak milestone, big celebration bigger smile than happy (warmer not goofy), small head bounce on intro then settle
confusion Lyra needs clarification one brow raised, slight squint, head tilt ~10° to one side
surprise Unexpected user input wide-open eyes (brief), both brows raised, small "o" mouth, quick head pull-back micro on intro then settle

Skip these (anti-patterns for recovery use-case)

  • angry / frustrated — never from coach
  • shocked / horror — too dramatic for trauma-context
  • Cute-mascot expressions (winks, tongue-out, hearts in eyes)
  • Heavy bone-rigs / particles — runtime cost too high

Visual style guidelines

  • Match existing Lyra-look (extract palette + line-weight from the .riv you'll receive)
  • Subtle is better — these animations play during emotional moments, they should support not demand attention
  • Loop-friendlyidle, calm, listening should breathe naturally, no pop on loop boundary
  • Smooth transitions — prefer 200-400ms crossfades over hard cuts. Especially: empathy → idle → happy should never feel jarring (route through idle, never direct jump from negative to positive)
  • Readability at 40px — exaggerate eye/brow shapes slightly, avoid mouth-only emotion (mouth is too small at 40px to carry expression)

Technical Requirements

  • Output: ONE .riv file named exactly lyra-avatar.riv (replaces current file)
  • Single artboard, single state-machine — preserve existing structure
  • Rive editor version: 2024.x (compatible with rive-react-native ^9.0.1)
  • Performance: 60 fps target on mid-range Android (Pixel 5-class)
  • File-size: ≤500KB (current 264KB, want headroom for new states)
  • Loop-cycle precision: calm should be ~4 seconds (we sync app-side to user's 4-7-8 breathing exercise)

Bonus task (optional, +scope)

Existing happy uses a 2-phase manual switch via 900ms JS-timeout — clunky. If you can fix this so it loops cleanly inside the .riv itself (intro auto-blends into loop without app-side coordination), that's worth +$X.

Timeline + Budget

  • $100 USD flat, paid: 50% on first-draft approval, 50% on final delivery
  • 1 week from brief-confirmation
  • Milestones:
    1. Day 0: brief-confirm + you receive .riv file + answers to your questions
    2. Day 2-3: first draft of 1-2 states for visual-direction approval (style-confirm)
    3. Day 4-6: remaining states + 1 round of revisions
    4. Day 7: final delivery

Deliverables you provide

  1. lyra-avatar.riv — replaces existing file
  2. Short README (1 page max):
    • List of all timeline-names + when each plays
    • Any limitations or known issues
    • State-machine diagram (simple)
  3. Source-file (Rive editor .rev or equivalent) for future edits
  4. Optional bonus: short demo-video (15-30 sec) showing all states cycling — earns trust

Questions to ask BEFORE starting (please answer in your application)

  1. Can I use the current .riv as a base and add states, or do you want a clean rebuild?
  2. Confirm Rive runtime version (rive-react-native ^9.0.1) — compatible with your export?
  3. Should I also fix the existing happy 2-phase JS-timer (auto-blend in .riv instead)?
  4. For the German market: any culture-specific gestures to avoid?
  5. Any brand-colors / hex-codes I must match?
  6. Audio cues or visual-only?
  7. Do you have Figma / brand-guide I should reference?

What I value in your work

  • Restraint over flashiness
  • Clean state-machine architecture (other devs may extend later)
  • Honest communication if scope is too tight for budget — happy to scope down to 4 states (Tier 1 only)
  • Async-first (Slack-like / email / Discord-DM)

How to apply

Send me:

  1. Link to Rive portfolio (not Lottie, not After-Effects — actual .riv work)
  2. Confirmation you've read this brief (so I know it's not auto-applied)
  3. Your suggested approach: extend existing state-machine OR rebuild?
  4. Your answers to the 7 questions above

Looking forward to working together.


End of brief — copy everything above into your job-post.

How to use this brief (internal — not for animator)

  1. Vor dem Senden alle [Platzhalter]-Stellen (insbesondere Communication-Channel falls du das spezifizieren willst) ausfüllen
  2. Aktuelle .riv mitschicken — Animator braucht sie als Style-Referenz + State-Machine-Setup
  3. Klarstellen: Emotion-Namen in der Tabelle sind Code-Contracts und müssen exakt so im Rive-File heißen — sonst muss React-Code refactored werden
  4. Vor Vergabe 2-3 Animator-Portfolios checken — suche „warm/subtle character"-style, NICHT nur knallige Logo-Animationen
  5. Nach Erhalt der ersten Draft auf echtem Android-Mid-Range-Gerät testen (Pixel 5 oder älter), nicht nur iOS-Simulator
  6. Wo publishen (in Reihenfolge der Wahrscheinlichkeit):
    • Rive Discord (https://rive.app/community → Discord) — Rive-spezialisierte Animatoren, keine LottieFiles-Refugees
    • Twitter #RiveAnimation hashtag + DMs an Animator-Portfolios die du gut findest
    • Fiverr „Rive animator" custom-offers ($30-150 typische Gigs)
    • Dribbble „Hiring" section — gemischte Quality, mehr Style-fokus
  7. Wenn .riv ankommt: drag in apps/rebreak-native/assets/lyra-avatar.riv (overwrite), commit, fertig. Code ist schon flexibel (RiveAvatar accepts any state-name nach Task #39 component-flex).

Sources / Internal-Files

  • Brief-Audit: apps/rebreak-native/components/RiveAvatar.tsx (lines 42-51 — Emotion-API contract)
  • Existing .riv: apps/rebreak-native/assets/lyra-avatar.riv (264 KB)
  • Plugin: apps/rebreak-native/plugins/with-rive-asset-android.js (Android raw-resource auto-mirror)
  • Trigger-context: apps/rebreak-native/app/lyra.tsx (lines 37-44, 306-323), apps/rebreak-native/app/urge.tsx, apps/rebreak-native/lib/lyraResponse.ts:57-61 (existing detectEmotion())