Skip to content
Nurbinurblingsavatars

API reference

Everything below is exported from the nurblings package. It has no runtime dependencies and runs anywhere JavaScript does: browsers, Node, Deno, Bun, edge runtimes and build-time rendering.

import { nurbling, traits, toDataUri } from 'nurblings'

nurbling(seed, options?)

Returns one Nurbling as an SVG string.

nurbling('user-42')
nurbling('user-42', { size: 48, background: 'circle', title: 'Ada Lovelace' })

Seeds are normalised first (see normaliseSeed), so Ada Lovelace, ada.lovelace and ADA_LOVELACE hatch the same Nurbling. Prefer a stable user id over an email: ids never change, and normalisation means two different strings can hatch the same creature.

Options

OptionTypeDefaultWhat it does
sizenumber128Width and height in pixels, a positive number. At 32 and below, small-size mode drops the mouth and extras so the face still reads, and motion stops.
background'none' | 'circle' | 'squircle' | 'square''none'The container behind the Nurbling, in a tint of its own shell colour.
titlestring'Nurbling'The accessible name, used for aria-label and <title>. Escaped for you.
decorativebooleanfalseHides the avatar from assistive technology (aria-hidden, no name), for an avatar beside the person’s name in text.
animateboolean | MotiontrueAmbient life: breath, blink, antenna drift and a hover wiggle. false draws a still avatar; an object picks layers. See Motion and transitions.
frame'auto' | 'full' | 'portrait''auto'How the Nurbling sits in its square. portrait crops closer on the face, which reads better in small round avatars; full shows the whole figure. auto uses a portrait at 48 px and below.
mode'light' | 'dark' | 'auto''light'The page the avatar sits on. The container colour and, where needed, the antennae change; the creature does not. auto follows the OS or a data-theme="dark" or .dark ancestor with CSS only.
transitionstringnoneA key for morph(): the same key in two places links them, so the avatar glides between them. Adds a data-nurbling-transition attribute.
gen11The trait generation. Pin it to keep an avatar identical across future releases.
mood'neutral' | 'curious' | 'pleased' | 'thinking' | 'sleepy'from the seedPins the resting mood.
mouth'none' | 'line' | 'smile'from the seedPins the mouth.
extra'none' | 'scarf' | 'hat' | 'collar'from the seedPins the extra.
silhouette'classic' | 'basketball' | 'squat' | 'firm' | 'round' | 'bell' | 'wide' | 'smooth' | 'pear' | 'tall'from the seedPins the body design. Each seed still varies it slightly and gets its own plate pattern.
shell'mint' | 'sky' | 'butter' | 'peach' | 'lilac' | 'sage' | 'cloud' | 'blush' | 'lemon'from the seedPins the body colour. The accent is still chosen from the colours that read well on it.

Pinning one trait never changes any other: every trait is drawn from its own random stream. The one exception is shell: pinning it re-picks the accent from the colours that read well on that shell, so the brow and antennae keep their contrast.

An unknown value for gen, mood, mouth, extra, silhouette or shell throws a RangeError, and so do a size or an animate.speed that is not a positive number.

traits(seed, options?)

Returns the resolved traits a seed hatches, without rendering: silhouette, antennae, eyes, brow, mouth, extra, mood and palette. Useful for tests, for theming around an avatar (the palette’s shell and accent are good UI colours), or for rendering with renderTraits. It returns a fresh object every time: changing it never affects any other avatar.

nurblingSrc(seed, options?)

The avatar as a data URI in one call, for an <img src>, a CSS url() or an email. Takes the same options as nurbling(). A createNurblings instance has the same thing as .src(seed, options?).

img.src = nurblingSrc(user.id, { size: 64, background: 'circle' })

toDataUri(svg)

Wraps an SVG string as a data: URI for an <img src> or a CSS background-image.

const src = toDataUri(nurbling('user-42', { size: 64 }))

renderTraits(traits, options?)

Renders a traits object you built or edited yourself. Takes the rendering options: size, background, title, decorative, animate, frame, mode and transition. Every value in the traits is checked first: a colour that is not 6-digit hex, a name outside the known traits or a number that is not finite throws a RangeError, so traits from a database or a form can never inject markup.

normaliseSeed(seed)

The normalisation every seed goes through before hashing: Unicode NFKC, lower case, accents and other combining marks stripped, whitespace and punctuation removed. Emoji are kept, so an emoji seed still hatches its own Nurbling.

nurbi(options?)

From nurblings/nurbi: Nurbi, the family’s flagship character, as the stored drawing. It takes the rendering options: size, background, title, decorative, animate, frame and transition. He has an entry of his own so no other import carries his drawing. The seed nurbi is an ordinary Nurbling.

