seedkin

React

An avatar is a pure function of its seed, so in React it's a small component with no state and no effects. It renders the same on the server and the client.

An avatar component

import { useMemo } from 'react';
import { botlingDataUri } from 'seedkin/botling';

export function Avatar({ id, size = 40 }: { id: string; size?: number }) {
  const src = useMemo(() => botlingDataUri(id, { size, title: null }), [id, size]);
  return <img src={src} alt="" width={size} height={size} />;
}

title: null leaves the accessible name to the <img>. Keep alt="" when the person's name sits next to the avatar, so screen readers don't say it twice; otherwise describe it, such as alt={`${user.name}'s avatar`}.

It has no hooks that need the browser, so it works as a Server Component in Next.js without 'use client'. There, the useMemo can go.

Inline SVG

import { botling } from 'seedkin/botling';

export function InlineAvatar({ id, size = 40 }: { id: string; size?: number }) {
  return <span dangerouslySetInnerHTML={{ __html: botling(id, { size, title: null }) }} />;
}

Inlining is safe: the seed never appears in the markup, and a title you pass is escaped. Prefer the <img> for long lists, since the browser decodes each image once and keeps the DOM small, and for animated avatars on pages with a strict Content Security Policy (see Animation).

Other styles

Swap the import for another style; the options are the same:

import { snootDataUri } from 'seedkin/snoot';

<img src={snootDataUri(user.id, { size: 40, title: null })} alt="" width={40} height={40} />