Creating a New Avatar Style
Relevant source files
The following files were used as context for generating this wiki page:The @nextorders/avatar package is designed with an extensible architecture that allows developers to define and integrate their own custom avatar styles. The default style provided is open-peeps, which is based on the "Open Peeps" illustration library. This document outlines the process and architecture for creating a new, custom avatar style that can be used with the core avatar generation system.
A "Style" is a self-contained module that provides the logic for generating the core SVG content. It defines the available components, how they are selected based on input options, and how they are assembled into a final SVG body. The core system then takes this SVG body and applies common transformations like backgrounds, scaling, and rotation.
Core Architecture
The avatar generation process is managed by a core function, createAvatar, which accepts a style object and a set of options. The style object is the central piece of the custom style implementation.
Sources: packages/avatar/src/core/index.ts:10-13
Avatar Generation Flow
The following diagram illustrates the high-level data flow when generating an avatar. The "Style" module is responsible for the initial SVG creation, which is then enhanced by the core system.
This diagram shows how the main createAvatar function orchestrates the process, calling the custom style's create method and then applying further SVG transformations.
Sources: packages/avatar/src/index.ts:15, packages/avatar/src/core/index.ts:10-58
The Style Object
A style is defined by an object that conforms to the Style type. It must contain a create method and can optionally include a schema.
| Property | Type | Description |
|---|---|---|
create | StyleCreate<O> | A function that generates the base SVG for the avatar. It receives a PRNG instance and options, and returns the SVG attributes and body. |
schema | StyleSchema | An optional JSON Schema object that defines the configurable options for this style. |
Sources: packages/avatar/src/core/index.ts:11, packages/avatar/src/open-peeps/index.ts:15, 203
Implementing a Style
To create a new style, you must implement the Style interface. The open-peeps style serves as the primary reference implementation.
Sources: packages/avatar/src/open-peeps/index.ts
The create Function
The create function is the core of any style. It is responsible for generating the initial SVG content based on the provided options.
// packages/avatar/src/open-peeps/index.ts:15-19
export const create: StyleCreate<OpenPeepsOptions> = ({ prng, options }) => {
const components = getComponents({ prng, options });
const colors = getColors({ prng, options });
// ... function body
};
The function receives an object with two properties:
prng: A seeded pseudo-random number generator instance. This should be used for any random selections to ensure that the sameseedalways produces the same avatar.options: The merged set of user-provided and default options for the style.
It must return a StyleCreateResult object, which has the following structure:
| Property | Type | Description |
|---|---|---|
attributes | Record<string, any> | A map of attributes for the root <svg> element. A viewBox is essential. |
body | string | The string content of the SVG, including all paths and groups that make up the avatar. |
extra | () => Record<string, any> | An optional function that returns extra metadata about the generated avatar. This is included in the toJson() output. |
Sources: packages/avatar/src/open-peeps/index.ts:21-201
Component-Based Structure
The open-peeps style demonstrates a robust, component-based approach. The avatar is broken down into logical parts like head, face, facialHair, and accessories. Each part is a "component group" containing multiple variations.
This diagram shows the internal logic of the open-peeps create function.
This flow illustrates how components and colors are selected using the PRNG and options, then assembled into the final SVG body.
Sources: packages/avatar/src/open-peeps/index.ts:16-20
Each component group is a collection of functions, where each function returns an SVG string for a specific variation.
Example from face.ts:
// packages/avatar/src/open-peeps/components/face.ts:3-5
export const face: ComponentGroup = {
angryWithFang: () =>
`<path fill-rule="evenodd" clip-rule="evenodd" d="..." fill="#000"/>`,
awe: () =>
`<g fill-rule="evenodd" clip-rule="evenodd"><path d="..." fill="#fff"/><path d="..." fill="#000"/></g>`,
// ... more face variations
}
The final SVG body is constructed by embedding these component strings within <g> (group) elements, using transform attributes to position them correctly.
Sources: packages/avatar/src/open-peeps/index.ts:197-201, packages/avatar/src/open-peeps/components/face.ts, packages/avatar/src/open-peeps/components/facialHair.ts, packages/avatar/src/open-peeps/components/accessories.ts
Defining Style Options with a Schema
To make a style configurable, you can export a schema object. This is a standard JSON Schema that defines all the available options, their types, and default values. The core system uses this schema to merge user options with defaults.
The open-peeps schema defines options for selecting component variations and setting probabilities.
Example open-peeps Schema Properties:
| Property | Type | Description | Default Value |
|---|---|---|---|
face | array | An array of strings specifying which face variations are allowed. | An array of all 30 face variations. |
facialHair | array | An array of strings specifying which facial hair variations are allowed. | An array of all 16 facial hair variations. |
facialHairProbability | integer | A percentage (0-100) chance of the avatar having facial hair. | 10 |
accessoriesProbability | integer | A percentage (0-100) chance of the avatar having accessories. | 20 |
skinColor | array | An array of hex color codes (without #) for the skin. | ['ffdbb4', 'edb98a', 'd08b5b', ...] |
Sources: packages/avatar/src/open-peeps/schema.ts:4-169
SVG Post-Processing
After your style's create function returns the base SVG, the core createAvatar function applies a series of post-processing steps. These are generic transformations that can be applied to any style.
The pipeline is as follows:
- Size: Sets the
widthandheightattributes ifoptions.sizeis provided. - Scale: Scales the avatar content if
options.scaleis provided. - Flip: Flips the avatar horizontally if
options.flipis true. - Rotate: Rotates the avatar if
options.rotateis provided. - Translate: Moves the avatar using
options.translateXandoptions.translateY. - Background: Adds a solid or gradient background.
- Mask: Applies a clipping mask, for example to create rounded corners with
options.radius.
This diagram shows the post-processing steps applied by the core system.
Final Result
The createAvatar function ultimately returns a Result object with methods to access the generated SVG in different formats.
| Method | Returns | Description |
|---|---|---|
toString() | string | Returns the final SVG as a string. |
toJson() | object | Returns an object containing the SVG string and extra metadata. |
toDataUri() | string | Returns a data:image/svg+xml URI, suitable for use in <img> tags. |
Sources: packages/avatar/src/core/index.ts:59-75
Conclusion
Creating a new avatar style for @nextorders/avatar involves implementing a Style object containing a create function and an optional schema. The create function is responsible for generating the base SVG, ideally using a component-based structure for maintainability. The core system handles the rest, applying transformations and packaging the final output. By following the open-peeps implementation as a template, developers can easily extend the library with unique and custom avatar styles.