createNurblings(config)

Makes an instance with your palette, body designs, drawn parts and defaults, returning { nurbling, traits, src } with the same signatures as above. Its calls also take theme and props. Colours are checked for contrast, and part positions and slot names are checked, at setup. See Customising.

ConfigWhat it does
themeA colour set for every avatar
shells, accentsBody and mark colours, replacing the built-in ones
silhouettes, eyes, mouths, extrasLists the seed picks from. New names are added to the built-in ones, false drops one, and weight sets how often each comes up. New eyes, mouths and extras draw themselves with draw(ctx)
slotsReplace, wrap or drop any part by name, built in or added
partsNew parts, each { after?, small?, draw(ctx) }
propsData every slot and part reads as ctx.props; a call’s props win
usePresets applied first, in order: each is a config like this one
defaultsOptions for every call

Every slot and part receives the same context: anchors, colours, paint(), random(), theme, options, props, n(), esc(), small, size, mode, traits and geometry. See Extending parts.

compose(...configs)

Combines configs into one, the same way use does: slots chain, each later one wrapping what the earlier ones drew; parts, designs, colours and props merge by name, later names winning; the last theme wins; defaults merge.

const avatars = createNurblings(compose(brand, glasses, status))

nurblings/themes

Named themes, palette() and colour helpers, in their own entry. Components take theme="lagoon"; createNurblings({ theme }) takes a theme object. See Customising.

ExportDoes
lagoon, punch, candy, picnic, sorbet, terracotta, marble, riso, lime, bauhausThe built-in themes
THEMES, ThemeNameAll of them by name
palette(colours, name?)A theme from 2 to 5 hex colours
themed(theme)A ready instance: themed('lagoon').nurbling(seed)
contrast, ensureContrast, readableOn, shade, pickBy, recolour, setFillColour helpers for slots
themeOf(theme)A theme from its name, or the theme object itself; an unknown name throws a RangeError
renderNurbling(renderer, seed, options, theme?)What the framework components call: an app-wide instance when there is one, a named theme when given, otherwise the default family. For writing a component of your own

morph(update, options?) and transitionName(key)

From nurblings/transition, a separate entry of under 1 KB. morph applies a page change and moves every avatar tagged with a transition key from where it was to where it lands. options is MorphOptions: duration in milliseconds (450 by default) and easing, any CSS easing. transitionName(key) returns the view-transition-name a key uses, for cross-page transitions in your framework. See Motion and transitions.

Constants and types

ExportWhat it is
SILHOUETTES, SHELLS, ACCENTSGeneration 1’s body designs, body colours and accent colours by name: the values the matching options accept
SLOTS, SlotNameThe drawn parts in paint order, the names slots and parts.after take
NurblingOptions, RenderOptionsThe options of nurbling() and of renderTraits()
Traits and its parts (Silhouette, Antennae, Eyes, Brow, Palette, …)What traits() returns and renderTraits() takes
NurblingsConfig, ConfiguredOptions, NurblingsA createNurblings config, its call options, and the instance it returns
Slot, Slots, Part, SlotContext, CallOptions, Variant, Variants, Anchors, Point, EyeAnchor, ColourRole, Props, SilhouetteShapeThe pieces of an extension; see Customising
NurblingRendererAnything with a nurbling(seed, options) method: the default package or an instance. Every component’s nurblings prop takes one
RngThe seeded random source behind ctx.random()
Theme, Hex, Motion, Mode, Frame, Background, GenerationThe value types the options use

Generations and stability

Traits ship in numbered generations. Within a generation, a seed always hatches the same Nurbling: releases never change existing avatars. The exact SVG for a seed is stable for the same options and configuration; motion markup is a layer on top of the drawing and can be turned off with animate: false. New shapes, colours or extras arrive as a new generation, and you opt in by passing gen.

Accessibility

  • Every SVG has role="img", an aria-label and a <title>. Pass title with the person’s name, for example title: 'Ada Lovelace'.
  • When the name is already written next to the avatar, pass decorative: true instead, so screen readers do not read it twice.
  • Colours are chosen for contrast: the accent clears 3:1 on the body, and the antennae read on both light and dark pages.
  • Motion is on by default, stops completely under prefers-reduced-motion, and turns off with animate: false.

Licence of generated avatars

The code is MIT. Every avatar it generates is dedicated to the public domain under CC0: use them anywhere, commercially or not, without attribution. Nurbi’s exact body design and colours are not among the generator’s choices. The one exception is Nurbi himself, the stored drawing that nurbi() from nurblings/nurbi returns: the names Nurbi and Nurblings and that artwork are reserved, see TRADEMARKS.md.