Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:The @nextorders/avatar package provides a toolkit for generating personalized SVG avatars. The architecture is designed to be modular, separating the core SVG generation and manipulation logic from the specific visual styles of the avatars. The primary style implemented is "Open Peeps" by Pablo Stanley.
The system's entry point is the createAvatar function, which orchestrates the process. It takes user-defined options, combines them with style-specific configurations, and passes them to a core engine. This engine uses a pseudo-random number generator (PRNG) for deterministic outputs based on a seed, calls the specified style to create the base avatar components, and then applies a series of SVG transformations (like scaling, rotation, and background effects) before returning the final SVG string.
High-Level Generation Flow
The avatar generation process is initiated by the createAvatar function. This function acts as a facade, simplifying the API for the end-user. It validates and transforms user options before invoking the core generation logic.
The diagram below illustrates the main data flow from the initial function call to the final SVG output.
Core Generation Engine
The core logic resides in packages/avatar/src/core/index.ts. The createAvatar function (renamed here to createBaseAvatar to avoid confusion with the public API) is the heart of the system. It is a generic function that can work with any style that conforms to the Style interface.
Process Steps
- Options Merging: Merges default style options with user-provided options.
- PRNG Initialization: Creates a pseudo-random number generator instance using the provided
seed. This ensures that for the same seed, the generated avatar is identical. - Style Creation: Invokes the
style.createmethod, passing the PRNG and options. This returns the basic SVG body and attributes. - Background Generation: Determines the background type (e.g.,
solid,gradientLinear) and colors, then prepends the background SVG elements to the avatar body. - SVG Transformations: Applies a series of transformations to the SVG body in a specific order. These include scaling, flipping, rotating, and translating.
- Final Assembly: Wraps the modified SVG body in
<svg>tags with the final attributes. - Result Object: Returns a
Resultobject with methods to get the avatar as a string (toString()), a JSON object with extra metadata (toJson()), or a Data URI (toDataUri()).
Sources: packages/avatar/src/core/index.ts:8-66
SVG Transformation Pipeline
The core engine applies several transformations to the raw SVG generated by the style. These are handled by utility functions in packages/avatar/src/core/utils/svg.ts.
The following diagram shows the sequence of these transformations.
The table below details the functions responsible for each transformation.
| Function | Description | Source File |
|---|---|---|
addScale | Wraps the SVG body in a <g> tag with a scale transform. | packages/avatar/src/core/utils/svg.ts:50-59 |
addFlip | Wraps the SVG body in a <g> tag with a horizontal flip transform. | packages/avatar/src/core/utils/svg.ts:77-83 |
addRotate | Wraps the SVG body in a <g> tag with a rotate transform around the center. | packages/avatar/src/core/utils/svg.ts:70-76 |
addTranslate | Wraps the SVG body in a <g> tag with a translate transform. | packages/avatar/src/core/utils/svg.ts:61-68 |
addBackground | Prepends a <rect> element for solid or gradient backgrounds. | packages/avatar/src/core/utils/svg.ts:19-48 |
addViewboxMask | Applies a clipping mask to create rounded corners (radius). | packages/avatar/src/core/utils/svg.ts:85-94 |
Style System: Open Peeps
The visual appearance of the avatar is determined by a "style" object. The repository implements the open-peeps style.
Sources: packages/avatar/src/open-peeps/index.ts
Style create Function
The openPeeps.create function is responsible for generating the raw SVG for an avatar based on the Open Peeps design.
Its process is as follows:
- Get Components: It calls
getComponentsto randomly select which avatar parts to use (e.g.,head,face,facialHair) based on the PRNG and user options. - Get Colors: It calls
getColorsto determine theskinandclothingcolors. - Assemble SVG: It constructs the SVG
bodyby embedding the selected components' SVG code within<g>tags, applying the necessarytransformattributes to position them correctly. Each component is a function that receives the color palette.
// packages/avatar/src/open-peeps/index.ts:20-24
export const create: StyleCreate<OpenPeepsOptions> = ({ prng, options }) => {
const components = getComponents({ prng, options })
const colors = getColors({ prng, options })
return {
attributes: {
'viewBox': '0 0 704 704',
'fill': 'none',
'shape-rendering': 'auto',
},
body: `<g>...</g><g transform="matrix(.99789 0 0 1 156 62)">${components.head?.value(colors) ?? ''}</g><g transform="translate(315 248)">${components.face?.value(colors) ?? ''}</g>...`,
// ...
}
}
Sources: packages/avatar/src/open-peeps/index.ts:20-49
Component Structure
Avatar parts are organized into component groups. For example, packages/avatar/src/open-peeps/components/face.ts defines all possible face variations. Each variation is a function that returns an SVG path string.
This is an example of the face component group:
// 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 styles
}
The getComponents utility randomly selects one of these functions from the group to be rendered.
Sources: packages/avatar/src/open-peeps/components/face.ts
Configuration and Options
The avatar generation is controlled by a set of options. The main public options are defined in AvatarOptions.
Public AvatarOptions
These are the simplified options exposed to the end-user.
| Option | Type | Description | Source |
|---|---|---|---|
seed | string | A string used to seed the random number generator for deterministic output. Required. | packages/avatar/src/types.ts:6 |
gender | Gender ('male' | 'female') | Influences the selection of gender-specific components. | packages/avatar/src/types.ts:7 |
clothing | 'amber' | 'green' | 'blue' | 'teal' | 'pink' | 'violet' | Determines the clothing color. | packages/avatar/src/types.ts:8 |
emotion | 1 | ... | 10 | A number from 1 to 10 that maps to a specific face emotion. | packages/avatar/src/types.ts:9 |
These high-level options are translated into more detailed, style-specific options by the buildOptions function.
Sources: packages/avatar/src/index.ts:18-27, packages/avatar/test/unit/index.test.ts:28-31
Style Schema
The open-peeps style defines a comprehensive JSON schema in packages/avatar/src/open-peeps/schema.ts. This schema documents all possible customization options for the style, including available components for head, face, accessories, facialHair, their probabilities, and color palettes. This schema serves as the ground truth for all available style variations.
The schema defines properties like face with an enum of all possible face component names.
// packages/avatar/src/open-peeps/schema.ts:51-83
"face": {
"type": "array",
"items": {
"type": "string",
"enum": [
"angryWithFang",
"awe",
"blank",
"calm",
"cheeky",
"concerned",
"concernedFear",
"contempt",
"cute",
"cyclops",
"driven",
"eatingHappy",
"explaining",
"eyesClosed",
"fear",
"hectic",
"lovingGrin1",
"lovingGrin2",
"monster",
"old",
"rage",
"serious",
"smile",
"smileBig",
"smileLOL",
"smileTeethGap",
"solemn",
"suspicious",
"tired",
"veryAngry"
]
},
// ...
}
Sources: [packages/avatar/src/open-peeps/schema.ts]
Project Structure and Build
The repository is a monorepo managed by pnpm. The main package is @nextorders/avatar located in the packages/avatar directory.
- Build Process: The
unbuildtool is used to compile the TypeScript source fromsrc/into JavaScript modules indist/. The build configuration inpackages/avatar/build.config.tsalso copies the rootREADME.mdinto the package directory. - Testing:
vitestis used for testing, with separate configurations forunitandbrowsertests. - Linting and Formatting:
eslintandlint-stagedare configured to maintain code quality.
Sources: package.json, packages/avatar/build.config.ts, vitest.config.ts
Summary
The @nextorders/avatar library features a robust and modular architecture. It separates the core SVG processing logic from the artistic style definitions, allowing for potential future expansion with new avatar styles. The use of a seeded PRNG ensures deterministic and reproducible avatar generation, while the component-based approach for the open-peeps style allows for a high degree of variation and customization. The entire process is orchestrated by a simple public API, hiding the complexity of option building and SVG manipulation from the end-user.