For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. The dithercn agent skill, for building any dither on the engine, is at /.well-known/agent-skills/dithercn/SKILL.md.
dithercn

Avatar

A generative avatar: a mirrored dither face drawn from a name, with a group that overlaps and counts the rest.

Controls
Name
Fill
Colour from name
Colour
Status
Shape
Size96px
Bloom
Ring

Installation

pnpm dlx shadcn@latest add https://dithercn.dev/r/avatar.json

Usage

import { Avatar, AvatarGroup } from "@/components/dithercn/avatar";
 
export function Owner() {
  return <Avatar name="ada@acme.dev" label="Ada Lovelace" status="online" />;
}
 
export function Viewers({ names }: { names: string[] }) {
  return (
    <AvatarGroup max={4}>
      {names.map((name) => (
        <Avatar key={name} name={name} />
      ))}
    </AvatarGroup>
  );
}

name seeds a small random generator that fills half of a 5 by 5 grid of blocks, and the other half mirrors it. A block is more likely to be on near the centre, so every face is a compact mark rather than noise, and the middle column always has at least two blocks. Each block is full or half tone, and the fill decides how half tone is drawn. Behind the face sits a disc of sparse dither in the same colour, densest at the top left as if lit, and kept one cell clear of the face so the mark stays crisp. The same string always gives the same face and colour, on the server and in the browser, so you can use an email or a user id and get a stable avatar for free.

Without color, the avatar picks one of six palette hues from the string. Pass a palette name or any CSS colour to set it yourself.

Examples

Group with a count

AvatarGroup overlaps its avatars, cuts a gap around each in the surface colour, and replaces the rest with a "+N" chip. Set outline to the colour behind the group so the gaps disappear into it.

Members with presence

A member list seeded by email, labelled by name. status adds a dot and appends the state to the accessible name, as in "Alan Turing, busy". The owner gets a ring; the bot gets a grey hatched face.

Fills

The same six names in every fill. Gradient draws half tone as a Bayer checker; dotted and hatched texture it instead; solid uses a lighter opacity. Full blocks are solid in every fill.

Props

Avatar

PropTypeDefault
name*

The string the face and colour come from, such as a name, email or id. Also the accessible name.

Type: stringDefault –
label

Accessible name to use instead of name, when name is an id.

Type: stringDefault –
size

Diameter in pixels. Inside a group, the group's size.

Type: numberDefault 40
color

A palette name or any CSS colour. Without it, one of six hues picked from name.

Type: DitherColorDefault –
fill

How each block's tone is drawn.

Type: "gradient" | "dotted" | "hatched" | "solid"Default "gradient"
shape

A circle or a rounded square.

Type: "circle" | "square"Default "circle"
ring

A ring in the avatar's colour, for the current user or a selection.

Type: booleanDefault false
status

A presence dot in the corner, added to the accessible name.

Type: "online" | "away" | "busy" | "offline"Default –
bloom

A soft glow in the avatar's colour.

Type: "off" | "low" | "high"Default "off"

AvatarGroup

PropTypeDefault
max

Show at most this many avatars, then a +N chip.

Type: numberDefault –
size

Diameter of every avatar in pixels.

Type: numberDefault 32
outline

Colour of the gap around each avatar. Match the surface behind the group.

Type: stringDefault "var(--background)"
moreLabel

What the +N chip announces to screen readers.

Type: (count: number) => stringDefault "N more"

avatarFace(name) and avatarColor(name) are exported too, if you want the same face elsewhere, such as an Open Graph image.

Notes

  • The avatar is a role="img" element named by label or name, plus the status when there is one. The group is a role="group"; give it an aria-label such as "Viewers" when the context does not say.
  • The face is one or a few SVG paths, cached per name and fill. No canvas, no client JavaScript.
  • Avatars in a group lift by 2 pixels on hover on devices that can hover. With reduced motion they stay put.