frontend-rive
Rive
Interactive animations with built-in state machines. Animation logic inside the .riv file.
When to Use
- Animations that REACT to input (hover, click, data)
- Animated buttons, toggles, checkboxes
- Progress indicators driven by values
- Multi-state characters/icons
- Complex state transitions
When NOT to Use
- Simple decorative loops → Lottie
- Static illustrations → SVG
- Quick spinners → CSS/Lottie
Key Concept: State Machines
┌─────────────────────────────────┐
│ Rive State Machine │
│ ┌──────┐ hover ┌───────┐ │
│ │ Idle │ ──────► │ Hover │ │
│ └──────┘ └───────┘ │
│ ▲ click │ │
│ └──────────── ◄──┘ │
│ │
│ Inputs: hover (bool), click │
└─────────────────────────────────┘
You control inputs → Rive handles animations
Process
SETUP → CONNECT → CONTROL
- Install:
npm install @rive-app/react-canvas - Load .riv file with state machine
- Get inputs via
useStateMachineInput - Connect to UI events
Quick Start
import { useRive, useStateMachineInput } from '@rive-app/react-canvas';
function InteractiveButton() {
const { rive, RiveComponent } = useRive({
src: '/button.riv',
stateMachines: 'ButtonState',
autoplay: true,
});
const hover = useStateMachineInput(rive, 'ButtonState', 'hover');
const press = useStateMachineInput(rive, 'ButtonState', 'pressed');
return (
<RiveComponent
onMouseEnter={() => hover && (hover.value = true)}
onMouseLeave={() => hover && (hover.value = false)}
onMouseDown={() => press && (press.value = true)}
onMouseUp={() => press && (press.value = false)}
/>
);
}
Input Types
Boolean: input.value = true/false # hover, isActive
Number: input.value = 75 # progress (0-100)
Trigger: input.fire() # onClick, onComplete
Common Patterns
Toggle:
- Boolean input "isOn"
- onClick: toggle value
Progress:
- Number input "progress" (0-100)
- useEffect: sync with prop
Notification Bell:
- Number input "count"
- Trigger input "ring"
- onClick: fire() trigger
Decision: Rive vs Lottie
| Need | Use |
|---|---|
| Just plays/loops | Lottie |
| Reacts to hover | Rive |
| Controlled by data | Rive |
| Multiple states | Rive |
| Simple loader | Lottie |
Layout & Sizing
// Container controls size
<div className="w-64 h-64">
<RiveComponent />
</div>
// Responsive with aspect ratio
<div className="w-full aspect-video max-w-2xl">
<RiveComponent />
</div>
SSR & Hydration
// Always 'use client'
'use client'
// Dynamic import for heavy animations
const Animation = dynamic(() => import('./RiveAnimation'), { ssr: false })
// Or mounted check
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) return <Skeleton />
Performance
// Lazy load
const Rive = dynamic(() => import('./RiveComponent'), { ssr: false })
// Pause when not visible
const { ref, inView } = useInView()
useEffect(() => { inView ? rive?.play() : rive?.pause() }, [inView])
Troubleshooting
"Animation not playing":
→ Check autoplay: true
→ Check stateMachines name (case-sensitive)
→ Check .riv path in public/
"Inputs undefined":
→ Always check: if (input) input.value = x
→ Verify input names match Rive editor
"Hydration mismatch":
→ Add 'use client'
→ Use dynamic(() => ..., { ssr: false })
"Wrong size":
→ Container needs explicit width/height
→ Use aspect-ratio utilities
References
- patterns.md — Toggle, Checkbox, Progress, Like button, Form integration
External Resources
- https://rive.app/docs/runtimes/react — React runtime docs
- https://rive.app/community — Free .riv files
- For latest API → use context7 skill
More from petbrains/mvp-builder
backend-vitest
Fast unit testing framework for TypeScript/JavaScript. Use for testing tRPC procedures, Zod schemas, utility functions, and any TypeScript code. Built on Vite with native ESM, TypeScript support, and Jest-compatible API. Choose Vitest over Jest for modern TypeScript projects, especially with Vite-based setups.
6figma-extractor
Extract design tokens, styles, component metadata, and screen structure from Figma files via MCP. Use whenever a figma.com URL appears, when someone mentions Figma tokens, variables, design system extraction, screen captures, text styles, shadows, component properties, or library assets. Trigger for phrases like 'get from Figma', 'extract design', 'Figma variables', 'design tokens', 'capture screens', 'get typography from Figma', 'extract shadows', 'find components in library', 'get code syntax for tokens', or any figma.com/design link. Even if the user just pastes a Figma link without instructions, use this skill to parse it and decide what to extract. Covers three extraction depths: Level 1 (quick read-only MCP), Level 2 (deep extraction via Plugin API scripts), Level 3 (library search + component property metadata).
2