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>
159 lines
9.5 KiB
Markdown
159 lines
9.5 KiB
Markdown
# 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-friendly** — `idle`, `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()`)
|