# How to Add New SVG Assets for Avatar Components in Vue Color Avatar

> Learn to add new SVG assets for avatar components in Vue Color Avatar. Follow simple steps to extend shape enums and register imports for custom avatars.

- Repository: [LeoKu/vue-color-avatar](https://github.com/codennnn/vue-color-avatar)
- Tags: how-to-guide
- Published: 2026-02-27

---

**To add new SVG assets for avatar components in vue-color-avatar, place the SVG file in the appropriate widgets directory, extend the corresponding shape enum in [`src/enums/index.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/enums/index.ts), and register the lazy import function in [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts).**

The `codennnn/vue-color-avatar` library renders avatars by dynamically loading SVG assets at runtime. This architecture allows you to extend the avatar library with custom graphics without modifying the core rendering logic. Understanding how to add new SVG assets for avatar components ensures you can seamlessly integrate custom widgets while maintaining the existing dynamic loading mechanism.

## Understanding the SVG Asset Pipeline

The avatar rendering pipeline relies on three interconnected systems to load and display SVG assets dynamically.

### Enum Definitions in src/enums/index.ts

Each widget category (e.g., `Tops`, `Mouth`, `Eyes`) has a corresponding shape enum that defines valid options. The enum values must match the SVG file names exactly.

```typescript
// src/enums/index.ts
export enum TopsShape {
  // ... existing members ...
  Crown = 'crown',
}

```

### Dynamic Import Mapping in src/utils/dynamic-data.ts

The `widgetData` object maps each widget type and shape to a lazy import function. The [`VueColorAvatar.vue`](https://github.com/codennnn/vue-color-avatar/blob/main/VueColorAvatar.vue) component calls these functions at runtime to fetch the raw SVG strings.

```typescript
// src/utils/dynamic-data.ts
[WidgetType.Tops]: {
  // ... existing shapes ...
  [TopsShape.Crown]: () => import(`../assets/widgets/tops/crown.svg?raw`),
},

```

### Runtime Rendering in VueColorAvatar.vue

The core component iterates over the selected widgets, resolves the async imports, substitutes `$fillColor` variables with the chosen colors, and injects the final SVG markup via `v-html`.

## Step-by-Step Guide to Adding New SVG Assets

Follow these steps to integrate custom SVG graphics into the avatar system.

### Step 1: Create the SVG File

Place your SVG file in `src/assets/widgets/<widget-type>/<shape>.svg`. The file name must exactly match the enum value you will define (case-sensitive).

```

src/assets/widgets/tops/crown.svg

```

### Step 2: Extend the Shape Enum

Add a new member to the appropriate enum in [`src/enums/index.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/enums/index.ts). Use PascalCase for the member name and ensure the value matches the SVG file name.

```typescript
// src/enums/index.ts
export enum TopsShape {
  Beanie = 'beanie',
  Crown = 'crown',  // New entry
  // ... other shapes
}

```

### Step 3: Register the Dynamic Import

In [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts), add a lazy import entry to the `widgetData` map for your widget type.

```typescript
// src/utils/dynamic-data.ts
[WidgetType.Tops]: {
  [TopsShape.Beanie]: () => import('../assets/widgets/tops/beanie.svg?raw'),
  [TopsShape.Crown]: () => import('../assets/widgets/tops/crown.svg?raw'),  // New entry
},

```

### Step 4: (Optional) Add Preview Thumbnails

If your UI displays preview thumbnails, add a simplified SVG to `src/assets/preview/<widget-type>/<shape>.svg` and register it in the `previewData` object in [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts).

## Working Example: Adding a Crown Top

Here is the complete implementation for adding a new "crown" top to the avatar system.

First, create the SVG asset:

```bash

# File location

src/assets/widgets/tops/crown.svg

```

Extend the enum definition:

```typescript
// src/enums/index.ts
export enum TopsShape {
  // existing members...
  Crown = 'crown',
}

```

Register the dynamic import:

```typescript
// src/utils/dynamic-data.ts
[WidgetType.Tops]: {
  // existing shapes...
  [TopsShape.Crown]: () => import(`../assets/widgets/tops/crown.svg?raw`),
},

```

Use the new asset in your application:

```typescript
import { AvatarOption, TopsShape } from '@/types';

const myAvatar: AvatarOption = {
  background: { color: '#fff', borderColor: '#000' },
  widgets: {
    tops: { shape: TopsShape.Crown, fillColor: '#FFD700' },
    // other widgets...
  },
};

```

The `VueColorAvatar` component will automatically resolve the lazy import, substitute the fill color, and render the crown SVG.

## Key Files and Their Roles

| File | Purpose |
|------|---------|
| [[`src/enums/index.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/enums/index.ts)](https://github.com/codennnn/vue-color-avatar/blob/main/src/enums/index.ts) | Defines widget‑type enums; each shape value must match an SVG filename. |
| [[`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts)](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts) | Holds the lazy‑import maps (`widgetData` & `previewData`) that the avatar component uses to fetch SVGs. |
| [[`src/components/VueColorAvatar.vue`](https://github.com/codennnn/vue-color-avatar/blob/main/src/components/VueColorAvatar.vue)](https://github.com/codennnn/vue-color-avatar/blob/main/src/components/VueColorAvatar.vue) | Core avatar renderer; pulls SVG strings from `widgetData`, substitutes colors, and builds the final SVG markup. |
| [[`src/types/index.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/types/index.ts)](https://github.com/codennnn/vue-color-avatar/blob/main/src/types/index.ts) | Type definitions for `AvatarOption` and widget shapes; ensures compile‑time safety when selecting new assets. |
| `src/assets/widgets/<type>/<shape>.svg` | Location for the raw SVG files that get imported at runtime. |
| `src/assets/preview/<type>/<shape>.svg` (optional) | Thumbnail preview assets used by the configurator UI. |

## Summary

- **Place SVG files** in `src/assets/widgets/<widget-type>/<shape>.svg` using filenames that match your enum values exactly.
- **Extend the appropriate enum** in [`src/enums/index.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/enums/index.ts) to register the new shape option.
- **Register the lazy import** in [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts) using the `?raw` query parameter to load the SVG as a string.
- **Optionally add preview thumbnails** in `src/assets/preview/` for UI selectors.
- The [`VueColorAvatar.vue`](https://github.com/codennnn/vue-color-avatar/blob/main/VueColorAvatar.vue) component automatically handles runtime loading, color substitution, and rendering once the asset is registered.

## Frequently Asked Questions

### What is the purpose of the `?raw` suffix in the import statement?

The `?raw` query parameter instructs Vite to import the SVG file as a plain text string rather than as a processed component or URL. The avatar component concatenates these raw SVG strings, substitutes `$fillColor` variables with user-selected colors, and injects the final markup via `v-html`. This approach keeps the SVG assets lightweight and enables dynamic color replacement without complex component hierarchies.

### Do I need to modify the VueColorAvatar.vue component to add new assets?

No, you do not need to modify [`VueColorAvatar.vue`](https://github.com/codennnn/vue-color-avatar/blob/main/VueColorAvatar.vue). The component is designed to dynamically load assets based on the `widgetData` map in [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts). As long as you register your new SVG in the dynamic-data file and extend the corresponding enum, the component will automatically resolve and render the new asset at runtime.

### Can I use different file names than the enum values?

No, the file names must match the enum values exactly (case-sensitive). The dynamic import path in [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts) uses the enum value to construct the file path: `import(\`../assets/widgets/tops/${shape}.svg?raw\`)`. If the enum value is `Crown = 'crown'`, the file must be named `crown.svg` (lowercase) to match the string value.

### Where should I place preview images for the UI configurator?

Place preview thumbnail SVGs in `src/assets/preview/<widget-type>/<shape>.svg`, using the same naming convention as the main assets. Then register the import in the `previewData` object within [`src/utils/dynamic-data.ts`](https://github.com/codennnn/vue-color-avatar/blob/main/src/utils/dynamic-data.ts) using the same lazy import pattern (`?raw`). The configurator UI uses these preview assets to display selectable options to users before they apply them to the main avatar.