presque.cool
Back to projects
Seedmoji icon

Seedmoji

Fév 2026 App
Visit project

A unique ASCII avatar for every word, every email, every username. Same input, same face — always.


Le pitch

Seedmoji transforme n’importe quelle chaîne de caractère — email, pseudo, UUID — en un avatar ASCII unique et déterministe. Même entrée, même visage. Toujours. Zéro API, zéro stockage, 100% client.

Essayer : presque.cool/seedmoji/

Durée ~1 jour
Période Fév 2026
Stack
React TypeScript PWA
Statut ✓ En production

Pourquoi ce projet

Il existe de nombreux générateurs d’avatars par seed — Identicon, MonsterID, Wavatars, Retro (by Gravatar), RoboHash… Mais aucun n’utilise des caractères ASCII pour composer des visages. En découvrant Facehash par cossistant, j’ai eu envie de faire ma propre version, en poussant plus loin la variabilité : plus d’éléments, plus de combinaisons, plus d’expressivité.

Le résultat : des petits visages en glyphs qui sont souvent drôles, parfois étranges, toujours uniques.

Un jour de développement, du plaisir créatif pur.


Le dictionnaire de glyphs

Le cœur de Seedmoji, c’est son dictionnaire de caractères. J’ai écumé des sites de référence Unicode et des tables de glyphs pour constituer un catalogue trié sur le volet :

  • 109 paires d’yeux — du classique ASCII (o,o ^,^ x,x) aux formes géométriques (◉,◉ ★,☆) en passant par les kaomoji (ಠ,ಠ ꖘ,ꖘ) et les symboles monétaires (€,€ ¥,¥). Symétriques et asymétriques.
  • 41 bouches — lignes horizontales ( ), courbes kaomoji (ω Д ), formes expressives ( ).
  • 15 nez — affichés uniquement avec les bouches horizontales pour éviter les chevauchements visuels.
  • 32 cadres — des crochets classiques ([ ]) aux cadres CJK (「 」 【 】) en passant par les décoratifs (╭ ╮ ╔ ╗).
  • 16 couleurs de fond — une palette vibrante récupérée sur un site d’inspiration graphique.

Le tout donne environ 34 millions de combinaisons uniques (sans compter les 3 formes de découpe). Chaque seed produit un visage différent et reproductible.


Le cœur technique : un hash déterministe

L’algorithme repose sur un hash simple, variante du String.hashCode() de Java (style djb2) :

seed → hash 32 bits → indices déterministes → composants du visage

Pourquoi pas SHA-256 ou MD5 ?

  1. Pas de sécurité requise — on génère des avatars, pas des tokens d’authentification
  2. Performance — djb2 fait ~10 opérations par caractère vs ~1000+ pour SHA-256. L’avatar se recalcule à chaque frappe clavier, la différence est perceptible
  3. Synchronicitécrypto.subtle.digest() est asynchrone, ça compliquerait inutilement le code
  4. Bundle size — le hash fait 8 lignes. Zéro dépendance, zéro polyfill

Un détail de design intéressant : le premier caractère du seed détermine la bouche. Taper a produit un avatar avec a comme bouche. Cela crée un lien visuel immédiat entre l’entrée et le résultat.

Le contraste texte/fond est calculé automatiquement via la luminance perçue (formule 0.299R + 0.587G + 0.114B) : fond clair → texte noir, fond foncé → texte blanc.


L’API d’embedding

Seedmoji inclut un endpoint /api/ qui génère du SVG brut via query params :

/seedmoji/api/?seed=tristan&shape=squircle&size=128

Pas de serveur — c’est la même app React qui détecte le pathname et rend un SVG pur au lieu de l’interface. Le SVG utilise des clipPath pour les formes (carré, squircle, rond), là où le composant React utilise borderRadius en CSS.

Pas encore utilisé en production, mais prêt pour une intégration dans d’autres projets.


Stack technique

  • React + TypeScript — Composants fonctionnels, typage strict
  • Vite + SWC — Build rapide
  • Tailwind CSS — Couleurs OKLch, dark mode
  • Zustand — State management, persistance localStorage
  • PWA — installable, offline, Workbox
  • i18n maison — Français/anglais, détection automatique du navigateur
  • Export SVG + PNG (512, 720, 1024px) via Canvas API
  • Compression — Brotli + Gzip sur les assets
  • CSP — Content-Security-Policy avec hashes auto-générés

Évolutions

DateVersionDescription
Fév 20261.0Version initiale — Dictionnaire, hash, export, PWA

Bilan

Durée : 1 jour (février 2026).

Ce que j’ai appris :

  • Qu’un dictionnaire de caractères Unicode soigneusement curé peut produire des résultats étonnamment expressifs — la contrainte ASCII force la créativité
  • Qu’un hash de 8 lignes suffit quand on n’a pas besoin de sécurité cryptographique

