Deterministic, zero-dependency avatars for React 18 and 19. One seed in, one memorable avatar out — the same face on the server, in the browser, and in your database.
Live playground → · Docs → — searchable API, guides, framework examples and an OG-image demo.
npm install react-avatar-kitReact 18 or 19 is the only peer dependency. react-dom is optional and only needed for
avatarToSvg() on the server.
import { Avatar } from 'react-avatar-kit'
<Avatar seed="ada@example.com" size={64} />That is the whole integration. The seed can be a user id, an email, a username, a slug — any stable string. The same seed always renders the same avatar.
<Avatar seed={user.id} size={96} shape="rounded" alt={user.name} />sizetakes a number (pixels) or any CSS length ("2.5rem","100%").altmakes the SVG accessible (role="img"); omit it and the avatar is decorative.shapeiscircle(default),rounded,squareornonefor a transparent canvas.
- Deterministic. Each attribute is drawn from its own seeded stream, so a seed produces an identical config on every platform, in every render, forever.
- Zero runtime dependencies. No colour library, no prop-types, no babel runtime. React is the only peer.
- Server first. No hooks, no effects, no
useId, no client boundary.<Avatar />works inside a React Server Component and inreact-dom/server. - One SVG. No nested divs, no CSS file, no font, no image request. It scales cleanly to any size and exports to PNG.
- Data, not art direction.
createAvatar()returns a plain JSON object you can store in Postgres, put in a session, or serve from an API.
New opt-in parts, drawn in the same flat 4px-stroke language:
- Facial hair:
moustache,handlebar,beard,goatee,stubble - Accessories:
earring: "stud" | "hoop",headphones: "over-ear"withheadphoneColor - Hair:
buzz - Palettes:
earthandneon
<Avatar seed="ada" facialHair="beard" earring="hoop" headphones="over-ear" palette="earth" />These fields are opt-in: existing seeds render exactly as they did in 1.0, which the
frozen fixture
and npm run check:compat enforce.
| Export | What it does |
|---|---|
<Avatar /> |
Renders a config or a seed as one self-contained SVG. |
createAvatar(seed | options) |
Returns a fully resolved, JSON-serialisable config. |
palettes |
The colour catalogues behind generated avatars. |
avatarToSvg() |
react-avatar-kit/server — standalone SVG string for OG images and email. |
Full signatures, every option and the migration table: docs/api.md. What has actually been run against Next.js, Vite, SSR and React 18/19: docs/integrations.md.
import { createAvatar } from 'react-avatar-kit'
const config = createAvatar(user.id)
await db.users.update({ where: { id: user.id }, data: { avatar: config } })
// Later, anywhere:
<Avatar config={user.avatar} size={48} /><Avatar seed={user.id} hair="mohawk" hat="beanie" shirt="hoodie" glasses="round" />Every option is a plain prop. The playground is a live editor for the same surface.
<Avatar seed={user.id} palette="pastel" />default, pastel, vivid and mono ship in the box. Individual colours
(skin, hairColor, hatColor, shirtColor, background) override the palette.
import { avatarToSvg } from 'react-avatar-kit/server'
const svg = avatarToSvg('ada@example.com', { size: 512, alt: 'Ada' })Returns a standalone SVG document — no DOM, no browser, no canvas.
// app/page.tsx — a React Server Component, no "use client"
import { Avatar } from 'react-avatar-kit'
export default function Page() {
return <Avatar seed="ada@example.com" size={80} alt="Ada" />
}import { renderToStaticMarkup } from 'react-dom/server'
import { Avatar } from 'react-avatar-kit'
const html = renderToStaticMarkup(<Avatar seed="ada@example.com" size={64} />)Framework notes (Next.js App Router, Vite, edge runtimes): docs/integrations.md.
- React
>=18 <20 - Any modern bundler. ESM and CommonJS are both first class; TypeScript declarations ship for both.
- Node
>=18if you use theserversubpath.
The API was rebuilt rather than patched, so prop names and seeded output are intentionally different. The migration table maps every old option to its new name; the playground makes re-picking a look quick.
npm install
npm run dev # playground at http://localhost:5173
npm test # unit, golden-seed and accessibility tests
npm run typecheck
npm run lint
npm run build # ESM + CJS + .d.ts via tsdown
npm run build:site # playground build
npm run check:api # public API surface, ESM and CJS
npm run check:package # tarball contents, exports, size budget
npm run check:ssr # react-server condition + react-dom/server render
npm run check:consumer# installs the tarball under React 18 and 19
npm run test:e2e # Playwright: playground behaviour + WCAG A/AA audit
npm run test:visual # Playwright: visual regression matrix
npm run check:all # every gate above, in orderVisual baselines live in e2e/matrix.visual.ts-snapshots/ and are platform-independent.
Update them deliberately with npm run test:visual:update and review the diff.
Publishing is a tag push, so the artifact is always built by the same workflow that verified it.
Route A — from this machine
npm login # or: npm login --auth-type=web
npm run check:all # every gate, in order
npm publish --access publicRoute B — from CI with OIDC (no token)
-
Register the trusted publisher once (either command or npmjs.com → package → Settings → Trusted Publisher → GitHub):
npm trust github react-avatar-kit --file publish.yml --repo kryptobaseddev/react-avatar-kit --allow-publish
-
Push a version tag:
npm version <patch|minor|major> && git push --follow-tags
publish.yml then typechecks, tests, builds, checks the API/package/SSR, and runs
npm publish --provenance --access public. npm exchanges the workflow's OIDC token for a
short-lived credential, so there is no NPM_TOKEN secret to rotate. Provenance is attached
to the release.
The playground deploys from main through pages.yml; Pages must be set to
Source: GitHub Actions (already configured for this repository).
MIT © 2026 Keaton Hoskins. The illustration geometry is derived from the Avatar Illustration System by @Micah; see NOTICE.md for the full attribution.