Le pitch
Kao-Z est un générateur d’avatars SVG personnalisables. On combine des éléments (visage, cheveux, yeux, accessoires…) avec des contrôles de position, zoom et couleurs, puis on exporte en PNG/SVG ou on partage via URL.
Essayer : presque.cool/kao-z/
Pourquoi ce projet
J’ai découvert icon-z.com par hasard sur les réseaux sociaux — un générateur d’avatars japonais créé par @topeconheroes avec des centaines d’éléments graphiques. La version originale est excellente, mais exclusivement en japonais.
Je me suis fixé un défi : rétro-ingénierie et adaptation en anglais.
Pas d’objectif d’apprentissage particulier cette fois. J’aime fabriquer des générateurs d’avatars, et je voulais me frotter à des assets graphiques différents de ceux dont j’avais l’habitude (Star Wars Avatar). C’était l’occasion de voir si je pouvais appliquer les leçons apprises sur les précédents générateurs.
Rétro-ingénierie d’un site japonais
icon-z.com n’est pas open source. Pour comprendre comment il fonctionnait, j’ai procédé par inspection : analyse du DOM pour comprendre la structure des couches SVG, interception des requêtes réseau pour identifier comment les assets étaient chargés, téléchargement des fichiers SVG catégorie par catégorie.
Le résultat : 828 fichiers SVG répartis en 12 catégories, un système de couleurs à 5 canaux (fill, border, tone, accent, secondary), et une logique de composition par superposition de couches.
Ce travail de rétro-ingénierie m’a donné une compréhension suffisante pour reconstruire l’expérience dans un contexte différent — interface FR/EN, stack React, et un système de partage par URL qui n’existait pas dans l’original.
Le défi technique : 828 fichiers SVG et un état à compresser
Le projet contient environ 828 fichiers SVG répartis en 12 catégories. Charger chaque fichier individuellement aurait créé des centaines de requêtes HTTP — une latence inacceptable.
La solution : bundling JSON
J’ai créé un système de bundles : un fichier JSON par catégorie contenant tous les SVG pré-chargés. Au lieu de centaines de requêtes, une seule par catégorie suffit.
Encodage URL compact
L’avatar complet (12 sélections + 5 couleurs + 4 paramètres de position) devait tenir dans une URL partageable. La première approche — sérialiser l’état en JSON puis l’encoder en Base64 — produisait des URLs d’environ 90 caractères. C’est fonctionnel, mais long.
J’ai opté pour un encodage binaire : chaque sélection est stockée sur 10 bits (supportant jusqu’à 1023 éléments par catégorie), les couleurs en 3 bytes RGB chacune, et la position en 3 bytes (X et Y en int8 signé, zoom + flag closeup dans le dernier byte). Le tout tient dans 34 bytes, encodés en Base64 URL-safe — soit environ 46 caractères. Moitié moins que la version JSON.
Autres défis :
- Composition temps réel — 12 couches SVG superposées dans le bon ordre, avec le système de couleurs CSS à 5 canaux
- Grille virtualisée — Des centaines d’éléments à afficher sans lag grâce à
@tanstack/react-virtual
Stack technique
- React + TypeScript — Composants fonctionnels, typage strict
- Vite + SWC — Build rapide avec Hot Module Replacement
- Tailwind CSS — Configuration CSS-first, classes utilitaires
- Zustand — State management avec persistence localStorage
- @tanstack/react-virtual — Virtualisation de grilles larges
- PWA — installable, offline
- i18n maison — Français/anglais sans dépendance externe
- Compression — Brotli + Gzip sur les assets
- CSP — Content-Security-Policy avec hashes auto-générés
Évolutions
| Date | Version | Description |
|---|---|---|
| Jan 2026 | 1.0 | Version initiale — Adaptation de icon-z.com avec interface FR/EN |
Bilan
Ce que j’ai appris :
- Que j’apprécie vraiment travailler avec des assets créés par des designers/illustrateurs. C’est différent de tout faire soi-même — on se concentre sur l’expérience utilisateur plutôt que sur la création graphique.
- L’encodage binaire pour les URLs de partage — penser en bits plutôt qu’en chaînes de caractères change la façon d’aborder la sérialisation.
Ce que je referais pareil :
- Le système de bundles JSON — c’est la clé pour gérer des centaines d’assets sans sacrifier les performances
- L’encodage URL binaire — les URLs restent courtes même avec beaucoup de paramètres
Ce que je changerais :
- Ajouter une version traduite en japonais, en hommage à la version originale.
- L’expérience accumulée sur Star Wars Avatar a rendu Kao-Z plus fluide : moins de tâtonnement sur l’UI, meilleure séparation des responsabilités dès le départ. Mais l’inverse aurait aussi été vrai — la rétro-ingénierie et la gestion de centaines de SVG auraient été utiles en amont.
The pitch
Kao-Z is a customizable SVG avatar generator. Combine elements (face, hair, eyes, accessories…) with position, zoom, and color controls, then export to PNG/SVG or share via URL.
Try it: presque.cool/kao-z/
Why this project
I discovered icon-z.com randomly on social media — a Japanese avatar generator created by @topeconheroes with hundreds of graphic elements. The original version is excellent, but exclusively in Japanese.
I set myself a challenge: reverse engineering and English adaptation.
No particular learning objective this time. I enjoy building avatar generators, and I wanted to work with graphic assets different from what I was used to (Star Wars Avatar). It was an opportunity to see if I could apply the lessons learned from previous generators.
Reverse engineering a Japanese site
icon-z.com isn’t open source. To understand how it worked, I proceeded by inspection: analyzing the DOM to understand the SVG layer structure, intercepting network requests to identify how assets were loaded, downloading SVG files category by category.
The result: 828 SVG files across 12 categories, a 5-channel color system (fill, border, tone, accent, secondary), and a composition logic based on layer superposition.
This reverse engineering work gave me enough understanding to rebuild the experience in a different context — FR/EN interface, React stack, and a URL sharing system that didn’t exist in the original.
The technical challenge: 828 SVG files and a state to compress
The project contains about 828 SVG files spread across 12 categories. Loading each file individually would have created hundreds of HTTP requests — unacceptable latency.
The solution: JSON bundling
I created a bundle system: one JSON file per category containing all pre-loaded SVGs. Instead of hundreds of requests, just one per category is needed.
Compact URL encoding
The complete avatar (12 selections + 5 colors + 4 position parameters) had to fit in a shareable URL. The first approach — serializing state as JSON then encoding in Base64 — produced URLs of about 90 characters. Functional, but long.
I opted for binary encoding: each selection is stored in 10 bits (supporting up to 1023 elements per category), colors in 3 bytes RGB each, and position in 3 bytes (X and Y as signed int8, zoom + closeup flag in the last byte). Everything fits in 34 bytes, encoded in URL-safe Base64 — about 46 characters. Half the size of the JSON version.
Other challenges:
- Real-time composition — 12 SVG layers superimposed in the correct order, with the 5-channel CSS color system
- Virtualized grid — Hundreds of elements to display without lag thanks to
@tanstack/react-virtual
Tech stack
- React + TypeScript — Functional components, strict typing
- Vite + SWC — Fast builds with Hot Module Replacement
- Tailwind CSS — CSS-first configuration, utility classes
- Zustand — State management with localStorage persistence
- @tanstack/react-virtual — Large grid virtualization
- PWA — installable, offline
- i18n custom — French/English without external dependency
- Compression — Brotli + Gzip on assets
- CSP — Content-Security-Policy with auto-generated hashes
Timeline
| Date | Version | Description |
|---|---|---|
| Jan 2026 | 1.0 | Initial version — Adaptation of icon-z.com with FR/EN interface |
Takeaways
What I learned:
- That I really enjoy working with assets created by designers/illustrators. It’s different from doing everything yourself — you focus on user experience rather than graphic creation.
- Binary encoding for share URLs — thinking in bits rather than strings changes how you approach serialization.
What I’d do the same:
- The JSON bundle system — it’s the key to managing hundreds of assets without sacrificing performance
- Binary URL encoding — URLs stay short even with many parameters
What I’d change:
- Add a Japanese translation, as a tribute to the original version.
- The experience accumulated on Star Wars Avatar made Kao-Z smoother: less trial and error on the UI, better separation of concerns from the start. But the reverse would also have been true — the reverse engineering and management of hundreds of SVGs would have been useful upstream.