# @avatar-generator > @avatar-generator is an open-source (MIT) JavaScript and TypeScript library that generates deterministic SVG avatars from any seed string. It has eleven styles, each in its own package, no runtime dependencies, and official components for React, Vue, Svelte and Angular, plus a custom element. --- # Compare JavaScript Avatar Libraries Source: https://avatar-generator.hugoogb.dev/get-started/comparison/ **Choose @avatar-generator** if you want official components for several frameworks, MIT licensing across every style, and support for Node.js 18. **Choose another library** if you need a hosted avatar API, more than eleven styles, or languages other than JavaScript. DiceBear, Boring Avatars and Jdenticon are all good, and far more widely used than @avatar-generator. If adoption and track record matter most to you, weigh that heavily. ## Comparison table Checked in November 2026 against each project's documentation and npm listing. These projects change, so confirm anything your decision depends on. | | @avatar-generator | [DiceBear](https://www.dicebear.com/) | [Boring Avatars](https://github.com/boringdesigners/boring-avatars) | [Jdenticon](https://jdenticon.com/) | | ----------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------- | ----------------------------------- | | **Styles** | 11 | 61 | 6 | Identicons only | | **License** | MIT for all packages | MIT for the code; artwork licenses vary by style | MIT | MIT | | **Framework support** | Components for React, Vue, Svelte and Angular, plus a custom element | Usage guides for Angular, React, React Native, Vue and Svelte | React component | Plain JavaScript library | | **Languages** | JavaScript and TypeScript | JavaScript, PHP, Python, Rust, Go, Dart, C# | JavaScript | JavaScript, C#, PHP | | **Core runtime dependencies** | None | None | None; needs React as a peer | 1 (`canvas-renderer`) | | **Minimum Node.js** | 18 | 22 | Not specified | 6.4 | ## @avatar-generator vs DiceBear DiceBear is the most established option. It has many more styles, a free HTTP API that serves avatars by URL, and libraries for seven languages, so choose it for any of those. @avatar-generator is narrower. Its advantages are components you install instead of writing yourself, one MIT license across every style with no per-style check, and support for Node.js 18 where the current DiceBear core requires Node.js 22. ## @avatar-generator vs Boring Avatars Boring Avatars is a small React component with six gradient-based variants. If you're building in React and like that look, it's a simple choice. Its hosted API is a separate paid service. @avatar-generator fits better if you work outside React, want non-gradient styles such as faces, pixels or animals, or need avatars as a string on the server without rendering a component. ## @avatar-generator vs Jdenticon Jdenticon does one thing: geometric identicons. It also runs in C# and PHP, so it's a strong choice if identicons are all you need or your backend isn't JavaScript. @avatar-generator includes an identicon-style option, [`style-geometric`](https://avatar-generator.hugoogb.dev/reference/gallery/), alongside ten other styles. ## Which avatar library should you choose? - **Multi-framework JavaScript projects, or Node.js 18:** @avatar-generator - **A hosted avatar URL, the widest style range, or a non-JavaScript backend:** DiceBear - **A React app that wants gradient avatars:** Boring Avatars - **Identicons only:** Jdenticon To see the eleven @avatar-generator styles, open the [Style Gallery](https://avatar-generator.hugoogb.dev/reference/gallery/) or try your own seed in the [Playground](https://avatar-generator.hugoogb.dev/get-started/playground/). --- # Install the Avatar Generator Source: https://avatar-generator.hugoogb.dev/get-started/installation/ v3.0.0 is the current release and the only supported one. The commands on this page install it. See [Versions & Support](https://avatar-generator.hugoogb.dev/reference/versioning/) for why 1.x and 2.x should not be used. ## Requirements - **Node.js 18+** for server-side or build-time use - Any bundler, or none — packages ship both ESM and CommonJS with a conditional `exports` map and per-condition type declarations - `@avatar-generator/angular` is the one exception: Angular Package Format is ESM-only, so that package has no `require()` entry point ## Quick start You always need two things: `@avatar-generator/core`, which holds `createAvatar`, and at least one style package, which does the drawing. Core renders nothing on its own. ```sh npm install @avatar-generator/core @avatar-generator/style-initials ``` ```sh pnpm add @avatar-generator/core @avatar-generator/style-initials ``` ```sh yarn add @avatar-generator/core @avatar-generator/style-initials ``` That is enough for plain JavaScript or TypeScript — see [Manual Usage](https://avatar-generator.hugoogb.dev/guides/manual/). Add a framework wrapper below if you want a component instead of a string. ## Framework packages Each wrapper declares its framework as a peer dependency, so it uses the version your app already pins. ### React React 18 or 19. ```sh npm install @avatar-generator/core @avatar-generator/react @avatar-generator/style-initials ``` ```sh pnpm add @avatar-generator/core @avatar-generator/react @avatar-generator/style-initials ``` ```sh yarn add @avatar-generator/core @avatar-generator/react @avatar-generator/style-initials ``` ### Vue Vue 3. ```sh npm install @avatar-generator/core @avatar-generator/vue @avatar-generator/style-initials ``` ```sh pnpm add @avatar-generator/core @avatar-generator/vue @avatar-generator/style-initials ``` ```sh yarn add @avatar-generator/core @avatar-generator/vue @avatar-generator/style-initials ``` ### Svelte Svelte 4 or 5. The published component is already preprocessed to plain JavaScript, so no preprocessor configuration is needed. ```sh npm install @avatar-generator/core @avatar-generator/svelte @avatar-generator/style-initials ``` ```sh pnpm add @avatar-generator/core @avatar-generator/svelte @avatar-generator/style-initials ``` ```sh yarn add @avatar-generator/core @avatar-generator/svelte @avatar-generator/style-initials ``` ### Angular Angular 17 through 21. Shipped as an Angular Package Format library (FESM2022, partial Ivy), so AOT builds consume it directly. ```sh npm install @avatar-generator/core @avatar-generator/angular @avatar-generator/style-initials ``` ```sh pnpm add @avatar-generator/core @avatar-generator/angular @avatar-generator/style-initials ``` ```sh yarn add @avatar-generator/core @avatar-generator/angular @avatar-generator/style-initials ``` ### Web component No framework peer dependency — it is a standard custom element, usable from any framework or from a plain HTML page. ```sh npm install @avatar-generator/core @avatar-generator/web-component @avatar-generator/style-initials ``` ```sh pnpm add @avatar-generator/core @avatar-generator/web-component @avatar-generator/style-initials ``` ```sh yarn add @avatar-generator/core @avatar-generator/web-component @avatar-generator/style-initials ``` ## Available styles Every style is its own tree-shakeable package. Install only the ones you import. | Package | Description | | ------------------------------------- | ------------------------------------------------ | | `@avatar-generator/style-initials` | Letter initials on colored backgrounds | | `@avatar-generator/style-geometric` | GitHub-style symmetrical identicon grids | | `@avatar-generator/style-pixels` | 8-bit retro pixel faces | | `@avatar-generator/style-rings` | Concentric rings, segmented and dashed variants | | `@avatar-generator/style-faces` | Minimal flat geometric faces | | `@avatar-generator/style-illustrated` | Detailed cartoon faces with accessories | | `@avatar-generator/style-anime` | Anime/manga-inspired faces with expressive eyes | | `@avatar-generator/style-abstract` | Mondrian/Kandinsky/Bauhaus-inspired compositions | | `@avatar-generator/style-emoji` | Yellow emoji-style expressive faces | | `@avatar-generator/style-animals` | Cute animal avatars (cat, dog, fox, panda, …) | | `@avatar-generator/style-gradient` | Smooth gradients with pattern overlays | To install several at once: ```sh npm install @avatar-generator/style-geometric @avatar-generator/style-pixels @avatar-generator/style-rings @avatar-generator/style-faces @avatar-generator/style-illustrated @avatar-generator/style-anime @avatar-generator/style-abstract @avatar-generator/style-emoji @avatar-generator/style-animals @avatar-generator/style-gradient ``` ```sh pnpm add @avatar-generator/style-geometric @avatar-generator/style-pixels @avatar-generator/style-rings @avatar-generator/style-faces @avatar-generator/style-illustrated @avatar-generator/style-anime @avatar-generator/style-abstract @avatar-generator/style-emoji @avatar-generator/style-animals @avatar-generator/style-gradient ``` ```sh yarn add @avatar-generator/style-geometric @avatar-generator/style-pixels @avatar-generator/style-rings @avatar-generator/style-faces @avatar-generator/style-illustrated @avatar-generator/style-anime @avatar-generator/style-abstract @avatar-generator/style-emoji @avatar-generator/style-animals @avatar-generator/style-gradient ``` ## Keeping versions in step All seventeen packages are released together at one version. Mixing majors is not supported, so upgrade them as a set. Style packages depend on `@avatar-generator/core` directly, so your package manager will install a compatible core either way — but you import `createAvatar` from core in your own code, so declare it explicitly rather than relying on a transitive dependency. ## Verify your install ```ts const a = createAvatar(initials, { seed: "hello" }); const b = createAvatar(initials, { seed: "hello" }); console.log(a.svg === b.svg); // true — same seed, same bytes ``` ## Next steps - [Manual Usage](https://avatar-generator.hugoogb.dev/guides/manual/) — the core API and every style's options - [React](https://avatar-generator.hugoogb.dev/guides/react/) · [Vue](https://avatar-generator.hugoogb.dev/guides/vue/) · [Svelte](https://avatar-generator.hugoogb.dev/guides/svelte/) · [Angular](https://avatar-generator.hugoogb.dev/guides/angular/) · [Web Component](https://avatar-generator.hugoogb.dev/guides/web-component/) - [API Reference](https://avatar-generator.hugoogb.dev/reference/avatar/) — every option, type and helper - [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/) — if you are coming from v1 or v2 --- # What Is @avatar-generator? Source: https://avatar-generator.hugoogb.dev/get-started/introduction/ **@avatar-generator** generates unique, deterministic SVG avatars. Give it a seed — a user ID, an email, anything stringy — pick a style, and get the same avatar back every time, on every platform. :::caution[Install the 3.x line] v3.0.0 is the current release and the only supported one. The 2.x tarballs on npm cannot be loaded by Node, and most of the 2.x line was never published at all. See [Versions & Support](https://avatar-generator.hugoogb.dev/reference/versioning/). ::: ## Features - **11 styles** — from letter initials to anime faces, each its own package - **Deterministic** — the same seed always produces byte-identical SVG - **Tree-shakeable** — you only bundle the styles you actually import - **Works anywhere** — React, Vue, Svelte, Angular, a custom element, or plain JS - **No runtime dependencies** — core ships ESM and CommonJS and depends on nothing - **SSR-safe** — `createAvatar` returns a string; no DOM, no browser globals ## Quick example ```typescript const avatar = createAvatar(initials, { seed: "john.doe@example.com", size: 64, }); img.src = avatar.toDataUri(); // or use avatar.svg directly ``` ## Available styles Every style is a separate package, so eleven styles cost you nothing if you | Style | Package | Description | | --------------- | ------------------------------------- | ------------------------------------------------ | | **Initials** | `@avatar-generator/style-initials` | Letter initials on colored backgrounds | | **Geometric** | `@avatar-generator/style-geometric` | GitHub-style symmetrical identicon grids | | **Pixels** | `@avatar-generator/style-pixels` | 8-bit retro pixel faces | | **Rings** | `@avatar-generator/style-rings` | Concentric rings, segmented and dashed variants | | **Faces** | `@avatar-generator/style-faces` | Minimal flat geometric faces | | **Illustrated** | `@avatar-generator/style-illustrated` | Detailed cartoon faces with accessories | | **Anime** | `@avatar-generator/style-anime` | Anime/manga-inspired faces with expressive eyes | | **Abstract** | `@avatar-generator/style-abstract` | Mondrian/Kandinsky/Bauhaus-inspired compositions | | **Emoji** | `@avatar-generator/style-emoji` | Yellow emoji-style expressive faces | | **Animals** | `@avatar-generator/style-animals` | Cute animal avatars (cat, dog, fox, panda, …) | | **Gradient** | `@avatar-generator/style-gradient` | Smooth gradients with pattern overlays | See them side by side in the [Style Gallery](https://avatar-generator.hugoogb.dev/reference/gallery/), or tweak their options in the [Configurator](https://avatar-generator.hugoogb.dev/reference/configurator/). ## Framework packages | Package | For | | --------------------------------- | --------------------------------------------- | | `@avatar-generator/react` | React 18 and 19 | | `@avatar-generator/vue` | Vue 3 | | `@avatar-generator/svelte` | Svelte 4 and 5 | | `@avatar-generator/angular` | Angular 17 through 21, standalone or NgModule | | `@avatar-generator/web-component` | Any framework, or none — a custom element | None of these are required: `createAvatar` returns an SVG string you can render however you like. ## How determinism works A style never calls `Math.random()`. It derives every choice — palette entry, hair style, expression — from a seeded generator built from `options.seed`. The same seed and options therefore produce the same bytes in a Node server render, a browser, and an edge runtime. That is what makes an avatar usable as a stable identity: you can generate it on demand instead of storing it. ## Getting started 1. [Install](https://avatar-generator.hugoogb.dev/get-started/installation/) core and at least one style 2. Try every style in the [Playground](https://avatar-generator.hugoogb.dev/get-started/playground/) 3. Read [Manual Usage](https://avatar-generator.hugoogb.dev/guides/manual/) for the core API 4. Or jump to your framework: [React](https://avatar-generator.hugoogb.dev/guides/react/), [Vue](https://avatar-generator.hugoogb.dev/guides/vue/), [Svelte](https://avatar-generator.hugoogb.dev/guides/svelte/), [Angular](https://avatar-generator.hugoogb.dev/guides/angular/), [Web Component](https://avatar-generator.hugoogb.dev/guides/web-component/) 5. Browse the [Cookbook](https://avatar-generator.hugoogb.dev/guides/cookbook/) for avatar groups, image fallbacks, theming, caching and SSR ## Upgrading Coming from an older version? The [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/) covers both v2 → v3 (two import changes) and v1 → v3 (a full API change). --- # Avatar Generator Playground Source: https://avatar-generator.hugoogb.dev/get-started/playground/ Try all eleven styles below. Change the seed and watch every style change together — same input, eleven different deterministic outputs. This embedded playground uses simplified renderers that match each style's shape, so the page stays dependency-free. Install the real packages for the full output, or use the [Configurator](https://avatar-generator.hugoogb.dev/reference/configurator/) to tweak individual options and copy the matching `createAvatar()` call. ## Run the playgrounds locally The repository ships six Vite playgrounds — one per framework wrapper, plus one for the core API. They import the workspace sources directly, so changes show up immediately. 1. Clone the repository ```sh git clone https://github.com/hugoogb/avatar-generator.git ``` 2. Install the playground dependencies The playgrounds are their own pnpm project, so install from that directory: ```sh cd avatar-generator/playgrounds && pnpm install ``` 3. Start the one you want ```sh pnpm playground:core ``` ```sh pnpm playground:react ``` ```sh pnpm playground:vue ``` ```sh pnpm playground:svelte ``` ```sh pnpm playground:angular ``` ```sh pnpm playground:web-component ``` 4. Open the URL Vite prints in the terminal To check that all six still build — which CI does on every pull request: ```sh pnpm build:all ``` ## Styles you can try | Style | Package | Description | | ----------- | ------------------------------------- | ------------------------------------------------ | | Initials | `@avatar-generator/style-initials` | Letter initials on colored backgrounds | | Geometric | `@avatar-generator/style-geometric` | GitHub-style symmetrical identicon grids | | Pixels | `@avatar-generator/style-pixels` | 8-bit retro pixel faces | | Rings | `@avatar-generator/style-rings` | Concentric rings, segmented and dashed variants | | Faces | `@avatar-generator/style-faces` | Minimal flat geometric faces | | Illustrated | `@avatar-generator/style-illustrated` | Detailed cartoon faces with accessories | | Anime | `@avatar-generator/style-anime` | Anime/manga-inspired faces with expressive eyes | | Abstract | `@avatar-generator/style-abstract` | Mondrian/Kandinsky/Bauhaus-inspired compositions | | Emoji | `@avatar-generator/style-emoji` | Yellow emoji-style expressive faces | | Animals | `@avatar-generator/style-animals` | Cute animal avatars (cat, dog, fox, panda, …) | | Gradient | `@avatar-generator/style-gradient` | Smooth gradients with pattern overlays | Every style produces a deterministic avatar from the seed you give it: the same seed always returns the same SVG. --- # Angular Avatar Component Source: https://avatar-generator.hugoogb.dev/guides/angular/ `@avatar-generator/angular` provides ``, a standalone component that renders an `` from any style. It supports Angular 17 through 21 and ships as an Angular Package Format library (FESM2022, partial Ivy), so AOT builds consume it directly. `AvatarComponent` is now `standalone: true`, and the package is built with ng-packagr. Earlier versions shipped plain `tsc` output, which made AOT builds fall back to the JIT compiler and fail. See the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). ## Import the component Add `AvatarComponent` to the `imports` of whichever component uses it: ```ts @Component({ selector: "app-user-profile", imports: [AvatarComponent], template: ``, }) export class UserProfileComponent { initialsStyle = initials; } ``` A style is a plain object, so expose it as a field on the component rather than importing it into the template. ### NgModule applications If your application still uses NgModules, import `AvatarModule`, which imports and re-exports the standalone component: ```ts @NgModule({ declarations: [AppComponent], imports: [BrowserModule, AvatarModule], bootstrap: [AppComponent], }) export class AppModule {} ``` Existing `imports: [AvatarModule]` code needs no change. Do not add `AvatarComponent` to `declarations` — declaring a standalone component is an error. ## Basic usage ```ts @Component({ selector: "app-user-profile", imports: [AvatarComponent], template: ` `, }) export class UserProfileComponent { initialsStyle = initials; user = { id: "user-123", name: "Hugo GB" }; } ``` ## Using different styles ```ts @Component({ selector: "app-avatar-gallery", imports: [AvatarComponent], template: ` `, }) export class AvatarGalleryComponent { styles: Array<{ style: Style; label: string }> = [ { style: initials, label: "Initials" }, { style: geometric, label: "Geometric" }, { style: pixels, label: "Pixels" }, { style: rings, label: "Rings" }, { style: faces, label: "Faces" }, { style: illustrated, label: "Illustrated" }, { style: anime, label: "Anime" }, { style: abstract, label: "Abstract" }, { style: emoji, label: "Emoji" }, { style: animals, label: "Animals" }, { style: gradient, label: "Gradient" }, ]; options = { seed: "user-123", size: 64 }; } ``` `@for` is Angular 17+ control flow. On an older template style use `*ngFor="let entry of styles"` with `CommonModule` imported. ## With custom options ```ts @Component({ selector: "app-custom-avatar", imports: [AvatarComponent], template: ``, }) export class CustomAvatarComponent { geometricStyle = geometric; avatarOptions: GeometricOptions = { seed: "user-123", size: 96, square: true, colors: ["#FF6B6B", "#4ECDC4", "#45B7D1"], border: { width: 2, color: "#333" }, }; } ``` Import the option type from the style package; in v3 core no longer declares style-specific types. ## Inputs | Input | Type | Default | Description | | --------- | ------------------------- | ---------- | ------------------------------- | | `style` | `Style` | (required) | The style object to render with | | `options` | `T extends AvatarOptions` | (required) | Seed and style-specific options | | `alt` | `string` | `"Avatar"` | Alt text for the `` | ## Change detection The component uses `OnPush` and regenerates in `ngOnChanges`, so it re-renders when the `style` or `options` **reference** changes. Mutating the existing options object in place will not trigger an update: ```ts // Does not re-render this.avatarOptions.size = 128; // Re-renders this.avatarOptions = { ...this.avatarOptions, size: 128 }; ``` ## ESM only Angular Package Format has been ESM-only since Angular v13, so this package has no `require()` entry point. Every other `@avatar-generator` package ships both ESM and CommonJS. If you need CommonJS in an Angular project — in a script run under plain Node, say — use `@avatar-generator/core` and the style package directly rather than this wrapper. --- # Avatar Recipes and Patterns Source: https://avatar-generator.hugoogb.dev/guides/cookbook/ Recipes for patterns that come up often with `@avatar-generator`. Each one assumes you already have `createAvatar` or a framework wrapper wired up; see the [Manual](https://avatar-generator.hugoogb.dev/guides/manual/), [React](https://avatar-generator.hugoogb.dev/guides/react/), [Vue](https://avatar-generator.hugoogb.dev/guides/vue/), [Svelte](https://avatar-generator.hugoogb.dev/guides/svelte/), or [Web Component](https://avatar-generator.hugoogb.dev/guides/web-component/) guides for setup. ## Avatar groups (stacked with overlap) A common layout in user lists — several avatars overlapping with a border. ```ts function avatarGroup(users: Array<{ id: string; name: string }>, max = 3): string { const displayed = users.slice(0, max); const overflow = users.length - displayed.length; const size = 32; return ( `
` + displayed .map((user, i) => { const avatar = createAvatar(initials, { seed: user.id, name: user.name, size, border: { width: 2, color: "#fff" }, }); return `${user.name}`; }) .join("") + (overflow > 0 ? `+${overflow}` : "") + `
` ); } ``` The border on each avatar prevents the overlapping edges from blending into each other. Use `-8px` to `-12px` margin-left depending on how much overlap you want. ## Gravatar-style fallback If you have a real profile image but want a deterministic fallback when it 404s, render an avatar under the `` and swap via the `onerror` handler. ```ts function userAvatar(user: { email: string; name: string }): string { const fallback = createAvatar(initials, { seed: user.email, name: user.name, size: 64, }); const gravatarUrl = `https://www.gravatar.com/avatar/${md5(user.email)}?d=404`; return `${user.name}`; } ``` Because the fallback is seed-driven, the same user always gets the same generated avatar when their Gravatar is missing — no cache-busting flicker. ## Theming (light/dark) Pass a different palette per theme. The seed stays the same, so each user keeps their identity but the colors adapt. ```ts const LIGHT_PALETTE = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7"]; const DARK_PALETTE = ["#B24747", "#2F8782", "#2E7DA0", "#6B9A85", "#B39E5F"]; function themedAvatar(seed: string, theme: "light" | "dark") { return createAvatar(geometric, { seed, size: 48, colors: theme === "dark" ? DARK_PALETTE : LIGHT_PALETTE, }); } ``` Pair this with a CSS `prefers-color-scheme` listener so the avatar rerenders when the system theme changes. ## Caching For very large lists (tables, timelines), you may want to cache the SVG string instead of regenerating it on every render. ```ts const cache = new Map(); function cachedAvatar(seed: string): string { if (!cache.has(seed)) { cache.set(seed, createAvatar(initials, { seed }).toDataUri()); } return cache.get(seed)!; } ``` Cache by a composite key if options vary by call site: ```ts const key = JSON.stringify({ seed, size, square }); ``` Most React apps don't need this — `useMemo` inside the `Avatar` component already deduplicates per component instance. ## Server-side rendering `createAvatar` returns a pure string — no DOM access, no browser APIs. It runs fine in Node, Bun, Deno, or any edge runtime. ```ts // Next.js server component, Express handler, Remix loader, etc. export async function getUserAvatar(userId: string): Promise { const avatar = createAvatar(initials, { seed: userId, size: 64 }); return avatar.svg; // inline SVG — no data URI needed server-side } ``` Inlining the raw `svg` string (rather than the data URI) is slightly smaller on the wire and plays nicely with streaming renderers. One caveat: `toDataUri()` uses `btoa`, which exists in Node 16+ globally. For older Node, swap in `Buffer.from(svg).toString("base64")` yourself. ## Using the same avatar across platforms All 11 styles are pure `createAvatar` implementations, so the SVG you generate in a Next.js server component is byte-identical to the one produced by the React component in the browser, the Vue component on the next page, or the web component inside a third-party embed. The seed + style + options is the ground truth. This means you can safely hash+store generated SVGs server-side and serve them as static PNGs (e.g. via `sharp`) without worrying about platform-specific rendering differences. --- # Create a Custom Avatar Style Source: https://avatar-generator.hugoogb.dev/guides/custom-styles/ An "avatar style" is just an object that implements the `Style` contract from `@avatar-generator/core`. You can use styles privately in your app or publish them as reusable npm packages. This guide walks through building one from scratch. ## The Style\ contract A style needs two things: a `name` and a `create(options)` method that returns an `AvatarResult`. ```ts interface Style { name: string; create(options: T): AvatarResult; } interface AvatarResult { svg: string; toDataUri(): string; } ``` Your `create` function receives the merged options (defaults already applied by `createAvatar`) and must return an SVG string plus a helper that serializes it to a data URI. ## The tools core gives you You almost never need to handcraft SVG from scratch — core ships the primitives every bundled style uses: | Helper | What it does | | ----------------------------- | ----------------------------------------------------------------------- | | `createRandom(seed)` | Deterministic RNG: `next`, `int`, `pick`, `bool`, `shuffle` | | `buildSvg(content, opts, bg)` | Wraps your SVG body in the right viewBox, clip path, border, transforms | | `escapeXml(text)` | Escapes text for use inside SVG `` nodes | | `DEFAULT_COLORS` | Vivid 10-color palette used as a fallback | | `SKIN_TONES`, `EYE_COLORS` | Curated palettes for face-based styles | | `validateOption(...)` | Throws a descriptive error if a string option is not in a known list | ## Minimal example — a "checker" style This style renders a two-colour checkerboard based on the seed. ```ts interface CheckerOptions extends AvatarOptions { gridSize?: number; } export const checker: Style = { name: "checker", create(options: CheckerOptions): AvatarResult { const size = options.size ?? 64; const gridSize = options.gridSize ?? 4; const random = createRandom(options.seed); const palette = options.colors ?? DEFAULT_COLORS; const a = random.pick(palette); const b = random.pick(palette.filter((c) => c !== a)); const cell = size / gridSize; let content = ""; for (let row = 0; row < gridSize; row++) { for (let col = 0; col < gridSize; col++) { const fill = (row + col) % 2 === 0 ? a : b; content += ``; } } return buildSvg(content, options, a); }, }; ``` Using it: ```ts const avatar = createAvatar(checker, { seed: "Hugo GB", gridSize: 6 }); document.querySelector("img")!.src = avatar.toDataUri(); ``` ## Literal union options + runtime validation For categorical options, use a literal union type and the `validateOption` helper so both compile-time and runtime reject invalid values. ```ts type CheckerPattern = "classic" | "diagonal" | "dotted"; const PATTERNS: CheckerPattern[] = ["classic", "diagonal", "dotted"]; interface CheckerOptions extends AvatarOptions { pattern?: CheckerPattern; gridSize?: number; } export const checker: Style = { name: "checker", create(options) { validateOption("checker", "pattern", options.pattern, PATTERNS); const random = createRandom(options.seed); const pattern = options.pattern ?? random.pick(PATTERNS); // … render based on pattern }, }; // Export the array so consumers can build UI pickers off it: export { PATTERNS }; ``` ## Determinism checklist Every bundled style in this repo passes the same snapshot test: the same seed and options must produce byte-identical SVG. Things that break that: - `Math.random()` anywhere in `create`. Use `createRandom(options.seed)`. - `Date.now()`, `crypto.randomUUID()`, or any other clock/entropy source. - `Array.sort()` without a comparator on strings with case differences (sort is stable in modern engines, but compare explicitly to be sure). - Generating unique DOM IDs. If you need an id inside the SVG, derive it from the seed rather than from a counter or a random value — that is how core keeps its clip-path ids stable. `buildSvg` already handles this for the wrapper, so you only need it for ids you introduce yourself, such as a `` you reference by `url(#…)`. The repository's own styles are covered by a snapshot test that renders each one from a fixed set of seeds. If you vendor a style into a project, the cheapest equivalent is asserting that two calls with the same seed are equal. ## Packaging your style To publish your style as a reusable npm package, follow the structure of `@avatar-generator/style-initials`: ```json { "name": "@your-scope/style-checker", "version": "1.0.0", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { "import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" }, "require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" } }, "./package.json": "./package.json" }, "files": ["dist", "LICENSE", "README.md"], "sideEffects": false, "engines": { "node": ">=18" }, "scripts": { "build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean --target es2020" }, "dependencies": { "@avatar-generator/core": "^3.0.0" } } ``` Key choices, each of which the 2.x releases got wrong and 3.0.0 fixed: - **`"type": "module"` plus a conditional `exports` map.** Plain `tsc` output emits ESM with extensionless relative specifiers, which `import` rejects with `ERR_MODULE_NOT_FOUND` and `require` rejects on the `export` keyword. Only a bundler doing node10-style resolution can load such a package — so it will work in your dev app and fail for whoever installs it. Build with a bundler like [tsup](https://tsup.egoist.dev) that emits real extensions and both formats. - **`files`**, so the tarball carries `dist/` and not `src/` and tsconfigs. - **`sideEffects: false`**, to stay tree-shakeable. - **Type declarations per condition** (`.d.ts` and `.d.cts`), so TypeScript resolves your option types under both `import` and `require`. - **`@avatar-generator/core` as a dependency**, matching the bundled styles. Core is stateless — no singletons, no registry — so a duplicated copy costs bundle size but never correctness. Make it a `peerDependency` instead if you would rather force a single copy and let the consumer own the version. Verify before publishing rather than after. `npx publint` checks the manifest and `npx @arethetypeswrong/cli --pack .` checks that your types resolve under every condition; both are what this repository runs in CI. Until v3, `@avatar-generator/core` declared every style's option type, so a style published by anyone else could not be typed. Each style now owns its own option type and core knows only the `Style` contract — which is exactly what makes a third-party style a first-class one. Once published, users install both packages and use your style exactly like the bundled ones: ```bash pnpm add @avatar-generator/core @your-scope/style-checker ``` ```ts createAvatar(checker, { seed: "user-42", gridSize: 8 }); ``` --- # Generate SVG Avatars in JavaScript Source: https://avatar-generator.hugoogb.dev/guides/manual/ `@avatar-generator/core` gives you one function, `createAvatar(style, options)`, which returns an SVG string. No framework, no DOM, no build step required. ## Basic usage ```ts const avatar = createAvatar(initials, { seed: "Hugo GB", size: 64, }); // The raw SVG markup console.log(avatar.svg); // …or a data URI for an const img = document.createElement("img"); img.src = avatar.toDataUri(); document.body.appendChild(img); ``` The package is plain JavaScript with type declarations alongside it, so the same code works unchanged in a `.js` file — drop the type imports and nothing else changes. `avatar.svg` is a complete `` element as a string. Inline it when you control the surrounding markup — it is smaller than a data URI and styleable with CSS. Use `toDataUri()` when you need something that fits in an `src` attribute. ## Using different styles A style is just an object you pass as the first argument, so switching styles means switching imports. ```ts // One seed, eleven different deterministic results const seed = "user-123"; const all = [initials, geometric, pixels, rings, faces, illustrated, anime, abstract, emoji, animals, gradient].map( (style) => createAvatar(style, { seed }), ); ``` ## Shared options Every style accepts these, whatever it draws: ```ts const avatar = createAvatar(geometric, { seed: "unique-id", // required — drives every choice size: 128, // pixels (default: 64) square: true, // square instead of circle (default: false) transparent: false, // transparent background (default: false) colors: ["#FF6B6B", "#4ECDC4", "#45B7D1"], // palette to pick from border: { width: 2, color: "#333" }, // optional border rotate: 45, // degrees (default: 0) flip: false, // horizontal flip (default: false) scale: 0.9, // scale factor (default: 1) }); ``` `colors` is a palette, not a single background: the style picks from it using the seed, so two users with the same palette still get different colors. ## Style-specific options Each style also owns its own option type, exported from its own package: ```ts ``` In v2 these types lived in `@avatar-generator/core`. They now live in the style that implements them. If you are upgrading, see the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). Anything you leave unset is chosen deterministically from the seed. Setting a value pins it for every seed — useful for a themed set, but it removes that dimension of variety. Categorical options are validated at runtime. Passing a value that is not in the list throws immediately, naming the option and the accepted values, rather than silently rendering something unexpected. ### Initials ```ts createAvatar(initials, { seed: "john.doe@example.com", name: "Hugo GB", // name to take initials from (default: the seed) fontFamily: "Arial", // default: "sans-serif" fontWeight: 700, // default: 600 textColor: "#ffffff", // default: "#fff" }); ``` Splitting `seed` from `name` is the point of this style: seed on the stable user ID so the color never changes, and display whatever name you currently have. ### Geometric ```ts createAvatar(geometric, { seed: "unique-id", gridSize: 5, // default: 5; odd values stay symmetrical padding: 1, // cells of padding around the pattern (default: 1) foregroundColor: "#2C3E50", // default: picked from the palette }); ``` ### Pixels ```ts createAvatar(pixels, { seed: "unique-id", pixelSize: 8, // grid resolution (default: 8) skinTones: ["#FFDBB4"], // default: the SKIN_TONES palette accessories: true, // allow glasses (default: true, 15% chance) featureColor: "#2C1810", // eyes and mouth }); ``` ### Rings ```ts createAvatar(rings, { seed: "unique-id", ringCount: 5, // default: 4 ringGap: 3, // default: 2 segmented: true, // allow pie-slice rings (default: true) dashed: true, // allow dashed rings (default: true) centerStyle: "diamond", // "solid" | "dot" | "ring" | "diamond" | "none" }); ``` ### Faces ```ts createAvatar(faces, { seed: "unique-id", skinTones: ["#FFDBB4"], // default: the SKIN_TONES palette featureColor: "#2C1810", // eyes, mouth, eyebrows eyebrows: true, // default: true (50% chance) ears: true, // default: true (40% chance) nose: true, // default: true (30% chance) hairStyle: "side-swept", // "none" | "flat-top" | "cap" | "side-swept" | "spiky" | "round-top" | "mohawk" | "beanie" eyeStyle: "round", // "dots" | "rectangles" | "lines" | "round" mouthStyle: "rect-smile", // "line" | "rect-smile" | "open-rect" | "zigzag" | "dot" }); ``` Faces has its own vocabulary — `"curly"`, `"happy"` and `"smile"` belong to other styles and will throw here. The values above are the complete lists. ### Illustrated ```ts createAvatar(illustrated, { seed: "unique-id", hairStyle: "afro", // 12 styles eyeStyle: "round", // 8 styles eyebrowStyle: "natural", // 6 styles noseStyle: "button", // 5 styles mouthStyle: "bigSmile", // 8 styles glasses: true, // default: true (20% chance) hat: true, // default: true (10% chance) earrings: true, // default: true (8% chance) facialHair: true, // default: true (15% chance) }); ``` ### Anime ```ts createAvatar(anime, { seed: "unique-id", hairStyle: "twin-tails", // 10 styles eyeStyle: "sparkly", // 8 styles mouthStyle: "cat-mouth", // 6 styles noseStyle: "dot", // "dot" | "line" | "shadow" bangs: true, // default: random (60% chance) ahoge: true, // the stray hair strand (default: random, 40%) blush: true, // default: random (35% chance) accessories: true, // bandaid, headband (default: true) }); ``` ### Abstract ```ts createAvatar(abstract, { seed: "unique-id", composition: "bauhaus", // "mondrian" | "kandinsky" | "bauhaus" shapeCount: 3, // accent shapes in the Kandinsky composition (default: 3) }); ``` ### Emoji ```ts createAvatar(emoji, { seed: "unique-id", expression: "laughing", // "happy" | "laughing" | "cool" | "wink" | "love" // | "sad" | "angry" | "surprised" | "sleepy" | "neutral" faceColor: "#FFD93D", // default: the yellow emoji palette }); ``` ### Animals ```ts createAvatar(animals, { seed: "unique-id", animal: "fox", // "cat" | "dog" | "bear" | "fox" | "panda" | "bunny" | "frog" | "monkey" furTones: ["#C68B59"], // default: earth tones }); ``` ### Gradient ```ts createAvatar(gradient, { seed: "unique-id", direction: "radial", // "linear" | "radial" | "diagonal" pattern: "waves", // "none" | "dots" | "stripes" | "waves" | "grid" colorStops: 3, // 2 or 3 (default: 2) }); ``` ## Building option pickers Each style exports the arrays behind its literal unions, so a settings UI can be generated rather than hand-maintained: ```ts for (const hairStyle of HAIR_STYLES) { renderOption(hairStyle, createAvatar(faces, { seed: "preview", hairStyle })); } ``` ## Determinism The same seed and options always produce the same result: ```ts const a = createAvatar(initials, { seed: "user-123" }); const b = createAvatar(initials, { seed: "user-123" }); a.svg === b.svg; // always true ``` That holds across processes and platforms, not just within one page — a Node server render and a browser render of the same seed produce identical bytes. So you never need to store a generated avatar: the seed is the storage. Seed on something stable, like a user ID. Seeding on an email or display name means the avatar changes when the user does. ## Next - [API Reference](https://avatar-generator.hugoogb.dev/reference/avatar/) — every option, type and exported helper - [Cookbook](https://avatar-generator.hugoogb.dev/guides/cookbook/) — groups, image fallbacks, theming, caching, SSR - [Creating Custom Styles](https://avatar-generator.hugoogb.dev/guides/custom-styles/) — write and publish your own --- # React Avatar Component Source: https://avatar-generator.hugoogb.dev/guides/react/ `@avatar-generator/react` wraps `createAvatar` in a component that renders an `` whose `src` is the generated SVG as a data URI. It works with React 18 and 19. ## Basic usage ```tsx function UserProfile({ user }) { return ; } ``` ## Using different styles The `style` prop takes the style object itself, so a gallery is just a list of imports: ```tsx const STYLES = [ { style: initials, label: "Initials" }, { style: geometric, label: "Geometric" }, { style: pixels, label: "Pixels" }, { style: rings, label: "Rings" }, { style: faces, label: "Faces" }, { style: illustrated, label: "Illustrated" }, { style: anime, label: "Anime" }, { style: abstract, label: "Abstract" }, { style: emoji, label: "Emoji" }, { style: animals, label: "Animals" }, { style: gradient, label: "Gradient" }, ]; function AvatarGallery({ userId }) { const options = { seed: userId, size: 64 }; return (
{STYLES.map(({ style, label }) => ( ))}
); } ``` ## With custom options ```tsx function CustomAvatar({ userId }) { return ( ); } ``` ## TypeScript Import the option type from the style package — in v3 the style owns its own types, not core: ```tsx interface UserAvatarProps { userId: string; userName: string; } function UserAvatar({ userId, userName }: UserAvatarProps) { const options: InitialsOptions = { seed: userId, name: userName, size: 48, fontWeight: 700, }; return ; } ``` `InitialsOptions` and its siblings used to come from `@avatar-generator/core`. They now come from the style package. See the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). `AvatarProps` is exported too, if you need to wrap the component: ```ts ``` ## Props | Prop | Type | Default | Description | | ----------- | ------------------------- | ---------- | --------------------------------- | | `style` | `Style` | (required) | The style object to render with | | `options` | `T extends AvatarOptions` | (required) | Seed and style-specific options | | `alt` | `string` | `"Avatar"` | Alt text for the rendered `` | | `className` | `string` | — | Class applied to the `` | The rendered element is an `` sized from `options.size` (default `64`), so give it a meaningful `alt` — or `alt=""` if the avatar is decorative and the name is already shown as text next to it. ## Memoization The component memoizes generation with `useMemo(…, [style, options])`. Because that compares by identity, an inline object literal creates a new `options` on every render and defeats the memo: ```tsx // Regenerates on every parent render — the object is new each time ``` Usually that is fine: generating an avatar is a little string building, not a network call. For a long list, give each row a stable `options` object by memoizing inside the row component — never inside a `.map()` callback, which would break the rules of hooks: ```tsx function UserRow({ user }) { const options = useMemo(() => ({ seed: user.id, name: user.name, size: 32 }), [user.id, user.name]); return (
  • {user.name}
  • ); } function UserList({ users }) { return (
      {users.map((user) => ( ))}
    ); } ``` If you would rather cache across components entirely, see the caching recipe in the [Cookbook](https://avatar-generator.hugoogb.dev/guides/cookbook/). ## Server-side rendering The component is safe in a React Server Component or during `renderToString`: `createAvatar` touches no browser globals, and the output is an `` with a data URI, so there is nothing to hydrate. If you would rather inline the SVG markup than embed a data URI, call `createAvatar` directly — see the SSR recipe in the [Cookbook](https://avatar-generator.hugoogb.dev/guides/cookbook/). --- # Svelte Avatar Component Source: https://avatar-generator.hugoogb.dev/guides/svelte/ `@avatar-generator/svelte` provides an `Avatar` component that renders an `` from any style. It works with Svelte 4 and Svelte 5; `svelte` is a peer dependency, so it uses whichever version your app pins. The published component is preprocessed to plain JavaScript. In v2 it shipped as ` ``` You can also import from the package root: ```ts ``` Svelte's build tooling resolves the `"svelte"` export condition to the component itself, so both imports work identically. ## Using different styles ```svelte ``` All eleven styles work the same way — see the [Style Gallery](https://avatar-generator.hugoogb.dev/reference/gallery/). ## TypeScript Import the option type from the style package: ```ts const options: InitialsOptions = { seed: "user-123", name: "Hugo GB", fontWeight: 700 }; ``` These types used to live in `@avatar-generator/core`. They now live in the style package that implements them. See the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). ## Props | Prop | Type | Default | Description | | --------- | ------------------------- | ---------- | ------------------------------- | | `style` | `Style` | (required) | The style object to render with | | `options` | `T extends AvatarOptions` | (required) | Seed and style-specific options | | `alt` | `string` | `"Avatar"` | Alt text for the `` | | `class` | `string` | `""` | Class applied to the `` | The component regenerates reactively, so reassigning `style` or `options` re-renders the avatar. ## Server-side rendering Safe in SvelteKit: `createAvatar` returns a string and touches no browser globals, so the avatar renders during SSR with nothing left to hydrate. --- # Vue Avatar Component Source: https://avatar-generator.hugoogb.dev/guides/vue/ `@avatar-generator/vue` provides an `Avatar` component that renders an `` from any style. `vue` is a peer dependency, so it uses the Vue 3 version your app already pins. ## Installation ```bash pnpm add @avatar-generator/core @avatar-generator/vue @avatar-generator/style-initials ``` ## Basic usage ```vue ``` The `style` prop takes the style object itself, so import it into the script block and bind it — it is not a string name. ## Using different styles ```vue ``` All eleven styles work the same way — see the [Style Gallery](https://avatar-generator.hugoogb.dev/reference/gallery/). ## TypeScript Import the option type from the style package: ```vue ``` These types used to live in `@avatar-generator/core`. They now live in the style package that implements them. See the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). ## Props | Prop | Type | Default | Description | | --------- | ------------------------- | ---------- | ------------------------------- | | `style` | `Style` | (required) | The style object to render with | | `options` | `T extends AvatarOptions` | (required) | Seed and style-specific options | | `alt` | `string` | `"Avatar"` | Alt text for the `` | | `class` | `string` | `""` | Class applied to the `` | ## Reactivity The SVG is generated inside a `computed`, so it is recalculated only when `style` or `options` change. Passing a `ref` or a `reactive` object gives you automatic updates: ```vue ``` ## Server-side rendering Safe in Nuxt and any other Vue SSR setup — `createAvatar` returns a string and touches no browser globals, and the component renders a plain `` with a data URI, so there is nothing to hydrate. --- # Avatar Web Component Source: https://avatar-generator.hugoogb.dev/guides/web-component/ `@avatar-generator/web-component` ships a standards-based custom element, so you can drop an avatar into any HTML page with no framework. It works equally well inside React, Vue, Svelte, Solid, or anything else that can set a DOM property. ## Installation ```bash pnpm add @avatar-generator/core @avatar-generator/web-component @avatar-generator/style-initials ``` ## Basic usage Importing the package auto-registers ``. Set the JavaScript properties `styleImpl` and `options` on the element: ```ts const el = document.createElement("avatar-generator"); el.styleImpl = initials; el.options = { seed: "Hugo GB", size: 64 }; el.setAttribute("alt", "Hugo GB"); document.body.append(el); ``` Every `HTMLElement` already has a `style` property for inline CSS. Overriding it would break the platform, so the avatar style goes on `styleImpl`. Both it and `options` must be set as JS properties, not attributes — a `Style` is an object, and objects do not survive stringification into an attribute. Setting `styleImpl` or `options` triggers an immediate re-render. Nothing renders until both are set. ## In a plain HTML page ```html ``` ## Custom tag name If `` collides with something in your app, register the element under another name: ```ts register("my-avatar"); const el = document.createElement("my-avatar"); el.styleImpl = initials; el.options = { seed: "Hugo GB" }; document.body.append(el); ``` The extra name is registered alongside ``, not instead of it, and `register` is safe to call more than once — a name that already exists is ignored. `register(tagName)` could never succeed before v3. Importing the package binds `AvatarElement` to ``, and the registry allows one tag name per constructor, so any custom name threw `NotSupportedError`. Additional names now get their own subclass. ## Properties and attributes | Name | Kind | Default | Description | | ----------- | --------- | ---------- | ------------------------------------------------------------ | | `styleImpl` | property | (required) | The avatar `Style` object — must be set as a JS property | | `options` | property | (required) | Avatar options for that style — must be set as a JS property | | `alt` | attribute | `"Avatar"` | Alt text for the internal `` | ## Styling The element renders its `` inside an open shadow root, so page CSS does not reach inside it. Size and position the host element itself: ```css avatar-generator { display: inline-block; border-radius: 50%; overflow: hidden; } ``` The shadow root is open, so `el.shadowRoot` is reachable if you need the `` directly. ## Server-side rendering Importing this package during a server render is a no-op: the element extends a stand-in when there is no DOM, and `register()` returns early when there is no custom element registry. Importing it from a Next.js, Nuxt, Astro or SvelteKit server component is safe, and the element upgrades in the browser as usual. In v2 this package threw `ReferenceError: HTMLElement is not defined` the moment it was imported on a server — before any of your own code ran. If you hit that, upgrade; see the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). There is no declarative shadow DOM output, so the avatar itself appears on the client. If you need the avatar in the server-rendered HTML, call `createAvatar` directly and inline `avatar.svg` — see the SSR recipe in the [Cookbook](https://avatar-generator.hugoogb.dev/guides/cookbook/). --- # Avatar Generator API Reference Source: https://avatar-generator.hugoogb.dev/reference/avatar/ Everything on this page describes **v3.x**, the current and only supported release line. See [Versions & Support](https://avatar-generator.hugoogb.dev/reference/versioning/). ## createAvatar The main function for generating avatars. ```ts const avatar = createAvatar(initials, { seed: "Hugo GB" }); ``` ### Parameters | Parameter | Type | Description | | --------- | ------------------------- | ----------------------- | | `style` | `Style` | The avatar style to use | | `options` | `T extends AvatarOptions` | Style-specific options | ### Returns | Property | Type | Description | | ------------- | -------------- | ------------------------------------- | | `svg` | `string` | The generated SVG string | | `toDataUri()` | `() => string` | Returns a data URI for use in img src | ## Common Options All styles accept these base options: | Option | Type | Default | Description | | ------------- | ---------------------------------- | --------------- | ---------------------------------- | | `seed` | `string` | (required) | Seed for deterministic generation | | `size` | `number` | `64` | Avatar size in pixels | | `colors` | `string[]` | (style default) | Custom color palette | | `square` | `boolean` | `false` | Use square shape instead of circle | | `transparent` | `boolean` | `false` | Make background transparent | | `border` | `{ width: number, color: string }` | - | Border configuration | | `rotate` | `number` | `0` | Rotation in degrees | | `flip` | `boolean` | `false` | Horizontal flip | | `scale` | `number` | `1` | Scale factor | ## Style-Specific Options Each style owns its option type and exports it from its own package — not from `@avatar-generator/core`, which declares only the style contract itself: `AvatarOptions`, `Style`, `Random`, `AvatarResult`, and the deprecated `LegacyAvatarOptions`. ```ts ``` That is what lets you publish a style of your own without core needing to know it exists. See [Creating Custom Styles](https://avatar-generator.hugoogb.dev/guides/custom-styles/). In v2 these types were declared by `@avatar-generator/core`. Update the import path when you upgrade — the types themselves are unchanged. See the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). Options you leave unset are chosen deterministically from the seed. Options listed with a fixed set of values are validated at runtime: passing anything else throws an `Error` naming the style, the option and the accepted values, rather than silently falling back to a random choice. Each style also exports the arrays behind its literal unions — `HAIR_STYLES`, `EYE_STYLES`, `MOUTH_STYLES`, `CENTER_STYLES`, `COMPOSITIONS`, `EXPRESSIONS`, `ANIMALS`, `DIRECTIONS`, `PATTERNS` — so a picker UI can be generated from them instead of hand-maintained. ### InitialsOptions For `@avatar-generator/style-initials`: | Option | Type | Default | Description | | ------------ | -------- | -------------- | ----------------------------- | | `name` | `string` | `seed` | Name to extract initials from | | `fontFamily` | `string` | `"sans-serif"` | Font family | | `fontWeight` | `number` | `600` | Font weight | | `textColor` | `string` | `"#fff"` | Text color | ### GeometricOptions For `@avatar-generator/style-geometric` (Identicon): | Option | Type | Default | Description | | ----------------- | -------- | -------------- | ---------------------------------------- | | `gridSize` | `number` | `5` | Grid size (odd recommended for symmetry) | | `padding` | `number` | `1` | Padding cells around the pattern | | `foregroundColor` | `string` | (from palette) | Override foreground color | ### PixelsOptions For `@avatar-generator/style-pixels` (Pixel Faces): | Option | Type | Default | Description | | -------------- | ---------- | ------------ | -------------------------------------------- | | `pixelSize` | `number` | `8` | Pixel grid size | | `skinTones` | `string[]` | `SKIN_TONES` | Custom skin tone palette | | `accessories` | `boolean` | `true` | Enable accessories like glasses (15% chance) | | `featureColor` | `string` | `"#2C1810"` | Override eye/mouth color | ### RingsOptions For `@avatar-generator/style-rings`: | Option | Type | Default | Description | | ------------- | --------- | --------- | ---------------------------------------------------------------------- | | `ringCount` | `number` | `4` | Number of rings | | `ringGap` | `number` | `2` | Gap between rings | | `segmented` | `boolean` | `true` | Allow segmented pie-slice rings | | `dashed` | `boolean` | `true` | Allow dashed rings | | `centerStyle` | `string` | `"solid"` | Center decoration: `"solid"`, `"dot"`, `"ring"`, `"diamond"`, `"none"` | ### FacesOptions For `@avatar-generator/style-faces`: | Option | Type | Default | Description | | -------------- | ---------- | ------------ | ---------------------------------------------------------------------------------------------------------------- | | `skinTones` | `string[]` | `SKIN_TONES` | Custom skin tone palette | | `featureColor` | `string` | `"#2C1810"` | Override feature color | | `eyebrows` | `boolean` | `true` | Enable eyebrows (50% chance) | | `ears` | `boolean` | `true` | Enable ears (40% chance) | | `nose` | `boolean` | `true` | Enable nose (30% chance) | | `mouthStyle` | `string` | (random) | Override mouth: `"line"`, `"rect-smile"`, `"open-rect"`, `"zigzag"`, `"dot"` | | `eyeStyle` | `string` | (random) | Override eyes: `"dots"`, `"rectangles"`, `"lines"`, `"round"` | | `hairStyle` | `string` | (random) | Override hair: `"none"`, `"flat-top"`, `"cap"`, `"side-swept"`, `"spiky"`, `"round-top"`, `"mohawk"`, `"beanie"` | ### IllustratedOptions For `@avatar-generator/style-illustrated`: | Option | Type | Default | Description | | -------------- | ---------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `skinTones` | `string[]` | `SKIN_TONES` | Custom skin tone palette | | `eyeColors` | `string[]` | `EYE_COLORS` | Custom eye color palette | | `hairStyle` | `string` | (random) | Override hair (12 styles): `"bald"`, `"buzz"`, `"short"`, `"medium"`, `"long"`, `"curly"`, `"wavy"`, `"mohawk"`, `"afro"`, `"ponytail"`, `"bangs"`, `"sidepart"` | | `eyeStyle` | `string` | (random) | Override eyes (8 styles): `"round"`, `"almond"`, `"narrow"`, `"wide"`, `"sleepy"`, `"winking"`, `"looking"`, `"glasses"` | | `eyebrowStyle` | `string` | (random) | Override eyebrows (6 styles): `"natural"`, `"thick"`, `"thin"`, `"raised"`, `"furrowed"`, `"unibrow"` | | `noseStyle` | `string` | (random) | Override nose (5 styles): `"small"`, `"pointed"`, `"round"`, `"long"`, `"button"` | | `mouthStyle` | `string` | (random) | Override mouth (8 styles): `"smile"`, `"bigSmile"`, `"neutral"`, `"frown"`, `"open"`, `"smirk"`, `"tongue"`, `"teeth"` | | `glasses` | `boolean` | `true` | Enable glasses (20% chance, 3 types) | | `hat` | `boolean` | `true` | Enable hat (10% chance, 3 types) | | `earrings` | `boolean` | `true` | Enable earrings (8% chance) | | `facialHair` | `boolean` | `true` | Enable facial hair (15% chance, 3 types) | ### AnimeOptions For `@avatar-generator/style-anime`: | Option | Type | Default | Description | | ------------- | ---------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `skinTones` | `string[]` | `SKIN_TONES` | Custom skin tone palette | | `eyeColors` | `string[]` | `EYE_COLORS` | Custom eye color palette | | `hairStyle` | `string` | (random) | Override hair (10 styles): `"short-spiky"`, `"medium-messy"`, `"long-straight"`, `"twin-tails"`, `"ponytail"`, `"side-swept"`, `"wild"`, `"bob"`, `"hime-cut"`, `"shaggy"` | | `eyeStyle` | `string` | (random) | Override eyes (8 styles): `"normal"`, `"sparkly"`, `"determined"`, `"gentle"`, `"cat"`, `"half-closed"`, `"closed-happy"`, `"surprised"` | | `mouthStyle` | `string` | (random) | Override mouth (6 styles): `"small-smile"`, `"open-small"`, `"cat-mouth"`, `"line"`, `"pout"`, `"grin"` | | `noseStyle` | `string` | (random) | Override nose (3 styles): `"dot"`, `"line"`, `"shadow"` | | `expression` | `string` | — | Reserved for future expression overrides; currently has no effect | | `bangs` | `boolean` | (random, 60%) | Enable bangs over forehead | | `ahoge` | `boolean` | (random, 40%) | Enable ahoge hair strand on top | | `blush` | `boolean` | (random, 35%) | Enable blush on cheeks | | `accessories` | `boolean` | `true` | Enable accessories (bandaid 5%, headband 8%) | ### AbstractOptions For `@avatar-generator/style-abstract`: | Option | Type | Default | Description | | ------------- | -------- | -------- | -------------------------------------------------------------- | | `composition` | `string` | (random) | Override composition: `"mondrian"`, `"kandinsky"`, `"bauhaus"` | | `shapeCount` | `number` | `3` | Number of accent shapes in the Kandinsky composition | ### EmojiOptions For `@avatar-generator/style-emoji`: | Option | Type | Default | Description | | ------------ | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `expression` | `string` | (random) | Override expression: `"happy"`, `"laughing"`, `"cool"`, `"wink"`, `"love"`, `"sad"`, `"angry"`, `"surprised"`, `"sleepy"`, `"neutral"` | | `faceColor` | `string` | (random) | Override the face fill color | ### AnimalsOptions For `@avatar-generator/style-animals`: | Option | Type | Default | Description | | ---------- | ---------- | ------------- | ------------------------------------------------------------------------------------------------ | | `animal` | `string` | (random) | Override animal: `"cat"`, `"dog"`, `"bear"`, `"fox"`, `"panda"`, `"bunny"`, `"frog"`, `"monkey"` | | `furTones` | `string[]` | (earth tones) | Custom fur palette | ### GradientOptions For `@avatar-generator/style-gradient`: | Option | Type | Default | Description | | ------------ | -------- | -------- | --------------------------------------------------------------------- | | `direction` | `string` | (random) | Override direction: `"linear"`, `"radial"`, `"diagonal"` | | `pattern` | `string` | (random) | Overlay pattern: `"none"`, `"dots"`, `"stripes"`, `"waves"`, `"grid"` | | `colorStops` | `number` | `2` | Number of color stops in the gradient (2 or 3) | ## Utilities ### createRandom Creates a deterministic random number generator from a seed string. ```ts const random = createRandom("my-seed"); random.next(); // Float between 0 and 1 random.int(0, 10); // Integer between 0 and 9 random.pick(["a", "b"]); // Random item from array random.bool(0.7); // Boolean with 70% true probability random.shuffle([1, 2, 3]); // Shuffle array in place ``` ### DEFAULT_COLORS The default color palette used by styles: ```ts // ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7", // "#DDA0DD", "#98D8C8", "#F7DC6F", "#BB8FCE", "#85C1E9"] ``` ### SKIN_TONES Skin tone palette for face-based styles (Pixel Faces, Faces, Illustrated, Anime): ```ts // ["#FFDBB4", "#EAC086", "#C68B59", "#A0674B", "#8D5524", "#613915"] ``` ### EYE_COLORS Eye color palette for the Illustrated and Anime styles: ```ts // ["#634E34", "#2E536F", "#3D6B45", "#89724B", "#3B3024"] ``` ### validateOption Throws if a categorical option is not one of the accepted values. Does nothing when the value is `undefined`, since absence means "pick from the seed". Style packages call it on every literal-union option; custom styles should too. ```ts validateOption("checker", "pattern", options.pattern, PATTERNS); // Error: [@avatar-generator/style-checker] Invalid pattern: "wobbly". // Expected one of: "classic", "diagonal", "dotted". ``` ### SVG utilities Low-level building blocks. `buildSvg` is the only one most styles need; the rest are exported for styles that assemble their own wrapper. ```ts buildSvg, buildTransform, createBackground, createBorder, createCircleClip, createSquareClip, createSvgOpen, escapeXml, wrapWithTransform, } from "@avatar-generator/core"; // buildSvg(content, options, backgroundColor) Complete SVG: viewBox, clip, background, border, transform // buildTransform(options) The transform attribute for rotate/flip/scale // createBackground(size, color, transparent) Background rect // createBorder(size, width, color, square) Border element // createCircleClip(id, size) Circular clip path // createSquareClip(id, size) Square clip path // createSvgOpen(size) Opening tag // escapeXml(text) Escapes text for SVG nodes // wrapWithTransform(content, options) Wraps content in a transform group ``` Together with `createAvatar` and the deprecated `createAvatarElement`, the utilities above are everything `@avatar-generator/core` exports at runtime. Anything not listed — the seed hash behind clip-path ids, for instance — is internal and may change in a minor release. ## Types `@avatar-generator/core` declares five types and no more: `AvatarOptions` (the [common options](#common-options) above), `Style`, `AvatarResult`, `Random`, and the deprecated `LegacyAvatarOptions`. Everything style-specific lives in the style's own package. ### Style Interface ```ts interface Style { name: string; create(options: T): AvatarResult; } ``` ### AvatarResult ```ts interface AvatarResult { svg: string; toDataUri(): string; } ``` ### Random ```ts interface Random { next(): number; int(min: number, max: number): number; pick(array: T[]): T; bool(probability?: number): boolean; shuffle(array: T[]): T[]; } ``` ### LegacyAvatarOptions The v1 options shape, kept only for `createAvatarElement` below. ```ts interface LegacyAvatarOptions { name: string; backgroundColor?: string | string[]; gradientDirection?: "vertical" | "horizontal"; textColor?: string; fontSize?: string; shape?: "circle" | "square"; width?: string; height?: string; tooltip?: boolean; additionalClasses?: string; } ``` ## Deprecated: the v1 element API `createAvatarElement` is the original v1 function. It builds a DOM `
    ` with CSS-styled initials — not deterministic SVG, and not a style. It survives so a v1 codebase can migrate incrementally. ```ts const element = createAvatarElement({ name: "Hugo GB", backgroundColor: "#4CAF50" }); document.body.appendChild(element); ``` Deprecated, and not a supported path for new code. It calls `document.createElement`, so it throws during server-side rendering; it ignores every style and every option on this page; and it will be removed in a future major. Use `createAvatar` with a style instead — see the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). --- # Avatar Configurator Source: https://avatar-generator.hugoogb.dev/reference/configurator/ Adjust the controls to see how each option changes the generated avatar. The snippet below the preview updates in real time — copy it straight into your code. The preview uses simplified renderers matching each style's shape. Install the actual packages for the full output: - `@avatar-generator/core` - `@avatar-generator/style-` See [Installation](https://avatar-generator.hugoogb.dev/get-started/installation/) for setup and the [Style Gallery](https://avatar-generator.hugoogb.dev/reference/gallery/) to compare styles side by side. --- # Avatar Style Gallery Source: https://avatar-generator.hugoogb.dev/reference/gallery/ Every style in `@avatar-generator`, rendered from the same seed set so you can compare them directly. Each row uses identical seeds — the differences come entirely from the style. ## Choosing a style - **Initials / Geometric / Rings / Gradient / Abstract** — no personal features; good for organizations, teams, and abstract identity - **Pixels / Faces / Illustrated / Anime / Emoji / Animals** — face or character-based; good when you want an avatar that reads as a "person" or mascot All 11 styles share the same base options (`seed`, `size`, `colors`, `square`, `transparent`, `border`, `rotate`, `flip`, `scale`). See the [API Reference](https://avatar-generator.hugoogb.dev/reference/avatar/) for style-specific options. --- # Migrate to @avatar-generator v3 Source: https://avatar-generator.hugoogb.dev/reference/migration/ **v3.0.0 is the current release and the only one you should install.** This page covers both upgrade paths: from v2 (the style-based API, unchanged in shape) and from v1 (the original DOM-element API). Neither line is supported. v2.0.0 is on npm, but its tarballs cannot be loaded by Node at all — they ship ESM without `"type": "module"` and with extensionless relative imports, so only a bundler doing node10-style resolution can resolve them. Versions 2.1.0 through 2.6.0 were never published. See [Versions & Support](https://avatar-generator.hugoogb.dev/reference/versioning/) for the full picture. ## Which path applies to you | You are on | Effort | | ------------------------------------- | ---------------------------------------------------------------- | | v2.x (`createAvatar(style, options)`) | [Small](#upgrading-from-v2) — two import changes at most | | v1.x (`createAvatar({ name })`) | [Larger](#upgrading-from-v1) — the whole API changed | | Nothing yet | Skip this page, go to [Installation](https://avatar-generator.hugoogb.dev/get-started/installation/) | ## Upgrading from v2 Avatar output is byte-identical between 2.x and 3.0.0 — no avatar your users already have will change. Only two things moved, and both are compile-time. ### 1. Style option types moved into their style packages In v2, `@avatar-generator/core` declared every style's option type — `FacesOptions`, `AnimeOptions`, `GradientOptions` and 26 more. Core therefore had to know about all eleven styles, and a style published by anyone else could not be typed at all. Each style now owns and exports its own option type. ```diff - import type { FacesOptions } from "@avatar-generator/core"; + import type { FacesOptions } from "@avatar-generator/style-faces"; ``` The types themselves are unchanged, and the style packages already re-exported them in v2 — so if you were already importing from the style package, there is nothing to do. Core now declares only `AvatarOptions`, `Style`, `Random`, `AvatarResult` and the deprecated `LegacyAvatarOptions`. This is what lets you publish a style of your own; see [Creating Custom Styles](https://avatar-generator.hugoogb.dev/guides/custom-styles/). ### 2. The Angular component is standalone `@avatar-generator/angular` is now built with ng-packagr as a real Angular Package Format library (FESM2022, partial Ivy), so AOT builds can consume it. Previously it shipped plain `tsc` output, which made a consumer's AOT build fall back to the JIT compiler and fail with _"needs to be compiled using the JIT compiler, but '@angular/compiler' is not available"_. `AvatarComponent` is also `standalone: true`, because components have been standalone by default since Angular 19 and declaring one in an NgModule is an error: ```diff @Component({ + imports: [AvatarComponent], template: ``, }) ``` `AvatarModule` still works and now re-exports the standalone component, so existing `imports: [AvatarModule]` code needs no change. Supported Angular versions widen to `^17 || ^18 || ^19 || ^20 || ^21`. Angular Package Format is ESM-only — Angular dropped CommonJS and UMD output in v13 — so `@avatar-generator/angular` has no `require()` entry point. Every other package ships both ESM and CommonJS. ### Everything else in 3.0.0 is a fix These need no action from you, but they are why upgrading is worth it: - Published packages are loadable from Node at all, as both ESM and CommonJS - `@avatar-generator/web-component` no longer throws `ReferenceError: HTMLElement is not defined` when imported during a Next.js, Nuxt, Astro or SvelteKit server render - `register(tagName)` in the web component works; it previously always threw `NotSupportedError` - `@avatar-generator/svelte` ships a preprocessed component, so it compiles without a preprocessor configured - Tarballs contain only `dist/` and the licence, not `src/` and tsconfigs ## Upgrading from v1 v1 generated an HTML `
    ` with CSS-styled initials. v2 replaced it with deterministic SVG and pluggable styles, and v3 keeps that API unchanged. If you are still on v1, you are moving to the current API in one step. | v1 | v3 | | ---------------------- | --------------------------------- | | HTML element output | SVG string output | | Single initials style | 11 pluggable style packages | | `name` prop | `seed` prop | | Styles bundled in core | Separate, tree-shakeable packages | ### Installation A style package is no longer optional — core renders nothing on its own. ```sh npm install @avatar-generator/core @avatar-generator/style-initials ``` ### Core package **v1:** ```ts const element = createAvatar({ name: "Hugo GB", backgroundColor: "#4CAF50", textColor: "#fff", fontSize: "48px", shape: "circle", }); document.body.appendChild(element); ``` **v3:** ```ts const avatar = createAvatar(initials, { seed: "Hugo GB", size: 100, textColor: "#fff", }); // SVG output — use as an image src const img = document.createElement("img"); img.src = avatar.toDataUri(); document.body.appendChild(img); // …or insert the SVG markup directly const div = document.createElement("div"); div.insertAdjacentHTML("beforeend", avatar.svg); document.body.appendChild(div); ``` ### React **v1:** ```tsx ; ``` **v3:** ```tsx ; ``` ### Angular **v1:** ```html ``` **v3** — note the `imports: [AvatarComponent]`, which v1 and v2 did not need: ```ts @Component({ selector: "app-user-avatar", imports: [AvatarComponent], template: ``, }) export class UserAvatarComponent { initialsStyle = initials; options = { seed: "Hugo GB", size: 64 }; } ``` ### Option mapping | v1 option | v3 equivalent | Notes | | ----------------- | ------------------- | ------------------------------------------- | | `name` | `seed` | Drives generation | | `name` | `options.name` | For the displayed initials (initials style) | | `backgroundColor` | `colors` | Now an array — a palette to pick from | | `textColor` | `options.textColor` | Initials style only | | `fontSize` | — | Derived from `size` | | `shape: "circle"` | `square: false` | The default | | `shape: "square"` | `square: true` | | | `width`/`height` | `size` | Single dimension; avatars are square | | `tooltip` | — | Set `title` on your own wrapper element | ### The v1 API is still present, but deprecated `createAvatarElement` is the original v1 function, kept so you can migrate incrementally rather than in one commit: ```ts // Still works. Deprecated — DOM-only, not deterministic SVG, and will be // removed in a future major. const element = createAvatarElement({ name: "Hugo GB", backgroundColor: "#4CAF50" }); ``` `createAvatarElement` calls `document.createElement`, so it throws during server-side rendering. `createAvatar` returns a plain string and runs anywhere. Treat the legacy function as a temporary bridge, not a supported path. ## After upgrading - Skim the [API Reference](https://avatar-generator.hugoogb.dev/reference/avatar/) — every base and style option - Compare the eleven styles in the [Style Gallery](https://avatar-generator.hugoogb.dev/reference/gallery/) - Check the [Cookbook](https://avatar-generator.hugoogb.dev/guides/cookbook/) for groups, fallbacks, theming, SSR --- # Versions & Support Source: https://avatar-generator.hugoogb.dev/reference/versioning/ ## Supported versions | Line | Status | Notes | | ---- | ------------- | --------------------------------------------------------- | | 3.x | **Supported** | Current. Install this. | | 2.x | Unsupported | Only `2.0.0` reached npm, and it cannot be loaded by Node | | 1.x | Unsupported | Different API; superseded by the 2.0 rewrite | They are not merely old — they do not work outside a bundler that still does node10-style module resolution. Install the 3.x line. ## Why v2 should not be used The 2.x tarballs on npm are broken in a way that a green build does not reveal: - Every package shipped ESM output without `"type": "module"`, so `require()` failed on the `export` keyword. - `tsc` emitted extensionless relative specifiers (`from "./random"`), so `import` failed with `ERR_MODULE_NOT_FOUND`. Only a bundler resolving extensionless imports could load them, which is why the repository's own playgrounds never caught it. Packages are now built with tsup and ship ESM + CommonJS with correct extensions, a conditional `exports` map, and per-condition type declarations. The catalogue was also incomplete. Versions 2.1.0 through 2.6.0 — which added the abstract, emoji, animals and gradient styles and the Vue, Svelte and web component wrappers — were developed but **never published**. npm only ever held `2.0.0` of `core`, `style-initials` and `react`. 3.0.0 is the first release that actually carries all seventeen packages. ## Why v1 should not be used v1 had a different API altogether: `createAvatar({ name })` returned a DOM element with CSS-styled initials, there was one style, and nothing was deterministic SVG. The 2.0 rewrite replaced it, and v3 keeps that API. The v1 entry point survives in core as `createAvatarElement`, deprecated, so a v1 codebase can migrate incrementally. It calls `document.createElement`, so it throws during server-side rendering. See the [Migration Guide](https://avatar-generator.hugoogb.dev/reference/migration/). ## What the version number covers All seventeen packages — `@avatar-generator/core`, the eleven style packages and the five framework wrappers — are released together from one fixed version group. `@avatar-generator/react@3.0.0` is always meant to be used with `@avatar-generator/core@3.0.0` and `@avatar-generator/style-faces@3.0.0`. They had drifted to 2.0.0 / 2.4.0 / 2.5.0 before 3.0.0 aligned them, so a matched set is a deliberate guarantee rather than a coincidence. Releases follow [semantic versioning](https://semver.org), with one clarification specific to a deterministic avatar library: The whole point of this library is that a given seed always yields the same avatar. A change to what a style draws would silently change every existing user's avatar, so it is treated as breaking and ships only in a major. 3.0.0 itself changed nothing visual — the SVG snapshots are byte-identical to 2.x. ## Requirements | Requirement | Value | | -------------- | -------------------------------------------------------------------- | | Node.js | 18 or newer | | Module formats | ESM and CommonJS (`@avatar-generator/angular` is ESM-only) | | TypeScript | Declarations ship per condition; no `skipLibCheck` workaround needed | | Runtime deps | None — core has no dependencies | Framework wrappers declare their framework as a peer dependency: | Package | Peer range | | --------------------------------- | ------------------------------------------------------- | | `@avatar-generator/react` | `react@^18 \|\| ^19` | | `@avatar-generator/vue` | `vue@^3` | | `@avatar-generator/svelte` | `svelte@^4 \|\| ^5` | | `@avatar-generator/angular` | `@angular/core@^17 \|\| ^18 \|\| ^19 \|\| ^20 \|\| ^21` | | `@avatar-generator/web-component` | none — standard custom element | `@avatar-generator/angular` ships Angular Package Format (FESM2022, partial Ivy), which Angular has required of libraries since v13 and which is ESM-only, so that package has no `require()` entry point. ## Pinning a matched set Because the packages move together, install them at the same version: ```sh npm install @avatar-generator/core@3 @avatar-generator/style-initials@3 @avatar-generator/react@3 ``` Style packages depend on core directly, so a package manager will pull a compatible core for you — but you import `createAvatar` from core yourself, so declare it explicitly rather than relying on a transitive install. ## Verification that ships with each release Every published tarball is built and checked in CI before it goes out: - `publint --strict` on the manifest and `attw` on type resolution - A smoke test that packs all seventeen packages, installs the tarballs into a throwaway project, loads each from real Node as both ESM and CommonJS, generates an avatar from every style, and compiles the published Svelte component with no preprocessor configured - Publication only from a version tag that matches every package's version, with npm provenance The 3.0.0 packages are an exception: they were published by hand rather than by the release workflow, so they have no npm provenance attestation. These exist because 2.x shipped without them. See [Contributing](https://github.com/hugoogb/avatar-generator/blob/develop/CONTRIBUTING.md) for how to run them locally.