Adding New Components to a Style
Relevant source files
The following files were used as context for generating this wiki page:- packages/avatar/src/open-peeps/components/face.ts
- packages/avatar/src/open-peeps/components/facialHair.ts
- packages/avatar/src/open-peeps/components/index.ts
- packages/avatar/src/open-peeps/index.ts
- packages/avatar/src/open-peeps/schema.ts
- packages/avatar/src/core/index.ts
- packages/avatar/src/core/utils/svg.ts
This document outlines the process for adding new SVG components, such as a new face or accessory, to an existing avatar style. The open-peeps style is used as the primary example. The system is designed to be modular, allowing for straightforward extension by adding new component definitions, updating the style's schema, and ensuring they are correctly integrated into the final SVG rendering pipeline.
The process involves defining the component's SVG markup, registering it within a component group, and making it available through the options schema. This ensures that the new component can be selected randomly by the generator or specified directly by the user.
Core Concepts and File Structure
Avatar components are organized into groups based on their type (e.g., face, facialHair, accessories). Each group is defined in its own file within the style's components directory.
The following table summarizes the key files involved in managing and rendering components for the open-peeps style.
| File Path | Description |
|---|---|
packages/avatar/src/open-peeps/components/*.ts | Contains the raw SVG data for each component, grouped by type (e.g., face.ts). |
packages/avatar/src/open-peeps/components/index.ts | Acts as a barrel file, exporting all component groups to make them accessible to the style. |
packages/avatar/src/open-peeps/schema.ts | Defines the JSON schema for the style's options, including the list of available components for each group. |
packages/avatar/src/open-peeps/index.ts | The main style creation file. It selects components and assembles them into the final SVG body. |
Sources: packages/avatar/src/open-peeps/components/face.ts, packages/avatar/src/open-peeps/components/index.ts, packages/avatar/src/open-peeps/schema.ts, packages/avatar/src/open-peeps/index.ts
Component Group Definition
A component group is an object where each key is the name of a specific component variant (e.g., smile, calm) and the value is a function that returns the SVG markup string for that variant. These functions can optionally accept a colors object to allow for dynamic coloring.
This diagram illustrates the structure of a component group file.
Below is an example from facialHair.ts showing a component that uses the colors object.
// packages/avatar/src/open-peeps/components/facialHair.ts:11-12
export const facialHair: ComponentGroup = {
// ... other facial hair components
full4: (colors) =>
`<g fill-rule="evenodd" clip-rule="evenodd"><path d="..." fill="${xml(colors.headContrast)}"/><path d="..." fill="#000"/></g>`,
// ...
}
Sources: packages/avatar/src/open-peeps/components/facialHair.ts:11-12
Step-by-Step Guide to Adding a Component
Adding a new component variant to an existing group (e.g., a new "surprised" face) involves three main steps.
1. Define the SVG Markup
First, create the SVG markup for the new component. This is typically a <path> or <g> element. The markup should be defined within a function that returns a string, following the ComponentGroup structure.
Add the new component to the appropriate file in packages/avatar/src/open-peeps/components/. For example, a new face would be added to face.ts.
// packages/avatar/src/open-peeps/components/face.ts
import type { ComponentGroup } from '../types'
export const face: ComponentGroup = {
// ... existing face components
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>`,
// Add your new component here
surprised: () =>
`<path d="...your new svg path data..." />`
};
Sources: packages/avatar/src/open-peeps/components/face.ts:3-5
2. Update the Style Schema
To make the new component selectable via options, its name must be added to the style's JSON schema. Open packages/avatar/src/open-peeps/schema.ts and add the new component's name to the enum array of the corresponding property.
// packages/avatar/src/open-peeps/schema.ts
export const schema: StyleSchema = {
// ...
properties: {
// ...
face: {
type: 'array',
items: {
type: 'string',
enum: [
// ... existing face names
'veryAngry',
'surprised', // Add the new component name here
],
},
default: [
// ... existing face names
'veryAngry',
'surprised', // Also add to the default list
],
},
// ...
},
}
Sources: packages/avatar/src/open-peeps/schema.ts:63-100
3. Verify Integration
The component is automatically picked up by the style's main creation function. The getComponents utility (used within packages/avatar/src/open-peeps/index.ts) uses the provided options and schema to select a component. The selected component's SVG is then injected into the main SVG body at a predefined position using a <g> tag with a transform attribute.
// packages/avatar/src/open-peeps/index.ts:16-17
export const create: StyleCreate<OpenPeepsOptions> = ({ prng, options }) => {
const components = getComponents({ prng, options })
const colors = getColors({ prng, options })
return {
// ... attributes
body: `
// ... other SVG parts
<g transform="translate(315 248)">${components.face?.value(colors) ?? ''}</g>
<g transform="translate(279 400)">${components.facialHair?.value(colors) ?? ''}</g>
<g transform="translate(203 303)">${components.accessories?.value(colors) ?? ''}</g>
`,
// ...
}
}
No changes are needed in this file unless you are adding a new category of component that requires a new position.
Sources: packages/avatar/src/open-peeps/index.ts:16-24
Component Rendering Flow
The following diagram shows the data flow from the initial createAvatar call to the final rendering of a component within the SVG.
This flow demonstrates how a component, once defined and added to the schema, is selected and integrated into the avatar SVG.
Sources: packages/avatar/src/index.ts:13, packages/avatar/src/core/index.ts:10, packages/avatar/src/open-peeps/index.ts:16-24
Conclusion
The avatar generation system is built for extensibility. By following the three main steps—defining the SVG markup in the correct component group file, updating the style's JSON schema, and verifying its placement in the main style file—developers can easily add new visual elements to the open-peeps style or any other similarly structured style. This modular approach keeps component definitions separate from the rendering logic, simplifying maintenance and expansion.
Sources: packages/avatar/src/open-peeps/components/face.ts, packages/avatar/src/open-peeps/schema.ts, packages/avatar/src/open-peeps/index.ts