seedkin

Botling Stable

Seeded robot avatars: tens of millions of robots from 7 heads, 14 eyes, 11 mouths, 7 tops and more, in 16 palettes and 4 cell shapes. Below 40px Botling draws a simpler 9x9 robot from the same traits, so it keeps a face at 24px. Try it in the playground.

import { botling, botlingDataUri } from 'seedkin/botling';

const svg = botling(user.id, { frame: 'circle' });
const src = botlingDataUri(user.id, { size: 40, title: null });

Random robots

randomSeed() returns a readable random seed, like plucky-servo-427, for a "give me a new robot" button or a default for someone without an id. Store the seed: that's what brings the same robot back.

import { botling, randomSeed } from 'seedkin/botling';

const seed = randomSeed(); // save this with the user
const svg = botling(seed);

There are 400,000 of these seeds, so two people can get the same one. To give every user their own robot, seed with their id. It uses crypto.getRandomValues where there is one (browsers, Node, edge runtimes) and Math.random otherwise, or pass your own source: randomSeed(() => myRng()).

Options

Option Type Default What it does
shape 'square' | 'circle' | 'triangle' | 'diamond' picked by the seed Cell shape.
palette number | Palette picked by the seed Index into PALETTES (0-15), or a palette object: one of HOLIDAY_PALETTES, or your own with hex colours.
size number 96 Width and height in pixels. The SVG scales cleanly to any size.
detail 'auto' | 'full' | 'small' 'auto' 'full' is the detailed 15x15 robot. 'small' is a simpler 9x9 robot from the same traits, with touching cells, made to read at 24px. 'auto' draws 'small' below 40px.
showGrid boolean | 'auto' 'auto' Draw the empty grid cells. 'auto' draws them from 40px up; below that they read as noise. The small robot never draws them.
look 'gapped' | 'flat' | 'inked' | 'soft' | 'soft-inked' | 'sticker' 'gapped' How the cells are drawn: apart, or merged into flat shapes. See Looks.
frame 'square' | 'rounded' | 'squircle' | 'circle' 'square' The outline of the background. See Frames.
background boolean true Draw the palette's background.
title string | null 'Robot avatar' Accessible name. null marks the image decorative (aria-hidden).
animate boolean false The robot hovers, blinks and talks, its top piece wobbles, its ears twitch and a scanline sweeps its screen. Below 40px it only blinks and hovers. See Animation.

Bad options (an unknown shape, an out-of-range palette, a palette colour that isn't hex, a size of 0) throw a RangeError rather than drawing nothing.

Frames

botling(user.id, { frame: 'circle' });

frame sets the outline of the background. Outside it the image is transparent, so a round avatar sits on any page colour without CSS.

The grid behind the robot keeps only whole cells inside the frame, so its edge steps round the curve, and in a squircle it fills the room the smaller robot leaves. FRAMES lists the four, for a picker. A seed never picks a frame, so store the one a user chooses with their seed.

Every frame but 'square' clips with a <clipPath>. Its id names the frame and its size (botling-circle-500-16000), so robots inlined on one page share identical clip paths instead of clashing. In an <img> or a data: URI each robot is its own document, so ids never meet.

Looks

botling(user.id, { look: 'soft' });

look sets how the cells are drawn. The same seed draws the same picture in every look; only the drawing changes.

Only 'gapped' has a grid, so showGrid does nothing in the other looks. Rounded corners and the lines between colours need square cells: with circles, triangles or diamonds, 'soft' draws like 'flat', and 'inked' and 'sticker' keep their outline and border. Small avatars, below 40px, already draw their cells touching, so there 'flat' changes nothing and the other looks add their outline, corners or border. The ink is the palette's shade colour darkened. LOOKS lists the six, for a picker. A seed never picks a look, so store the one a user chooses with their seed. Every style takes look; animated robots keep their outline on their moving parts.

Animation

botling(user.id, { animate: true });

animate: true adds a small CSS animation inside the SVG, so it moves wherever an SVG image does: inlined, in an <img>, as a CSS url() or a data: URI, with no script. Every robot moves:

Below 40px the robot only blinks and hovers, since anything busier reads as flicker at 24px. Timing comes from the seed, so a page of robots doesn't move in unison.

Holiday palettes

HOLIDAY_PALETTES has New Year's, Valentine's, St Patrick's, Fourth of July, Halloween and Christmas. A seed never picks one, so everyday robots don't change; pass one in to dress the same robot up for the day:

import { botling, HOLIDAY_PALETTES } from 'seedkin/botling';

botling(user.id, { palette: HOLIDAY_PALETTES.halloween });

Building a picker

Everything that goes into a robot is exported, so you can offer users a choice:

import { botling, PALETTES, SHAPES, traits } from 'seedkin/botling';

// Let someone choose a shape and palette for their own seed.
const options = SHAPES.flatMap((shape) => PALETTES.map((_, palette) => botling(user.id, { shape, palette, size: 48 })));

// Or show what a seed is made of.
traits(user.id); // { head: 'tv', eyes: 'visor', mouth: 'grille', top: 'antenna', ... }

Store the user's chosen shape, palette, look and frame next to their seed, and pass them back in. LOOKS and FRAMES list the looks and frames, as SHAPES lists the cells.

Advanced

These are exported for drawing a robot some other way, such as onto a canvas or into a PNG (the playground's link preview does this). They follow the same versioning as the SVG: a seed's traits and grids only change in a major version.

Export What it is
traits(seed) Every choice that makes up the seed's robot (Traits).
resolveTraits(seed, options) traits with the shape and numeric palette options applied, checked the way botling checks them.
grid(traits) The detailed robot as a 15x15 array of Role values, indexed [row][column].
smallGrid(traits) The simpler robot drawn below 40px, as a 9x9 array of Role values.
Role What a cell is part of: Empty (0), Body (1), Screen (2), Glow (3), Accent (4), Shade (5). Each maps to the palette colour of the same name. Without a screen (traits.hasScreen false), paint Glow cells in the screen colour, as botling does.
GRID_SIZE, SMALL_GRID_SIZE, CENTER 15, 9, and the detailed grid's centre column (7).

The grids are the robot before it's drawn: cell shape, padding and animation are left to you.