Ce que je referais pareil :

  • Partir d’un constat simple (“aucun générateur ASCII par seed n’existe”) et livrer en un jour
  • Le premier caractère du seed comme bouche — c’est le détail qui rend l’avatar personnel

Ce que je changerais :

  • Explorer les animations SVG pour donner vie aux avatars — un clin d’œil, une bouche qui bouge
  • Intégrer l’API dans d’autres projets pour tester son utilité réelle

The pitch

Seedmoji turns any string — email, username, UUID — into a unique, deterministic ASCII avatar. Same input, same face. Always. Zero APIs, zero storage, 100% client-side.

Try it: presque.cool/seedmoji/

Duration ~1 day
Period Feb 2026
Stack
React TypeScript PWA
Status ✓ In production

Why this project

There are many seed-based avatar generators — Identicon, MonsterID, Wavatars, Retro (by Gravatar), RoboHash… But none use ASCII characters to compose faces. After discovering Facehash by cossistant, I wanted to build my own version with more variability: more elements, more combinations, more expressiveness.

The result: little glyph faces that are often funny, sometimes weird, always unique.

One day of development, pure creative fun.


The glyph dictionary

The heart of Seedmoji is its character dictionary. I scoured Unicode reference sites and glyph tables to build a hand-picked catalogue:

  • 109 eye pairs — from classic ASCII (o,o ^,^ x,x) to geometric shapes (◉,◉ ★,☆), kaomoji (ಠ,ಠ ꖘ,ꖘ), and currency symbols (€,€ ¥,¥). Both symmetric and asymmetric.
  • 41 mouths — horizontal lines ( ), kaomoji curves (ω Д ), expressive shapes ( ).
  • 15 noses — displayed only with horizontal mouths to avoid visual overlap.
  • 32 frames — from classic brackets ([ ]) to CJK frames (「 」 【 】) and decorative ones (╭ ╮ ╔ ╗).
  • 16 background colors — a vibrant palette sourced from a graphic inspiration site.

This yields roughly 34 million unique combinations (not counting the 3 clipping shapes). Each seed produces a different, reproducible face.


The technical core: a deterministic hash

The algorithm relies on a simple hash, a variant of Java’s String.hashCode() (djb2-style):

seed → 32-bit hash → deterministic indices → face components

Why not SHA-256 or MD5?

  1. No security needed — we’re generating avatars, not authentication tokens
  2. Performance — djb2 runs ~10 operations per character vs ~1000+ for SHA-256. The avatar recalculates on every keystroke, the difference is noticeable
  3. Synchronicitycrypto.subtle.digest() is async. That would needlessly complicate the code
  4. Bundle size — the hash is 8 lines. Zero dependencies, zero polyfills

An interesting design detail: the first character of the seed determines the mouth. Typing a produces an avatar with a as its mouth. This creates an immediate visual link between input and output.

Text/background contrast is calculated automatically using perceived luminance (formula 0.299R + 0.587G + 0.114B): light background → black text, dark background → white text.


The embedding API

Seedmoji includes an /api/ endpoint that generates raw SVG via query params:

/seedmoji/api/?seed=tristan&shape=squircle&size=128

No server — the same React app detects the pathname and renders pure SVG instead of the interface. The SVG uses clipPath for shapes (square, squircle, round), while the React component uses CSS borderRadius.

Not yet used in production, but ready for integration into other projects.


Tech stack

  • React + TypeScript — Functional components, strict typing
  • Vite + SWC — Fast builds
  • Tailwind CSS — OKLch colors, dark mode
  • Zustand — State management, localStorage persistence
  • PWA — installable, offline, Workbox
  • i18n custom — French/English, automatic browser detection
  • Export SVG + PNG (512, 720, 1024px) via Canvas API
  • Compression — Brotli + Gzip on assets
  • CSP — Content-Security-Policy with auto-generated hashes

Timeline

DateVersionDescription
Feb 20261.0Initial version — Dictionary, hash, export, PWA

Takeaways

Duration: 1 day (February 2026).

What I learned:

  • That a carefully curated Unicode character dictionary can produce surprisingly expressive results — the ASCII constraint forces creativity
  • That an 8-line hash function is enough when you don’t need cryptographic security

What I’d do the same:

  • Start from a simple observation (“no ASCII seed-based generator exists”) and ship in one day
  • The first character of the seed as the mouth — it’s the detail that makes the avatar feel personal

What I’d change:

  • Explore SVG animations to bring the avatars to life — a wink, a moving mouth
  • Integrate the API into other projects to test its real-world usefulness

Settings

Language
Theme
Privacy Policy