Your users are gems. Show it.

Deterministic gemstone avatars. Infinitely shimmering.

Create your own gem

Stable avatars for any platform

@m3000/hashed-gems is a React avatar component and hosted image API for generating deterministic gemstone avatars from any string seed. The same seed always resolves to the same avatar, which makes it useful for profiles, comments, communities, dashboards, and developer tools.

Use the interactive WebGL component when you want animated gemstone avatars in React or Next.js, or use the static PNG API when you need a canonical avatar URL for HTML, emails, tables, or social sharing. Each avatar includes stable gem traits such as rarity, gemstone type, and cut, all derived directly from the seed.

Installation

Install with your favourite package manager.

Usage

Import the component and pass any string as a seed.

Basic usageThe only required prop is seed — any string produces a unique, deterministic gem.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="alice" />
Sizesize sets the CSS display size in pixels. Default is 64px. Internally the gem renders at size × devicePixelRatio for crisp results on retina screens.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="bob" size={48} />
ResolutionPass resolution to override the WebGL canvas pixel count. Useful when you need a high-quality capture for sharing or exports — display size stays the same.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

// Displays at 96px, renders internally at 512px — sharp capture
<HashedGem seed="frank" size={96} resolution={512} />
Static modeDisable the shimmer animation for improved performance in lists or print contexts.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="carol" static />
Gem typeChoose from 12 predefined gemstone types — diamond, ruby, sapphire, and more.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="dave" gemType="emerald" />
Cut typeSelect from 7 different gem cuts - round-brilliant, princess, cushion, emerald-step, firework, jubilee, or rose.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="eve" cutType="rose" />
Custom stylingApply your own classes for border radius, borders, or shadows.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="hashed-gem" className="rounded-full border border-neutral-500 shadow-lg" />
AccessibilityUse aria-label when the gem should stand alone semantically, or aria-hidden when nearby text already identifies the user.
import "@m3000/hashed-gems/styles.css";
import { HashedGem } from "@m3000/hashed-gems";

<HashedGem seed="ada.lovelace" aria-label="Avatar for Ada Lovelace" />

<div>
  <HashedGem seed="ada.lovelace" aria-hidden={true} />
  <span>Ada Lovelace</span>
</div>

Image API

Use the hosted PNG API when you want a static gem image instead of the live WebGL component. Each seed resolves to one canonical `512x512` image.

Direct image URLRequest the canonical gem PNG for any seed. The API always resolves to a fixed 512x512 image.
GET https://gems.m3000.io/api/gems/marina
Use in HTMLDrop the endpoint straight into an img tag when you want a stable avatar URL for profiles, tables, or comments.
<img
  src="https://gems.m3000.io/api/gems/marina"
  alt="marina gem"
  width="64"
  height="64"
/>
Use in ReactThe endpoint works well as a static asset layer when the consumer does not need the live WebGL component.
function UserAvatar({ seed }: { seed: string }) {
  return (
    <img
      src={`https://gems.m3000.io/api/gems/${encodeURIComponent(seed)}`}
      alt={`${seed} gem`}
      width={64}
      height={64}
    />
  );
}