A unique crab for every account, generated from seven digits
Part of my Krabber series, a Twitter clone in Go. The full source is on GitHub.
Intro
Every account on Krabber gets its own little crab as an avatar, and no two are quite the same. There’s no uploading, no image processing, and no bucket full of avatar PNGs anywhere. Each crab is drawn as SVG from a short code, on the fly, and then cached at the edge. It’s one of my favorite small pieces of the project, so let me pull it apart.
I. A crab is seven digits
A crab’s whole look is a seven-digit trait code: one digit each for shell, pattern, eyes, claws, expression, accessory, and background. In Go it’s just this:
const (
Shells = 8
Patterns = 8
Eyes = 8
Claws = 6
Expressions = 6
Accessories = 10
Backgrounds = 6
CodeLen = 7
)
// Traits is one crab's look.
type Traits struct {
Shell, Pattern, Eyes, Claws, Expression, Accessory, Background int
}
Multiply those tables out and you get 8 x 8 x 8 x 6 x 6 x 10 x 6, which is about 1.1 million distinct crabs. Plenty for everyone to feel like they got their own, and small enough that the whole identity of a crab fits in seven characters.
II. The code is the picture
Here’s the part that makes it cheap. The SVG is built only from those trait tables, so the code completely determines the image. There’s no randomness at render time and no state to look up: give the drawer the same seven digits and you get back the exact same crab, every time.
That means the avatar is served from a URL that is the code:
GET /avatar/{code} -> the SVG for that crab
GET /banner/{code} -> a matching banner
Because the URL fully identifies the output, it’s content-addressed. The same code is always the same crab, forever, which has a lovely consequence for caching.
III. Why this is nearly free
I never store an avatar. There’s no S3 bucket of images, no upload pipeline, no thumbnailing, no image CDN bill. The crab is generated from the code when it’s asked for, and then CloudFront caches it at the edge. Since a given code always produces the same bytes, the cache can hold it essentially forever, so my origin draws each crab roughly once and the CDN serves it after that.
Compare that to the usual avatar setup: users upload images, you store and resize them, you serve them from object storage, and you worry about what people upload. Krabber sidesteps all of it. Changing your crab is just picking new trait values at /settings/avatar, which changes your code, which points at a different cached SVG. No file ever moves.
Conclusion
Generated avatars turned a feature that usually means storage, uploads, and moderation into seven digits and a drawing function. Over a million unique crabs, each one content-addressed so the CDN caches it forever, and not a single image file to keep. It fits the whole project’s habit of choosing the option that’s cheap and has no moving parts. If you need avatars and don’t need user photos, consider drawing them from a code instead of storing them. Thanks for reading, and may your crab be a handsome one.