Bot avatars
Animated avatars for your AI agents: eighteen glossy 3D shapes with living faces that look around, jump, hop while they work and doze off between tasks. Drawn on a plain canvas, so no WebGL and no dependencies.
Installation
npm install bot-avatars
Usage
import { BotAvatar } from 'bot-avatars';
<BotAvatar type="clover" state={busy ? 'working' : 'default'} />
Installation
bot-avatars-native is not on npm yet — it lives in this repo at packages/bot-avatars/ports/react-native/bot-avatars-native. Expo needs expo run:ios / run:android (native modules).
npm install @shopify/react-native-skia react-native-reanimated react-native-worklets
Usage
import { BotAvatar } from 'bot-avatars-native';
<BotAvatar type="clover" state={busy ? 'working' : 'default'} size={64} />
Installation
iOS 17+. It draws into SwiftUI's Canvas, so SwiftPM builds it on its own; BotAvatarStage puts a whole roster on one canvas.
// Package.swift — or Xcode: File › Add Package Dependencies… › Add Local… .package(path: "packages/bot-avatars/ports/ios/BotAvatarsKit")
Usage
import BotAvatarsKit BotAvatar(type: .clover, state: busy ? .working : .default)
Add the Bot avatars from Libraries.dev to my React app.
Install:
npm install bot-avatars
Usage:
import { BotAvatar } from 'bot-avatars';
<BotAvatar type="clover" state={busy ? 'working' : 'default'} />
// A roster: each agent gets its own shape
<BotAvatar type="star" size={36} />
<BotAvatar type="flower" face="mouth" state="working" />
Props:
- type: "clover" | "flower" | "triangle" | "square" | "blob" | "ghost" | "circle" | "drop" | "star" | "droid" | "mech" | "alien" | "hexagon" | "cat" | "cloud" | "pill" | "pebble" | "puddle" — the body shape, each with its own colour
- face: "eyes" (default) | "mouth" — the eyes alone, or eyes with a mouth
- state: "default" | "working" | "sleeping" — looking around with a jump now and then, hopping and spinning with a laugh now and then, head down with shut lids and slow breaths
- size: px or any CSS length (default 64)
- color: body colour (defaults to the type's palette colour); brightness: 0.5–1.5, darker or lighter body; saturation: 0.5–1.5, duller or more vivid body; ink: face colour (auto dark or light)
- speed: multiplier on the animations; paused: freeze; seed: 0–1 offset so a row does not blink in unison
- shading: "plastic" (default: a per-pixel glossy material — baked pillow form with occluded cusps, hot spot, sheen, Fresnel rim, window reflection) | "crisp" (lit rim with a clean edge) | "smooth" (soft shadow and highlight, no edge) | "flat" (depth only)
- shadow (default 0.35), highlight (1.3): 0–2 intensities; light: degrees clockwise from the top (265, from the left); depth: 0.2–2 body thickness (0.65); rim: 0–2 Fresnel strength in plastic, rim width in crisp (0.5); spread: 0.4–2.5 highlight width in plastic, reach of the soft shading in smooth (1.55)
- turn: 0–2, how far the head turns from side to side while idle (1 as the library has it, 0 faces forward)
- interactive: true by default — the eyes and head follow a pointer nearby and a click makes the avatar hop and turn round; false turns it off
- jumpHeight (body units, default 26), jumpTime (seconds in the air, 0.68), jumpStretch (stretch in the air, 0–2, 1), jumpSquash (squash on the ground, 0–2, 1.15), jumpSquashTime (seconds the landing squash takes, 0.37), jumpSquashEase (sharp | pulse | soft | bouncy), jumpGroundTime (seconds held at the deepest squash on the ground, 0.11; 0 for none), jumpGroundEase (how the weight settles through that hold: sharp | pulse | soft | bouncy, pulse), jumpRiseTime (seconds from the deepest squash back to shape, 0.33), jumpRiseEase (how it rises: sharp | pulse | soft | bouncy, pulse), jumpClickSquashTime (seconds a click's crouch and landing squash take, 0.24), jumpSpin (whole turns, 1), jumpLean (degrees, 6), jumpEvery (seconds between idle jumps, 8; 0 for none), jumpLand (seconds before or after touch-down that the landing squash begins, 0 = at contact): the idle flip and a click's jump
- theme: "auto" (default, from an ancestor data-theme / dark / light class, then prefers-color-scheme) | "dark" | "light" — the surface the avatar sits on
- whirl (0–2 strength, off by default, 1 turns it on), whirlSize (0.6–1.6), whirlWidth (0.4–2), whirlLength (0.4–1.6), whirlTilt (0.5–1.8): the motion ring round a spin, a translucent tube of the body's own plastic
Bot avatars draws each avatar on a 2D canvas as a lit, rounded extrusion
of a vector shape — a simple 3D head that turns, hops and flips — with a
small rig that cross-animates every state change. No WebGL, zero runtime
dependencies, React 18 or newer. It respects prefers-reduced-motion
(still pose, no motion), pauses offscreen, and carries role="img" with a
per-state label.
Docs: https://libraries.dev/bots.html