Building identicons with AI

For Evolu's upcoming collaboration, the local auth demo needed an identicon for OwnerId. While many identicon libraries exist, it's always better to avoid a dependency. Evolu has a strict rule for dependencies: avoid them as much as possible. Evolu uses only what's absolutely necessary: SQLite, crypto, MessagePack, and random.

So I decided to create Evolu's own identicons, which became a fun task to evaluate LLMs on something artistic 🎨.

GitHub identicon example 1GitHub identicon example 2
GitHub
Quadrant identicon example 1Quadrant identicon example 2
Quadrant
Gradient identicon example 1Gradient identicon example 2
Gradient
Sutnar identicon example 1Sutnar identicon example 2
Sutnar

The GitHub identicon challenge

Of course, Evolu could not omit the most famous identicon: the GitHub one. LLM created many seemingly functional GitHub identicons, but the code was an unreadable mess full of terrible bugs, so I started looking for an algorithm description, but there isn't one publicly available. Only a Rust library claiming it's based on the original code existed as reference, but it wasn't using SVG (which is a must for vectors because of performance). I really didn't want to spend much time on that. I was working on it before breakfast, as it was supposed to be a super quick task, but it could easily explode into days. So we (me and LLM) ported the basic algorithm which I was able to quickly review/refactor/fix.

The reality of AI-assisted coding

Programmers are actually not paid for the code they write, but for the code they read (and hopefully understand). While I use LLMs a lot, every line must be triple-checked. The more code we have, the more work we have. The less code the better.

While LLM and I made wonderful creations during our experimentation, I decided to commit only the most simple and readable identicon implementations. I didn't have time to refactor all the slop it generated.

  • "github" (default): 5x5 grid with horizontal mirroring (GitHub-style)
  • "quadrant": 2x2 grid with direct RGB color mapping from bytes
  • "gradient": Diagonal stripes with smooth color gradients
  • "sutnar": Three compositional variants with adaptive colors

As for sutnar, it's named after Ladislav Sutnar, the Czech graphic designer I love, who was a pioneer of information design and information architecture. Sutnar's work:

Here are all four identicon styles, each generated from 10 different owner IDs:

GitHub

GitHub identicon 0GitHub identicon 1GitHub identicon 2GitHub identicon 3GitHub identicon 4GitHub identicon 5GitHub identicon 6GitHub identicon 7GitHub identicon 8GitHub identicon 9

Quadrant

Quadrant identicon 0Quadrant identicon 1Quadrant identicon 2Quadrant identicon 3Quadrant identicon 4Quadrant identicon 5Quadrant identicon 6Quadrant identicon 7Quadrant identicon 8Quadrant identicon 9

Gradient

Gradient identicon 0Gradient identicon 1Gradient identicon 2Gradient identicon 3Gradient identicon 4Gradient identicon 5Gradient identicon 6Gradient identicon 7Gradient identicon 8Gradient identicon 9

Sutnar

Sutnar identicon 0Sutnar identicon 1Sutnar identicon 2Sutnar identicon 3Sutnar identicon 4Sutnar identicon 5Sutnar identicon 6Sutnar identicon 7Sutnar identicon 8Sutnar identicon 9

The implementation

Each identicon is deterministic: the same ID always generates the same visual representation.

const svg = createIdenticon(ownerId, "sutnar");

The function extracts bytes from the ID and uses them to deterministically generate colors, shapes, and compositions. No randomness, no external dependencies—just pure, predictable visual identity generation.

All identicons use SVG rather than Canvas. While Canvas can create truly artistic effects, we prefer simplicity and performance. SVG is lightweight and declarative, easily scalable without quality loss, and simpler to generate and cache.

Lessons learned

  1. AI is a tool, not a replacement: LLMs can accelerate exploration and generate ideas, but human judgment is essential for code quality.

  2. Simplicity wins: The most elegant solution often comes from understanding the problem deeply and implementing it simply, rather than accepting the first working solution.

  3. Art meets code: Bringing design principles (like Sutnar's constructivism) into algorithmic generation creates more meaningful visual results.