# Building your catalog

Catalogs define what assets your users may use in order to customize their avatars. By default, MSquared provides an extensive library of parts to get you started, however, you may want to build your own catalog for a custom experience.

Catalogs are hosted json files which the Avatar Editor ingests and presents to the user so they can pick the assets they desire. At its root, a catalog is defined as a set of `skin` and `bodyTypes` configurations. How to set up each section is outlined below.

```typescript
{
    skin: Skin;
    bodyTypes: BodyTypes;
}
```

### Skin

By default the Avatar Creator supports 7 skin tones. If you need more skin tones please reach out to the MSquared Team. Any parts which are [skin dependent](#skin-dependent-parts) will require a variation to be created for each skin color.

```typescript
{
    name: string;
    index: number;
}
```

For most projects, the following `skin` setup can be used:

```json
"skin": [
    {
       "name": "01",
        "index": 1
    },
    {
       "name": "02",
        "index": 2
    },
    {
       "name": "03",
        "index": 3
    },
    {
       "name": "04",
        "index": 4
    },
    {
       "name": "05",
        "index": 5
    },
    {
       "name": "06",
        "index": 6
    },
    {
       "name": "07",
        "index": 7
    }
],
    
```

### Body Types

By default, the Avatar Creator supports 2 body types (`bodyA` and `bodyB`). If you need more body types please reach out to the MSquared Team. Every catalog should define parts for both `bodyA` and `bodyB`.

A body type is composed of `body`, `head`, `hair`, `top`, `bottom`, and `shoes`  - each containing a list of parts.

```typescript
  body:{
    torsoArms: string; 
    arms: string;
    legsFeet: string;
    legs: string;
  };
  head: {
    list: HeadPart[];
  };
  hair: {
    list: HairPart[]
  };
  top: {
    list: TopPart[]
  };
  bottom: {
    list: BottomPart[]
  };
  shoes: {
    list: ShoesPart[]
  };
```

#### Defining a body

The base body parts must be provided, which the user's chosen assets will be placed on top of. All fields which make up the body are [skin dependent](#skin-dependent-parts).

#### Defining a part

A part is composed of the following fields:

* `file`&#x20;
  * Required for every part&#x20;
  * References the thumbnail and model by appending `.webp` and `.glb` respectively to the provided URI
* `secondary`&#x20;
  * Optionally provided to `TopPart` and `BottomPart`
  * Loads an additional glb for the slot
  * File referenced in the same way as the primary file but no thumbnail is required
* `torso`
  * Optional field on `TopPart`&#x20;
  * If value is `true` then the torso will be rendered
  * For example, this may be needed for shirts but a hoodie covers the whole torso so by default it will not need to render the torso
* `legs`
  * Optional field on `BottomPart`&#x20;
  * If value is `true` then the legs will be rendered
  * For example, this may be needed for shorts but a pair of jeans covers the whole legs so by default it will not need to render the legs

Additionally, the `head` slot is [skin dependent](#skin-dependent-parts).

### Example Catalog

This minimal example only has one body type configured; selecting the other body type in the editor with this will cause an error

```json
{
  "skin": [
    {
      "name": "01",
      "index": 1
    },
    {
      "name": "02",
      "index": 2
    }
  ],
  "bodyTypes": {
    "bodyA": { ...omitted... },
    "bodyB": {
      "body": {
        "torsoArms": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyTorsoHeadless",
        "arms": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyArmsHeadless",
        "legsFeet": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyLegsFeet",
        "legs": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyLegs"
      },
      "head": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Head_B_Mixed_B"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Head_B_Mixed_A"
          }
        ]
      },
      "hair": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Hair_B_NatalieHair_Brown_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Hair_B_NatalieHair_Extra_01"
          }
        ]
      },
      "top": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_Hoodie_WindbreakerBlackWhite_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_RockJacket_VinylWhite_01",
            "secondary": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_RockTopLong_White_01",
            "torso": true
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_FlannelShirt_CheckerdRed_01",
            "secondary": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_BaseballJersey_BlackRed_01"
          }
        ]
      },
      "bottom": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Bottom_B_TightJoggers_TanJeans_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Bottom_B_PleatedSkirt_TweedWhite_01",
            "secondary": "https://storage.googleapis.com/glb-content-bucket/parts/Bottom_B_StockingsGarterRibbon_White_01",
            "legs": true
          }
        ]
      },
      "shoes": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Shoes_B_HighTops_WhitePink_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Shoes_B_HighTops_RunningBlue_01"
          }
        ]
      }
    }
  }
}

```

### Asset Files

Assets, including the thumbnail and model, should be hosted using a high-availability, high-throughput CDN to avoid bottlenecks. Additionally, configure your CDN with aggressive caching to minimize network requests and speed up downloads. The files must be publicly downloadable.

Files referenced in the below catalog do not have a file extension included. This is so they can reference both the thumbnail and model by simply appending `.webp` and `.glb`  respectively.&#x20;

A common issue encountered when configuring asset files is the bucket hosting the assets does not have the correct CORS configuration, leading to the Avatar Creator UI not being able to fetch the content. Please ensure that whatever bucket is used for hosting content allows cross-origin requests.

#### Skin Dependent Parts

Additionally, some parts are marked as skin dependent. These will have the skin index, (preceded by an underscore), appended before the extension so specific parts can be set based off of the skin color

#### Example files

Given the base file reference:

```
example.com/my-storage/body-part
```

It would be expected that it would be possible to publicly access both

```
example.com/my-storage/body-part.webp // The thumbnail.
example.com/my-storage/body-part.glb  // The model.
```

Furthermore, if the part was skin dependent the following should be accessible:

```
example.com/my-storage/body-part_01.webp // The thumbnail for skin tone 01.
example.com/my-storage/body-part_01.glb  // The model for skin tone 01.
example.com/my-storage/body-part_02.webp // The thumbnail for skin tone 02.
example.com/my-storage/body-part_02.glb  // The model for skin tone 02.
...
example.com/my-storage/body-part_07.webp // The thumbnail for skin tone 07.
example.com/my-storage/body-part_07.glb  // The model for skin tone 07.
```
