# 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"