Agent Skills: Rive Generator Skill

|

UncategorizedID: stevysmith/rive-skills/rive-generator

Install this agent skill to your local

pnpm dlx add-skill https://github.com/stevysmith/rive-skills/tree/HEAD/skills/rive-generator

Skill Files

Browse the full folder contents for rive-generator.

Download Skill

Loading file tree…

skills/rive-generator/SKILL.md

Skill Metadata

Name
rive-generator
Description
|

Rive Generator Skill

Generate Rive animations programmatically using TypeScript.

Installation

First, install the npm package:

npm install @stevysmith/rive-generator

Quick Start

import { writeFileSync } from 'fs';
import { RiveFile, hex } from '@stevysmith/rive-generator';

const riv = new RiveFile();

// Create artboard
const artboard = riv.addArtboard({
  name: 'My Animation',
  width: 400,
  height: 400,
});

// Add shape at center
const shape = riv.addShape(artboard, {
  name: 'MyShape',
  x: 200,
  y: 200,
});

// Add path (ellipse or rectangle)
riv.addEllipse(shape, { width: 100, height: 100 });

// Add fill with color
const fill = riv.addFill(shape);
riv.addSolidColor(fill, hex('#3498db'));

// Export
writeFileSync('my-animation.riv', riv.export());

Running

# With TypeScript (Node 22+)
node --experimental-strip-types generate.ts

# Or compile first
npx tsc generate.ts && node generate.js

API Reference

RiveFile

Main class for building .riv files.

| Method | Description | |--------|-------------| | addArtboard(options) | Add an artboard (canvas) | | addNode(parent, options) | Add a transform group | | addShape(parent, options) | Add a shape container | | addEllipse(shape, options) | Add an ellipse/circle | | addRectangle(shape, options) | Add a rectangle | | addPointsPath(shape, options) | Add a custom vector path | | addVertex(path, options) | Add a straight vertex | | addFill(shape, options) | Add a fill | | addStroke(shape, options) | Add a stroke | | addSolidColor(paint, color) | Set solid color | | addLinearGradient(paint, options) | Add linear gradient | | addRadialGradient(paint, options) | Add radial gradient | | addGradientStop(gradient, options) | Add gradient color stop | | addLinearAnimation(artboard, options) | Add an animation | | addKeyedObject(animation, targetId) | Link animation to object | | addKeyedProperty(keyedObject, propertyKey) | Specify property to animate | | addKeyFrameDouble(keyedProperty, options) | Add a keyframe | | export() | Returns Uint8Array of .riv binary |

Colors

import { hex, rgba } from '@stevysmith/rive-generator';

hex('#ff0000')           // Red
hex('#3498db')           // Nice blue
rgba(255, 0, 0, 255)     // Red with full opacity
rgba(0, 0, 0, 128)       // Semi-transparent black

PropertyKey

import { PropertyKey } from '@stevysmith/rive-generator';

PropertyKey.x          // X position
PropertyKey.y          // Y position
PropertyKey.scaleX     // X scale
PropertyKey.scaleY     // Y scale
PropertyKey.rotation   // Rotation (radians)

Important Constraints

  1. Use a single Node container - All shapes must be children of ONE Node under the Artboard.

  2. Gradient shapes must be LAST - Add shapes with gradients after solid color shapes.

  3. DO NOT use CubicVertex - Use addVertex() only. Approximate curves with many straight vertices.

  4. DO NOT use cornerRadius - Use plain rectangles or PointsPath for rounded corners.

  5. First shape position bug - Add a tiny transparent dummy shape first:

    const dummy = riv.addShape(container, { name: 'Dummy', x: 0, y: 0 });
    riv.addRectangle(dummy, { width: 1, height: 1 });
    const dummyFill = riv.addFill(dummy);
    riv.addSolidColor(dummyFill, hex('#00000000'));
    

Animation Example

import { RiveFile, hex, PropertyKey } from '@stevysmith/rive-generator';
import { writeFileSync } from 'fs';

const riv = new RiveFile();
const artboard = riv.addArtboard({ name: 'Pulse', width: 200, height: 200 });

const shape = riv.addShape(artboard, { name: 'Circle', x: 100, y: 100 });
riv.addEllipse(shape, { width: 50, height: 50 });
const fill = riv.addFill(shape);
riv.addSolidColor(fill, hex('#e74c3c'));

const anim = riv.addLinearAnimation(artboard, {
  name: 'pulse',
  fps: 60,
  duration: 60,
  loop: 'pingPong',
});

const keyed = riv.addKeyedObject(anim, shape);

const scaleX = riv.addKeyedProperty(keyed, PropertyKey.scaleX);
riv.addKeyFrameDouble(scaleX, { frame: 0, value: 1.0, interpolation: 'cubic' });
riv.addKeyFrameDouble(scaleX, { frame: 30, value: 1.2, interpolation: 'cubic' });
riv.addKeyFrameDouble(scaleX, { frame: 60, value: 1.0, interpolation: 'cubic' });

const scaleY = riv.addKeyedProperty(keyed, PropertyKey.scaleY);
riv.addKeyFrameDouble(scaleY, { frame: 0, value: 1.0, interpolation: 'cubic' });
riv.addKeyFrameDouble(scaleY, { frame: 30, value: 1.2, interpolation: 'cubic' });
riv.addKeyFrameDouble(scaleY, { frame: 60, value: 1.0, interpolation: 'cubic' });

writeFileSync('pulse.riv', riv.export());

Viewing Generated .riv Files