# Avatar metadata — handoff

## Summary

Paarrot embeds profile accent metadata **inside image files** (PNG, JPEG, WebP, GIF) so avatar colors, banners, gradients, and border colors travel with the MXC upload. Other Paarrot clients read this metadata to theme profile UI without extra Matrix account data fields.

## User-facing behavior

- **Settings → Account → Profile**: pick accent color (and related styling) applied to avatar image on save
- Profile viewers extract color/banner from avatar HTTP URL for themed headers
- Works across image formats users commonly upload

## Architecture

```
Profile settings UI
  → embedMetadata / embedColor (imageMetadata.ts)
    → format-specific: pngMetadata, jpegMetadata, webpMetadata, gifMetadata
  → upload to Matrix
Other clients / Profile.tsx
  → extractMetadataFromImage(fetch avatar)
    → apply CSS variables / banner URL
```

## Key files

| Path | Role |
|------|------|
| `cinny/src/app/utils/imageMetadata.ts` | Unified embed/extract API |
| `cinny/src/app/utils/pngMetadata.ts` | PNG tEXt chunks |
| `cinny/src/app/utils/jpegMetadata.ts` | JPEG XMP APP1 |
| `cinny/src/app/utils/webpMetadata.ts` | WebP XMP |
| `cinny/src/app/utils/gifMetadata.ts` | GIF application extension |
| `cinny/src/app/features/settings/account/Profile.tsx` | Settings UI + upload pipeline |

## Data model

Metadata keys (embedded in binary image, not Matrix):

| Key | Format | Notes |
|-----|--------|-------|
| `paarrot:color` | All | Accent color hex |
| `paarrot:banner` | PNG (+ unified API) | Banner image URL |
| `paarrot:borderColor` | PNG | Border accent |
| `paarrot:gradient` | PNG | Gradient spec |

XMP namespace: `http://paarrot.app/ns/1.0/`

## Dependencies

- Browser `ArrayBuffer` / `Uint8Array` parsing
- No server-side processing — client-only before upload

## Integration points

- **Profile display**: user profile cards read metadata from avatar URL
- **Image upload flow**: must re-encode image with metadata before `uploadContent`

## Testing

### Manual

1. Set profile color in settings; save avatar.
2. Download avatar MXC; verify metadata with hex dump or Paarrot on second account.
3. Repeat for PNG, JPEG, WebP, GIF uploads.
4. Remove color; verify strip functions work.

### Automated

- None — good candidate for unit tests on chunk parsers

## Known issues & gotchas

- Metadata stripped if user uploads through non-Paarrot client
- Large images: re-encoding memory cost on mobile
- Console logging in `pngMetadata.ts` (`extractColorFromPNG`) — noisy in prod
- Federation: only Paarrot-aware clients interpret metadata

## Future work

- Unit tests per format parser
- Fallback to account data if metadata missing
- Document binary spec in standalone spec doc

## Related docs

- None

## Add your extra things here

- Entry points: `extractPaarrotMetadata`, `embedPaarrotMetadata`, `embedPaarrotColor` in `imageMetadata.ts`
- Profile comment: "Stored in avatar image metadata, visible to other Paarrot users"
