gradient_avatars
Generative gradient avatars for Flutter. A unique gradient for every seed, with no stored images and no network.
A 1:1 Dart port of @outpacelabs/avatars
by Outpace Studios: the seeded RNG, string
hashing, and palette math replicate the original's JavaScript semantics
exactly, so a given seed produces the same palette here as it does on the
web - verified byte-for-byte by golden tests captured from the original
package.
Give it any string or number (a user id, an email, a username) and it paints a unique, good-looking mesh gradient. The same seed always yields the same gradient, so you get stable avatars with nothing to store and nothing to fetch.
Install
flutter pub add gradient_avatars
Usage
import 'package:gradient_avatars/gradient_avatars.dart';
Widget build(BuildContext context) {
return GradientAvatar(seed: user.id, size: 40);
}
That's the whole API surface for most apps. A few more:
GradientAvatar(seed: 'jane@example.com', size: 96) // circle (default)
GradientAvatar(seed: 'jane@example.com', size: 96, borderRadius: BorderRadius.circular(16)) // rounded square
GradientAvatar(seed: 'jane@example.com', size: 96, borderRadius: BorderRadius.zero) // square
For anything fancier than a rounded rectangle, pass a shape (any
ShapeBorder); it takes precedence over borderRadius.
Why gradient_avatars
- Deterministic. Same seed, same gradient, every time - and the same as the original React package, so web and Flutter apps sharing a backend show identical avatars.
- No images, no network. Rendered at runtime on a
Canvas. No CDN, no requests, no broken image links, no upload pipeline. - Zero dependencies. Only Flutter itself.
- Actually pretty. Soft mesh gradients, not blocky identicons.
- Any size, any shape. Circles, rounded squares, hard squares: your call.
- Exports anywhere. Built-in helpers turn a seed into a
ui.Imageor PNG bytes for downloads, uploads, and sharing.
GradientAvatar
| Parameter | Type | Default | Description |
|---|---|---|---|
seed |
Object (String or int) |
required | Any value; each unique seed is a unique gradient. |
size |
double |
32 |
Rendered size in logical pixels. |
borderRadius |
BorderRadius? |
null |
Rounds the corners into a rounded rectangle; pass BorderRadius.zero for a hard square. Ignored when shape is set. |
shape |
ShapeBorder? |
null |
Full control over the clip shape. When both shape and borderRadius are null, the avatar is a full circle. |
Beyond the widget: the engine
The framework-agnostic engine is exported too, so you can generate gradients
without rendering a widget - handy for exporting a profile picture, painting
inside your own CustomPainter, or just grabbing a seed's colors.
import 'package:gradient_avatars/gradient_avatars.dart';
// A 512×512 PNG. Save it, upload it, or hand it to Image.memory.
final Uint8List bytes = await gradientToPngBytes('jane@example.com', size: 512);
// Just the colors behind a seed.
final palette = GradientPalette.generate('jane@example.com');
print(palette.colors); // List<Color> stops, ready for Flutter
print(palette.hexColors); // uppercase #RRGGBB strings, identical to the web
print(palette.harmony); // which color-harmony rule produced the hues
| Helper | Description |
|---|---|
drawMeshGradient(canvas, seed, size) |
Paint the raw mesh into a dart:ui Canvas. |
renderGradientImage(seed, size:, blur:) |
Render a seed to a ui.Image with the signature soft blur baked in. |
gradientToPngBytes(seed, size:, blur:) |
Render and return encoded PNG bytes. |
GradientPalette.generate(seed) |
The colors and harmony rule behind a seed. |
seedFromString(input) / Seed.from(seed) |
The deterministic hashing that turns any value into a numeric seed. |
Types GradientPalette and Harmony, the GradientPaint widget and its
GradientPainter CustomPainter, and the defaultBlurFraction constant are
exported too.
Porting notes
The palette core (seedFromString, Seed.from, GradientPalette.generate) is
a line-by-line port that reproduces JavaScript's 32-bit integer semantics
(Math.imul, >>>, ToUint32) with masked arithmetic, exact on both the
Dart VM and the web. The render layer maps Canvas2D onto dart:ui - radial
gradient stops, compositing order, and blur procedure are identical; only
platform plumbing differs (PNG bytes instead of data URLs/Blobs, and no
Safari blur fallback since Flutter's image filters work everywhere).
License
Libraries
- gradient_avatars
- Generative gradient avatars for Flutter.