solfaces 1.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +489 -97
  2. package/SKILL.md +171 -0
  3. package/dist/agent/index.cjs +15 -14
  4. package/dist/agent/index.js +5 -4
  5. package/dist/agent/mcp-server.cjs +2956 -287
  6. package/dist/chunk-6QRDULAO.cjs +191 -0
  7. package/dist/chunk-6QRDULAO.cjs.map +1 -0
  8. package/dist/{chunk-RX6D5FGH.js → chunk-77SPWQU5.js} +69 -28
  9. package/dist/chunk-77SPWQU5.js.map +1 -0
  10. package/dist/chunk-CQWXUU7P.js +239 -0
  11. package/dist/chunk-CQWXUU7P.js.map +1 -0
  12. package/dist/chunk-CXRVPOTI.cjs +244 -0
  13. package/dist/chunk-CXRVPOTI.cjs.map +1 -0
  14. package/dist/chunk-DRUSCLEF.js +177 -0
  15. package/dist/chunk-DRUSCLEF.js.map +1 -0
  16. package/dist/{chunk-VMNATBH3.cjs → chunk-F244Q4KC.cjs} +74 -33
  17. package/dist/chunk-F244Q4KC.cjs.map +1 -0
  18. package/dist/chunk-HVPGR6G5.cjs +647 -0
  19. package/dist/chunk-HVPGR6G5.cjs.map +1 -0
  20. package/dist/{chunk-SNJABBAT.js → chunk-MGP7F65H.js} +3 -3
  21. package/dist/{chunk-SNJABBAT.js.map → chunk-MGP7F65H.js.map} +1 -1
  22. package/dist/chunk-R3MC2AJZ.cjs +2247 -0
  23. package/dist/chunk-R3MC2AJZ.cjs.map +1 -0
  24. package/dist/chunk-SWML743U.js +625 -0
  25. package/dist/chunk-SWML743U.js.map +1 -0
  26. package/dist/chunk-SX3FQDKM.js +2238 -0
  27. package/dist/chunk-SX3FQDKM.js.map +1 -0
  28. package/dist/{chunk-A6N3RPEA.cjs → chunk-WTCXTXTV.cjs} +6 -6
  29. package/dist/{chunk-A6N3RPEA.cjs.map → chunk-WTCXTXTV.cjs.map} +1 -1
  30. package/dist/constants-Bi5uTRp5.d.cts +17 -0
  31. package/dist/constants-Bi5uTRp5.d.ts +17 -0
  32. package/dist/core/index.cjs +69 -29
  33. package/dist/core/index.d.cts +29 -47
  34. package/dist/core/index.d.ts +29 -47
  35. package/dist/core/index.js +3 -3
  36. package/dist/index.cjs +104 -35
  37. package/dist/index.d.cts +4 -2
  38. package/dist/index.d.ts +4 -2
  39. package/dist/index.js +6 -5
  40. package/dist/names/index.cjs +40 -0
  41. package/dist/names/index.cjs.map +1 -0
  42. package/dist/names/index.d.cts +36 -0
  43. package/dist/names/index.d.ts +36 -0
  44. package/dist/names/index.js +3 -0
  45. package/dist/names/index.js.map +1 -0
  46. package/dist/react/index.cjs +454 -397
  47. package/dist/react/index.cjs.map +1 -1
  48. package/dist/react/index.d.cts +17 -3
  49. package/dist/react/index.d.ts +17 -3
  50. package/dist/react/index.js +450 -394
  51. package/dist/react/index.js.map +1 -1
  52. package/dist/solfaces.cdn.global.js +2 -2
  53. package/dist/solfaces.cdn.global.js.map +1 -1
  54. package/dist/themes/index.cjs +29 -17
  55. package/dist/themes/index.d.cts +10 -7
  56. package/dist/themes/index.d.ts +10 -7
  57. package/dist/themes/index.js +1 -1
  58. package/dist/{traits-DAFZnXeS.d.cts → traits-QlWuxZDD.d.cts} +45 -1
  59. package/dist/{traits-DAFZnXeS.d.ts → traits-QlWuxZDD.d.ts} +45 -1
  60. package/dist/vanilla/index.cjs +20 -8
  61. package/dist/vanilla/index.cjs.map +1 -1
  62. package/dist/vanilla/index.d.cts +1 -1
  63. package/dist/vanilla/index.d.ts +1 -1
  64. package/dist/vanilla/index.js +17 -5
  65. package/dist/vanilla/index.js.map +1 -1
  66. package/package.json +22 -5
  67. package/python/solfaces.py +830 -237
  68. package/reference/integrations.md +166 -0
  69. package/reference/react.md +108 -0
  70. package/reference/themes.md +124 -0
  71. package/dist/chunk-2DIKGLXZ.cjs +0 -126
  72. package/dist/chunk-2DIKGLXZ.cjs.map +0 -1
  73. package/dist/chunk-CVFO7YHY.cjs +0 -97
  74. package/dist/chunk-CVFO7YHY.cjs.map +0 -1
  75. package/dist/chunk-H3SK3MNX.cjs +0 -409
  76. package/dist/chunk-H3SK3MNX.cjs.map +0 -1
  77. package/dist/chunk-KSGFMW33.js +0 -401
  78. package/dist/chunk-KSGFMW33.js.map +0 -1
  79. package/dist/chunk-LQWJRHGC.js +0 -86
  80. package/dist/chunk-LQWJRHGC.js.map +0 -1
  81. package/dist/chunk-RX6D5FGH.js.map +0 -1
  82. package/dist/chunk-VMNATBH3.cjs.map +0 -1
  83. package/dist/chunk-WURY4QGH.js +0 -117
  84. package/dist/chunk-WURY4QGH.js.map +0 -1
  85. package/skill.md +0 -463
package/README.md CHANGED
@@ -1,22 +1,36 @@
1
- # SolFaces
1
+ # SolFaces
2
2
 
3
- **Deterministic wallet avatars for the Solana ecosystem.**
3
+ [![npm version](https://img.shields.io/npm/v/solfaces)](https://www.npmjs.com/package/solfaces)
4
+ [![npm downloads](https://img.shields.io/npm/dw/solfaces)](https://www.npmjs.com/package/solfaces)
5
+ [![license](https://img.shields.io/npm/l/solfaces)](https://github.com/jorger3301/SolFaces/blob/main/LICENSE)
6
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/solfaces)](https://bundlephobia.com/package/solfaces)
4
7
 
5
- Every Solana wallet address generates a unique, consistent face — no API calls, no storage, no randomness. Same wallet = same face, everywhere, forever.
8
+ **Deterministic wallet avatars and names for the Solana ecosystem.**
9
+
10
+ Every Solana wallet address generates a unique, consistent face and a deterministic name — no API calls, no storage, no randomness. Same wallet = same face, same name, everywhere, forever.
6
11
 
7
12
  Built for dApps, AI agents, social features, leaderboards, and anywhere a wallet needs a visual identity.
8
13
 
14
+ ![SolFaces theme showcase showing Default, Light, Dark, and Mono rendering modes](solfaces-themes-labeled.png)
15
+
16
+ *Default, Light, Dark, and Mono — four of the 11 built-in themes. Each row shows the same 10 wallets rendered in a different theme.*
17
+
9
18
  ---
10
19
 
11
20
  ## Why SolFaces?
12
21
 
13
22
  - **Deterministic** — Same wallet always produces the same avatar. No database needed.
14
23
  - **Zero dependencies** — Core engine has no runtime dependencies.
15
- - **~221M unique faces** — 11 traits with multiple variants = massive combination space.
24
+ - **~2.56B unique faces** — 11 traits with expanded ranges = massive combination space.
25
+ - **SolNames** — Every wallet gets a deterministic, human-friendly name derived via SHA-256 (e.g. "SunnyIcon"). ~1M display names, ~65.5B unique tags.
26
+ - **11 built-in themes** — Default, Dark, Light, Mono, Flat, Transparent, plus 3 Pixel and 2 Glass themes (React).
27
+ - **Gradient-rich rendering** — Skin-luminance-driven colors, specular highlights, cheek blush, gradient hair, glow overlays.
16
28
  - **Works everywhere** — React, vanilla JS, Node, Python, CDN script tag, edge functions.
17
- - **Fully customizable** — Every color, every feature. Themes, per-instance overrides, animation timing — adapt every detail to match your UI, your brand, or your users' preferences.
18
- - **Eliminates dead space** — No more blank avatars or generic placeholders. Every wallet gets a unique face instantly, elevating your dApp or website UI even when users never upload a profile picture.
19
- - **AI-agent ready** — Natural language self-descriptions for agent system prompts.
29
+ - **Flat mode** — Disable all gradients for simplified rendering.
30
+ - **Detail levels** — Full detail (gradients, specular, cheeks) at size >= 48, simplified below.
31
+ - **Fully customizable** — Every visual element is customizable: 4 color palettes, 8 individual color overrides, 9 per-instance color keys, rendering toggles, layout controls, blink timing, and 30+ React-only pixel/glass fields. No visual element is locked — if you can see it, you can theme it.
32
+ - **Eliminates dead space** — No more blank avatars or generic placeholders. Every wallet gets a unique face instantly.
33
+ - **AI-agent ready** — AI trading bots and autonomous agents are becoming on-chain users. SolFaces gives every agent a recognizable face and a natural language self-description for system prompts and bios.
20
34
  - **PNG rasterization** — Serve real image files for bots, Discord, Telegram, OG images.
21
35
  - **SSR-ready** — String renderer works server-side with zero browser APIs.
22
36
 
@@ -57,6 +71,25 @@ function UserProfile({ walletAddress }) {
57
71
  }
58
72
  ```
59
73
 
74
+ ### Pixel Art Mode (React)
75
+
76
+ ```tsx
77
+ import { SolFace } from "solfaces/react";
78
+ import { pixelTheme, pixelRetroTheme } from "solfaces/themes";
79
+
80
+ <SolFace walletAddress="7xKXqR..." size={64} theme={pixelTheme} />
81
+ <SolFace walletAddress="7xKXqR..." size={64} theme={pixelRetroTheme} />
82
+ ```
83
+
84
+ ### Liquid Glass Mode (React)
85
+
86
+ ```tsx
87
+ import { SolFace } from "solfaces/react";
88
+ import { glassTheme, glassDarkTheme } from "solfaces/themes";
89
+
90
+ <SolFace walletAddress="7xKXqR..." size={64} theme={glassTheme} />
91
+ ```
92
+
60
93
  ### Vanilla JS (npm)
61
94
 
62
95
  ```js
@@ -69,6 +102,8 @@ mountSolFace("#avatar", "7xKXqR...", { size: 48 });
69
102
 
70
103
  ```html
71
104
  <div data-solface="7xKXqR..." data-solface-size="48" data-solface-theme="dark"></div>
105
+ <div data-solface="DRpbCBMx..." data-solface-flat="true"></div>
106
+ <div data-solface="9WzDXwBb..." data-solface-detail="full"></div>
72
107
 
73
108
  <script src="https://unpkg.com/solfaces/dist/solfaces.cdn.global.js"></script>
74
109
  <!-- Auto-initializes on DOMContentLoaded -->
@@ -80,6 +115,24 @@ mountSolFace("#avatar", "7xKXqR...", { size: 48 });
80
115
  </script>
81
116
  ```
82
117
 
118
+ ### Name Derivation (SolNames)
119
+
120
+ ```ts
121
+ import { deriveName, deriveIdentity } from "solfaces";
122
+
123
+ deriveName("7xKXqR...");
124
+ // → "SunnyIcon" (deterministic, SHA-256 derived)
125
+
126
+ deriveName("7xKXqR...", "tag");
127
+ // → "SunnyIcon#2f95" (unique identifier)
128
+
129
+ deriveName("7xKXqR...", "full");
130
+ // → "SunnyIcon-InfiniteOre" (formal contexts)
131
+
132
+ const id = deriveIdentity("7xKXqR...");
133
+ // → { short, name, tag, full, adjective, noun, hash, discriminator }
134
+ ```
135
+
83
136
  ### Node / SSR / Edge
84
137
 
85
138
  ```ts
@@ -92,18 +145,157 @@ const svg = renderSolFaceSVG("7xKXqR...", { size: 128 });
92
145
  ### Python
93
146
 
94
147
  ```python
95
- from solfaces import generate_traits, render_svg, describe_appearance
148
+ from solfaces import generate_traits, render_svg, describe_appearance, derive_name
96
149
 
97
150
  traits = generate_traits("7xKXqR...")
98
151
  svg = render_svg("7xKXqR...", size=256)
99
152
  desc = describe_appearance("7xKXqR...")
153
+ name = derive_name("7xKXqR...")
154
+ ```
155
+
156
+ ---
157
+
158
+ ## SolNames — Deterministic Name Derivation
159
+
160
+ Every wallet gets a deterministic, human-friendly name derived via SHA-256 hashing and curated word lists. Nothing like this exists on any blockchain — every other naming system (SNS, ENS, Unstoppable Domains) requires purchase. SolNames derives names automatically — zero registration, zero storage, just math.
161
+
162
+ ```
163
+ Wallet: 7PjJ2AHq9BMXWYjt3qqeKwZVLXHYFPmHRYrMF6PpRySD
164
+
165
+
166
+ SHA-256("solnames-v1:" + wallet) → 32 bytes
167
+
168
+ ├─→ Bytes 0-3: seed PRNG → adjective + noun
169
+ └─→ Bytes 8-9: hex discriminator → "2f95"
170
+
171
+ Display: WavingMistral
172
+ Tag: WavingMistral#2f95
173
+ ```
174
+
175
+ ### Name Formats
176
+
177
+ | Format | Example | Unique Names | Use Case |
178
+ |---------|------------------------------|-------------|-----------------------------|
179
+ | short | "Waving" | 1,000 | Tight UIs, badges |
180
+ | display | "WavingMistral" | ~1,000,000 | Default — profiles, feeds |
181
+ | tag | "WavingMistral#2f95" | ~65.5B | Unique identifier |
182
+ | full | "WavingMistral-InfiniteOre" | ~1T | Formal contexts |
183
+
184
+ ### Usage
185
+
186
+ ```ts
187
+ import { deriveName, deriveIdentity } from "solfaces";
188
+ // or: import { deriveName } from "solfaces/names";
189
+
190
+ deriveName("7xKXqR..."); // → "SunnyIcon" (display format)
191
+ deriveName("7xKXqR...", "short"); // → "Sunny"
192
+ deriveName("7xKXqR...", "tag"); // → "SunnyIcon#2f95"
193
+ deriveName("7xKXqR...", "full"); // → "SunnyIcon-InfiniteOre"
194
+
195
+ const id = deriveIdentity("7xKXqR...");
196
+ // → { short, name, tag, full, adjective, noun, hash, discriminator }
197
+ ```
198
+
199
+ ### React Hook
200
+
201
+ ```tsx
202
+ import { useSolName } from "solfaces/react";
203
+
204
+ function Profile({ wallet }) {
205
+ const name = useSolName(wallet, "display"); // string
206
+ const identity = useSolName(wallet); // full SolNameIdentity
207
+ return <span>{name}</span>;
208
+ }
209
+ ```
210
+
211
+ ### Show Name with Avatar
212
+
213
+ ```tsx
214
+ import { SolFace } from "solfaces/react";
215
+
216
+ <SolFace walletAddress="7xKXqR..." showName />
217
+ <SolFace walletAddress="7xKXqR..." showName namePosition="above" nameFormat="tag" />
218
+ ```
219
+
220
+ ### Validation
221
+
222
+ ```ts
223
+ import { isValidSolName, parseSolName } from "solfaces/names";
224
+
225
+ isValidSolName("SunnyIcon"); // true
226
+ isValidSolName("SunnyIcon#2f95"); // true
227
+ parseSolName("SunnyIcon#2f95");
228
+ // → { adjective: "Sunny", noun: "Icon", discriminator: "2f95" }
229
+ ```
230
+
231
+ - **1000 adjectives + 1000 nouns** — curated positive/neutral PascalCase words
232
+ - **Same name everywhere** — TypeScript, Python, CDN, and server all produce identical output
233
+ - **Blocked combinations** — offensive adjective+noun pairs are automatically skipped
234
+
235
+ ---
236
+
237
+ ## Rendering Modes
238
+
239
+ ### Full Detail vs Simplified
240
+
241
+ SolFaces automatically adjusts detail based on size:
242
+
243
+ - **Full detail** (size >= 48): Gradient fills, specular highlights on eyes, cheek blush, chin shadow, face glow, eyelid strokes, jawline hints.
244
+ - **Simplified** (size < 48): Flat shapes optimized for small sizes — no gradients, no cheeks, no specular.
245
+
246
+ Override with the `detail` option:
247
+
248
+ ```ts
249
+ renderSolFaceSVG("7xKXqR...", { detail: "full" }); // Force full detail at any size
250
+ renderSolFaceSVG("7xKXqR...", { detail: "simplified" }); // Force simplified
251
+ renderSolFaceSVG("7xKXqR...", { detail: "auto" }); // Default — based on size
252
+ ```
253
+
254
+ ### Flat Mode
255
+
256
+ Disable all gradients globally. Useful for print, email clients, or minimal UIs:
257
+
258
+ ```ts
259
+ import { flatTheme } from "solfaces/themes";
260
+
261
+ renderSolFaceSVG("7xKXqR...", { theme: flatTheme });
262
+ // Zero <linearGradient> or <radialGradient> elements in output
263
+ ```
264
+
265
+ Or set `flat: true` on any theme:
266
+
267
+ ```ts
268
+ renderSolFaceSVG("7xKXqR...", { theme: { flat: true } });
269
+ ```
270
+
271
+ ### Pixel Art Mode (React Only)
272
+
273
+ Renders the SVG at a low pixel density then scales up with `image-rendering: pixelated`:
274
+
275
+ ```tsx
276
+ import { pixelTheme, pixelRetroTheme, pixelCleanTheme } from "solfaces/themes";
277
+
278
+ <SolFace walletAddress="7xKXqR..." theme={pixelTheme} /> // 16px density, rounded
279
+ <SolFace walletAddress="7xKXqR..." theme={pixelRetroTheme} /> // 12px + scanlines + shadow
280
+ <SolFace walletAddress="7xKXqR..." theme={pixelCleanTheme} /> // 24px, clean
281
+ ```
282
+
283
+ ### Liquid Glass Mode (React Only)
284
+
285
+ Backdrop-blur glass effect with specular highlights and rim lighting:
286
+
287
+ ```tsx
288
+ import { glassTheme, glassDarkTheme } from "solfaces/themes";
289
+
290
+ <SolFace walletAddress="7xKXqR..." theme={glassTheme} />
291
+ <SolFace walletAddress="7xKXqR..." theme={glassDarkTheme} />
100
292
  ```
101
293
 
102
294
  ---
103
295
 
104
296
  ## AI Agent Identity
105
297
 
106
- SolFaces gives AI agents a visual identity tied to their wallet. The `describeAppearance()` function generates natural language descriptions agents can use in system prompts to know and reference what they look like.
298
+ AI trading bots, autonomous agents, and on-chain programs are becoming users — they need a visual identity, a personality, and a recognizable presence. SolFaces gives every agent a deterministic face tied to their wallet, plus natural language self-descriptions they can use in system prompts to know and reference what they look like.
107
299
 
108
300
  ### System Prompt Integration
109
301
 
@@ -112,11 +304,11 @@ import { agentAppearancePrompt } from "solfaces";
112
304
 
113
305
  const appearance = agentAppearancePrompt("7xKXqR...", "Atlas");
114
306
  // → "My visual identity is a SolFace avatar (ID: a3f2b1c0) derived from
115
- // my wallet address. I'm Atlas. I have a round face with light peach skin,
116
- // wide and expressive blue eyes with elegantly arched eyebrows, and tall,
117
- // spiky Solana mint green hair. I'm wearing round glasses. I have a
118
- // confident smirk. This appearance is deterministic — anyone who looks up
119
- // my wallet will see the same face."
307
+ // my wallet address. I'm Atlas. I have a squircle face with warm golden skin,
308
+ // almond-shaped hazel eyes with gently curved eyebrows, and flowing
309
+ // auburn wavy hair. I'm wearing aviator sunglasses. I have a playful grin.
310
+ // This appearance is deterministic — anyone who looks up my wallet will
311
+ // see the same face."
120
312
 
121
313
  const systemPrompt = `You are Atlas, a DeFi trading agent. ${appearance}`;
122
314
  ```
@@ -134,11 +326,11 @@ describeAppearance("7xKXqR...", { format: "paragraph", perspective: "first", nam
134
326
 
135
327
  // Structured (for data display)
136
328
  describeAppearance("7xKXqR...", { format: "structured" });
137
- // → "Face: round\nSkin: light peach\nEyes: wide and expressive, blue\n..."
329
+ // → "Face: squircle\nSkin: warm golden\nEyes: almond-shaped, hazel\n..."
138
330
 
139
331
  // Compact (for alt text, captions)
140
332
  describeAppearance("7xKXqR...", { format: "compact" });
141
- // → "round face, light peach skin, blue wide eyes, spiky mint hair, round glasses, smirking"
333
+ // → "squircle face, warm golden skin, hazel almond eyes, wavy auburn hair, aviator sunglasses, grinning"
142
334
  ```
143
335
 
144
336
  ### Alt Text & Accessibility
@@ -147,7 +339,7 @@ describeAppearance("7xKXqR...", { format: "compact" });
147
339
  import { solFaceAltText } from "solfaces";
148
340
 
149
341
  const alt = solFaceAltText("7xKXqR...");
150
- // → "SolFace avatar: round face, light peach skin, blue wide eyes, ..."
342
+ // → "SolFace avatar: squircle face, warm golden skin, hazel almond eyes, ..."
151
343
  ```
152
344
 
153
345
  ### Python (AI Agent Backends)
@@ -206,36 +398,69 @@ const dataUrl = await renderSolFacePNGDataURL("7xKXqR...", { pngSize: 256 });
206
398
 
207
399
  ## Themes
208
400
 
209
- SolFaces is fully customizable to your UI. Every visual element — skin, eyes, hair, mouth, eyebrows, nose, accessories, background, border, and even eye white/teeth color — can be themed globally or overridden per instance. Use a preset, extend one, or build your own from scratch. You can also use `colorOverrides` to change individual colors on a specific avatar without affecting the theme.
401
+ SolFaces ships with 11 preset themes. Themes control colors, gradients, borders, rendering modes, and more.
210
402
 
211
403
  ### Available Presets
212
404
 
213
- | Theme | Description |
214
- |-------|-------------|
215
- | `solanaTheme` | Defaultvibrant Solana colors (#14F195, #9945FF) |
216
- | `darkTheme` | Muted tones on dark backgrounds |
217
- | `lightTheme` | Soft pastels for white/light UIs |
218
- | `monoTheme` | Grayscale onlyminimal interfaces |
219
- | `neonTheme` | High-contrast cyberpunk vibes |
220
- | `jupiterTheme` | Matches Jupiter aggregator's palette |
221
- | `phantomTheme` | Phantom wallet's purple style |
222
- | `circleTheme` | Full border-radius for circular avatars |
405
+ | Theme | Description | Works In |
406
+ |-------|-------------|----------|
407
+ | `default` | Base look with gradient-rich rendering no overrides | All renderers |
408
+ | `dark` | Dark backgrounds with muted tones and subtle border | All renderers |
409
+ | `light` | Soft pastel backgrounds with rounded corners | All renderers |
410
+ | `mono` | Full grayscaleall colors replaced with grays | All renderers |
411
+ | `flat` | Disables all gradients — flat fill colors only | All renderers |
412
+ | `transparent` | Transparent background with flat rendering | All renderers |
413
+ | `glass` | Liquid glass effect with backdrop blur and specular highlights | React only |
414
+ | `glassDark` | Dark variant of liquid glass with deeper blur | React only |
415
+ | `pixel` | Pixel art mode at 16px density with rounded corners | React only |
416
+ | `pixelRetro` | Retro pixel art with scanlines and drop shadow | React only |
417
+ | `pixelClean` | Clean pixel art at 24px density | React only |
418
+
419
+ ### Using Themes
420
+
421
+ ```ts
422
+ import { renderSolFaceSVG } from "solfaces";
423
+ import { darkTheme } from "solfaces/themes";
424
+
425
+ const svg = renderSolFaceSVG("7xKXqR...", { theme: darkTheme });
426
+ ```
223
427
 
224
428
  ### Custom Themes
225
429
 
430
+ Every visual element is customizable through the theme system — color palettes, individual colors, rendering toggles, layout, and more. All fields are optional; only override what you need.
431
+
226
432
  ```ts
433
+ import type { SolFaceTheme } from "solfaces";
434
+
227
435
  const myTheme: SolFaceTheme = {
228
- skinColors: ["#ffd5b0", "#f4c794", "#e0a370", "#c68642", "#8d5524", "#4a2c17"],
229
- eyeColors: ["#333", "#4a80c4", "#5a9a5a"],
230
- hairColors: ["#1a1a1a", "#6b3a2a", "#d4a844", "#ff6b6b", "#4ecdc4", "#45b7d1"],
231
- bgColors: ["#1a1b23", "#2d1b69", "#0a2463"],
436
+ // Color palettes (arrays one color per trait variant)
437
+ skinColors: ["#fce4d4", "#f5d0b0", "#e8b88a", "#d4956a", "#b5724a", "#8d5524", "#6b3f1d", "#4a2c17", "#3a1f10", "#2a1008"],
438
+ eyeColors: ["#333", "#4a80c4", "#5a9a5a", "#c89430", "#8a8a8a"],
439
+ hairColors: ["#1a1a1a", "#4a3728", "#8b6b4a", "#c44a20", "#d4a844", "#6090e0", "#14F195", "#e040c0", "#ff6b6b", "#4ecdc4"],
440
+ bgColors: ["#14F195", "#4a90e2", "#9945FF", "#f0e68c", "#e06070", "#ff8c42", "#5bc0be", "#8338ec", "#ff006e", "#3a86ff"],
441
+
442
+ // Individual color overrides
232
443
  mouthColor: "#e06070",
233
444
  eyebrowColor: "#aaa",
234
- accessoryColor: "#888",
235
- eyeWhiteColor: "#e0e0e0", // Sclera color (great for dark themes)
236
- noseColor: "#c68642aa", // Nose color (defaults to skin + transparency)
445
+ accessoryColor: "#888", // Default glasses/earring/headband color
446
+ eyeWhiteColor: "#e0e0e0", // Sclera + teeth color (important for dark themes)
447
+ noseColor: "#c68642aa", // Nose color (defaults to skin-derived)
448
+ glassesColor: "#333", // Glasses frame color (overrides accessoryColor)
449
+ earringColor: "#ffd700", // Earring color (overrides accessoryColor)
450
+ headbandColor: "#e04080", // Headband color (overrides accessoryColor)
451
+
452
+ // Rendering control
453
+ flat: false, // Set true to disable all gradients
454
+ cheekEnabled: true, // Enable/disable cheek blush
455
+ cheekColor: "#ff8080", // Custom cheek color
456
+ cheekOpacity: 0.3, // Cheek blush opacity
457
+ skinOpacity: 1, // Skin fill opacity
458
+ shadowEnabled: true, // Enable/disable chin shadow
459
+ glowIntensity: 0.15, // Face glow strength
460
+
461
+ // Layout
237
462
  bgOpacity: 1,
238
- bgRadius: 999,
463
+ bgRadius: 14,
239
464
  border: { color: "#14F195", width: 2 },
240
465
  };
241
466
  ```
@@ -248,25 +473,98 @@ import { getPresetTheme } from "solfaces/themes";
248
473
  const myTheme = getPresetTheme("dark", {
249
474
  bgRadius: 999,
250
475
  border: { color: "#14F195", width: 1 },
476
+ eyeWhiteColor: "#d0c8c0", // Warmer eye whites for dark mode
251
477
  });
252
478
  ```
253
479
 
254
- ### Per-Instance Color Overrides
255
-
256
- Override any color on a specific avatar without changing the global theme:
257
-
258
- ```tsx
259
- // React
260
- <SolFace walletAddress="7xKXqR..." colorOverrides={{ hair: "#ff0000", bg: "#000" }} />
261
-
262
- // String renderer
263
- renderSolFaceSVG("7xKXqR...", {
264
- theme: darkTheme,
265
- colorOverrides: { skin: "#ffd5b0", eyes: "#00ff00", accessory: "#gold" },
266
- });
267
- ```
268
-
269
- Available override keys: `skin`, `eyes`, `hair`, `bg`, `mouth`, `eyebrow`, `accessory`, `nose`, `eyeWhite`.
480
+ ### Theme Field Reference
481
+
482
+ **Color palettes** (arrays one per trait variant):
483
+
484
+ | Field | Type | What it controls |
485
+ |-------|------|-----------------|
486
+ | `skinColors` | `string[]` | 10 skin tone colors |
487
+ | `eyeColors` | `string[]` | 5 iris/pupil colors |
488
+ | `hairColors` | `string[]` | 10 hair fill colors |
489
+ | `bgColors` | `string[]` | 10 background fill colors |
490
+
491
+ **Individual color overrides:**
492
+
493
+ | Field | Type | What it controls |
494
+ |-------|------|-----------------|
495
+ | `mouthColor` | `string` | Mouth stroke/fill |
496
+ | `eyebrowColor` | `string` | Eyebrow stroke |
497
+ | `accessoryColor` | `string` | Default accessory color (glasses, earring, headband) |
498
+ | `eyeWhiteColor` | `string` | Sclera (eye white) and teeth color — set for dark themes |
499
+ | `noseColor` | `string` | Nose color (defaults to skin-derived + transparency) |
500
+ | `glassesColor` | `string` | Glasses frame color (overrides accessoryColor) |
501
+ | `earringColor` | `string` | Earring color (overrides accessoryColor) |
502
+ | `headbandColor` | `string` | Headband color (overrides accessoryColor) |
503
+
504
+ **Rendering control:**
505
+
506
+ | Field | Type | What it controls |
507
+ |-------|------|-----------------|
508
+ | `flat` | `boolean` | Disable all gradients (flat fill colors only) |
509
+ | `cheekEnabled` | `boolean` | Enable/disable cheek blush |
510
+ | `cheekColor` | `string` | Custom cheek color |
511
+ | `cheekOpacity` | `number` | Cheek blush opacity (0-1) |
512
+ | `skinOpacity` | `number` | Skin fill opacity (0-1) |
513
+ | `shadowEnabled` | `boolean` | Enable/disable chin shadow and face overlays |
514
+
515
+ **Layout:**
516
+
517
+ | Field | Type | What it controls |
518
+ |-------|------|-----------------|
519
+ | `bgOpacity` | `number` | Background opacity (0-1) |
520
+ | `bgRadius` | `number` | SVG rect border radius (999 = circle) |
521
+ | `border` | `{ color, width }` | Optional border around avatar |
522
+
523
+ ### Pixel Art Customization (React Only)
524
+
525
+ All `_pixel*` fields are React-only. Set `_pixel: true` to enable pixel art mode.
526
+
527
+ | Field | Type | Default | What it controls |
528
+ |-------|------|---------|-----------------|
529
+ | `_pixel` | `boolean` | `false` | Enable pixel art mode |
530
+ | `_pixelDensity` | `number` | `16` | Render resolution before upscale (lower = blockier) |
531
+ | `_pixelRounded` | `boolean` | `true` | Rounded corners on pixel container |
532
+ | `_pixelOutline` | `boolean` | `false` | Draw outline around pixel art |
533
+ | `_pixelOutlineColor` | `string` | `"#000"` | Outline color |
534
+ | `_pixelOutlineWidth` | `number` | `1` | Outline width in pixels |
535
+ | `_pixelContrast` | `number` | — | CSS contrast filter |
536
+ | `_pixelSaturation` | `number` | — | CSS saturation filter |
537
+ | `_pixelBrightness` | `number` | — | CSS brightness filter |
538
+ | `_pixelScanlines` | `boolean` | `false` | Horizontal scanline overlay |
539
+ | `_pixelScanlineOpacity` | `number` | `0.08` | Scanline opacity |
540
+ | `_pixelScanlineSpacing` | `number` | `2` | Scanline spacing in pixels |
541
+ | `_pixelGrid` | `boolean` | `false` | Pixel grid overlay |
542
+ | `_pixelGridOpacity` | `number` | — | Grid opacity |
543
+ | `_pixelGridColor` | `string` | — | Grid color |
544
+ | `_pixelShadow` | `boolean` | `false` | Drop shadow behind pixel art |
545
+ | `_pixelShadowColor` | `string` | `"rgba(0,0,0,0.3)"` | Shadow color |
546
+ | `_pixelShadowOffset` | `number` | `2` | Shadow offset in pixels |
547
+
548
+ ### Liquid Glass Customization (React Only)
549
+
550
+ All glass fields are React-only. Set `_glass: true` to enable liquid glass mode.
551
+
552
+ | Field | Type | Default | What it controls |
553
+ |-------|------|---------|-----------------|
554
+ | `_glass` | `boolean` | `false` | Enable liquid glass mode |
555
+ | `_blurRadius` | `number` | `12` | Backdrop blur radius |
556
+ | `_saturate` | `number` | `1.8` | Backdrop saturation multiplier |
557
+ | `_tintColor` | `string` | `"rgba(255,255,255,1)"` | Glass tint color |
558
+ | `_tintOpacity` | `number` | `0.12` | Glass tint opacity |
559
+ | `_borderColor` | `string` | `"rgba(255,255,255,0.25)"` | Glass border color |
560
+ | `_borderWidth` | `number` | `1` | Glass border width |
561
+ | `_borderOpacity` | `number` | `0.25` | Glass border opacity |
562
+ | `_specularColor` | `string` | `"rgba(255,255,255,1)"` | Specular highlight color |
563
+ | `_specularOpacity` | `number` | `0.25` | Specular highlight strength |
564
+ | `_specularEnd` | `number` | `50` | Specular gradient end (%) |
565
+ | `_lightAngle` | `number` | `135` | Light source angle (degrees) |
566
+ | `_rimIntensity` | `number` | `0.08` | Rim lighting intensity |
567
+ | `_shadow` | `string` | `"0 8px 32px rgba(0,0,0,0.12)"` | CSS box-shadow |
270
568
 
271
569
  ---
272
570
 
@@ -296,9 +594,10 @@ const result = await handleToolCall("generate_solface_svg", {
296
594
  |------|-------------|
297
595
  | `generate_solface_svg` | Render SVG avatar from wallet address |
298
596
  | `describe_solface` | Natural language description of an avatar |
299
- | `get_solface_traits` | Raw trait data with labels and hash |
597
+ | `get_solface_traits` | Raw trait data with labels, hash, and name |
300
598
  | `get_agent_identity` | System prompt snippet for AI agent identity |
301
599
  | `list_solface_themes` | List available preset themes |
600
+ | `derive_solname` | Deterministic name from wallet via SHA-256 |
302
601
 
303
602
  ### MCP Server (Claude Code / Cursor)
304
603
 
@@ -327,14 +626,7 @@ import {
327
626
 
328
627
  ### Skill File for AI Agents
329
628
 
330
- SolFaces includes a comprehensive `skill.md` that teaches AI agents how to integrate, customize, and use SolFaces. Feed it to any agent (Claude, GPT, custom bots) as context:
331
-
332
- - How to install and import for any platform
333
- - React component usage with themes, animations, and styling
334
- - Server-side rendering and API route patterns
335
- - Custom theme creation to match any UI
336
- - Bot integration (Discord, Telegram)
337
- - All 5 tool definitions with parameters and usage guidance
629
+ SolFaces includes a comprehensive `SKILL.md` (with 3 reference files in `reference/`) that teaches AI agents how to integrate, customize, and use SolFaces. Feed it to any agent (Claude, GPT, custom bots) as context.
338
630
 
339
631
  ---
340
632
 
@@ -356,14 +648,15 @@ Templates included for: **Next.js App Router**, **Express**, **Hono (Cloudflare
356
648
 
357
649
  ## Python Port
358
650
 
359
- Full Python implementation with identical trait generation to JavaScript. Zero dependencies.
651
+ Full Python implementation with identical trait generation to JavaScript. Zero dependencies. Includes gradient-rich rendering matching the TypeScript renderer.
360
652
 
361
653
  ```python
362
- from solfaces import generate_traits, render_svg, describe_appearance
654
+ from solfaces import generate_traits, render_svg, describe_appearance, derive_name
363
655
 
364
656
  traits = generate_traits("7xKXqR...")
365
657
  svg = render_svg("7xKXqR...", size=256)
366
658
  desc = describe_appearance("7xKXqR...")
659
+ name = derive_name("7xKXqR...")
367
660
  prompt = agent_appearance_prompt("7xKXqR...", "Atlas")
368
661
  ```
369
662
 
@@ -375,8 +668,11 @@ python solfaces.py 7xKXqR... --svg # Output SVG
375
668
  python solfaces.py 7xKXqR... --json # Output JSON
376
669
  python solfaces.py 7xKXqR... --describe # Natural language
377
670
  python solfaces.py 7xKXqR... --svg --size 512 # Custom size
671
+ python solfaces.py 7xKXqR... --svg --flat # Flat mode (no gradients)
378
672
  ```
379
673
 
674
+ > **Note:** Pixel art and liquid glass modes are React-only (CSS-dependent) and not available in the Python port.
675
+
380
676
  ---
381
677
 
382
678
  ## CDN / Script Tag
@@ -390,6 +686,8 @@ For sites without a build step — Webflow, Notion embeds, plain HTML, WordPress
390
686
  <div data-solface="7xKXqR..." data-solface-size="48"></div>
391
687
  <div data-solface="DRpbCBMx..." data-solface-size="48" data-solface-theme="dark"></div>
392
688
  <div data-solface="9WzDXwBb..." data-solface-blink="true"></div>
689
+ <div data-solface="Abc123..." data-solface-flat="true"></div>
690
+ <div data-solface="Def456..." data-solface-detail="full"></div>
393
691
 
394
692
  <!-- Global API available as window.SolFaces -->
395
693
  <script>
@@ -397,6 +695,7 @@ For sites without a build step — Webflow, Notion embeds, plain HTML, WordPress
397
695
  SolFaces.setImg("#pfp", "7xKXqR...");
398
696
  const svg = SolFaces.renderSVG("7xKXqR...");
399
697
  const desc = SolFaces.describe("7xKXqR...");
698
+ const name = SolFaces.deriveName("7xKXqR...");
400
699
  const prompt = SolFaces.agentPrompt("7xKXqR...", "Atlas");
401
700
  </script>
402
701
  ```
@@ -407,23 +706,33 @@ For sites without a build step — Webflow, Notion embeds, plain HTML, WordPress
407
706
 
408
707
  | Function | Returns | Description |
409
708
  |----------|---------|-------------|
709
+ | `deriveName(wallet, format?)` | `string` | Deterministic name from wallet (SHA-256) |
710
+ | `deriveIdentity(wallet)` | `SolNameIdentity` | Full identity bundle from wallet |
410
711
  | `generateTraits(wallet, overrides?)` | `SolFaceTraits` | Deterministic traits from wallet |
712
+ | `getTraitLabels(traits)` | `Record<string, string>` | Human-readable trait names |
713
+ | `traitHash(wallet)` | `string` | 8-char hex hash |
714
+ | `resolveTheme(name?, themes?)` | `SolFaceTheme \| undefined` | Look up theme by name from a map |
715
+ | `mergeTheme(base, overrides)` | `SolFaceTheme` | Merge two themes |
716
+ | `effectiveAccessory(traits)` | `number` | Accessory index (earring suppressed for long/bob hair) |
411
717
  | `renderSolFaceSVG(wallet, options?)` | `string` | Raw SVG markup |
412
718
  | `renderSolFaceDataURI(wallet, options?)` | `string` | Data URI for `<img>` tags |
413
719
  | `renderSolFaceBase64(wallet, options?)` | `string` | Base64 data URI |
414
720
  | `renderSolFacePNG(wallet, options?)` | `Promise<Buffer>` | PNG buffer (Node) |
415
721
  | `renderSolFacePNGBrowser(wallet, options?)` | `Promise<Blob>` | PNG blob (browser) |
722
+ | `renderSolFacePNGDataURL(wallet, options?)` | `Promise<string>` | PNG data URL (browser) |
416
723
  | `describeAppearance(wallet, options?)` | `string` | Natural language description |
724
+ | `describeTraits(traits, options?)` | `string` | Describe from pre-generated traits |
417
725
  | `agentAppearancePrompt(wallet, name?)` | `string` | System prompt for AI agents |
418
726
  | `solFaceAltText(wallet)` | `string` | Accessible alt text |
419
- | `getTraitLabels(traits)` | `Record<string, string>` | Human-readable trait names |
420
- | `traitHash(wallet)` | `string` | 8-char hex hash |
421
- | `SOLFACE_TOOLS` | `SolFaceTool[]` | All 5 agent tool definitions |
422
- | `handleToolCall(name, params)` | `Promise<unknown>` | Universal agent tool dispatcher |
423
- | `allToolsOpenAI()` | `OpenAITool[]` | Tools in OpenAI format |
424
- | `allToolsAnthropic()` | `AnthropicTool[]` | Tools in Anthropic format |
425
- | `allToolsVercelAI()` | `Record<string, VercelAITool>` | Tools in Vercel AI SDK format |
426
- | `allToolsMCP()` | `MCPTool[]` | Tools in MCP format |
727
+ | `hexToRgb(hex)` | `[r, g, b]` | Parse hex color |
728
+ | `rgbToHex(r, g, b)` | `string` | Convert RGB to hex |
729
+ | `darken(hex, pct)` | `string` | Darken a color |
730
+ | `lighten(hex, pct)` | `string` | Lighten a color |
731
+ | `blend(a, b, t)` | `string` | Blend two colors |
732
+ | `luminance(hex)` | `number` | Perceived luminance (0-255) |
733
+ | `deriveSkinColors(skinHex)` | `DerivedColors` | Full skin-luminance color derivation |
734
+ | `SOLFACE_TOOLS` | `SolFaceTool[]` | All 6 agent tool definitions |
735
+ | `handleToolCall(name, params)` | `unknown` | Universal agent tool dispatcher |
427
736
 
428
737
  ### React Component Props
429
738
 
@@ -431,25 +740,77 @@ For sites without a build step — Webflow, Notion embeds, plain HTML, WordPress
431
740
  <SolFace
432
741
  walletAddress="7xKXqR..." // Required
433
742
  size={48} // Default: 64
434
- enableBlink={true} // Default: false — or { duration: 2, delay: 0.5 }
743
+ enableBlink={true} // Default: false — or custom timing below
435
744
  theme={darkTheme} // Optional theme
745
+ detail="full" // "full" | "simplified" | "auto"
436
746
  traitOverrides={{ hairStyle: 0 }} // Pin specific traits
437
747
  colorOverrides={{ hair: "#ff0000" }} // Override individual colors
438
748
  className="my-avatar" // CSS class
439
749
  style={{ borderRadius: "50%" }} // Inline styles
440
- onClick={handleClick} // All SVG props supported
750
+ onClick={handleClick} // All standard SVG element props supported
751
+ />
752
+
753
+ // Custom blink timing
754
+ <SolFace
755
+ walletAddress="7xKXqR..."
756
+ enableBlink={{ duration: 3, delay: 1 }} // 3s cycle, 1s initial delay
441
757
  />
442
758
  ```
443
759
 
760
+ ### RenderOptions
761
+
762
+ ```ts
763
+ interface RenderOptions {
764
+ size?: number; // Default: 64
765
+ theme?: SolFaceTheme; // Theme object
766
+ enableBlink?: boolean | { // Blink animation (boolean or custom timing)
767
+ duration?: number; // Blink cycle duration in seconds (default: 4)
768
+ delay?: number; // Initial delay in seconds (default: 0)
769
+ };
770
+ detail?: "full" | "simplified" | "auto"; // Detail level (default: "auto")
771
+ traitOverrides?: Partial<SolFaceTraits>; // Pin specific traits
772
+ className?: string; // CSS class on SVG element
773
+ colorOverrides?: { // Override individual colors per instance
774
+ skin?: string;
775
+ eyes?: string;
776
+ hair?: string;
777
+ bg?: string;
778
+ mouth?: string;
779
+ eyebrow?: string;
780
+ accessory?: string;
781
+ nose?: string;
782
+ eyeWhite?: string;
783
+ };
784
+ }
785
+ ```
786
+
787
+ ### Per-Instance Color Overrides
788
+
789
+ Override any color on a specific avatar without changing the global theme:
790
+
791
+ ```tsx
792
+ // React
793
+ <SolFace walletAddress="7xKXqR..." colorOverrides={{ hair: "#ff0000", bg: "#000" }} />
794
+
795
+ // String renderer
796
+ renderSolFaceSVG("7xKXqR...", {
797
+ theme: darkTheme,
798
+ colorOverrides: { skin: "#ffd5b0", eyes: "#00ff00" },
799
+ });
800
+ ```
801
+
802
+ Available keys: `skin`, `eyes`, `hair`, `bg`, `mouth`, `eyebrow`, `accessory`, `nose`, `eyeWhite`.
803
+
444
804
  ### Import Paths
445
805
 
446
806
  | Path | Contents | React? |
447
807
  |------|----------|--------|
448
- | `solfaces` | Core + themes + describe + rasterize + agent tools | No |
449
- | `solfaces/core` | Engine only | No |
450
- | `solfaces/react` | React component | Yes |
451
- | `solfaces/vanilla` | DOM helpers | No |
452
- | `solfaces/themes` | Preset themes | No |
808
+ | `solfaces` | Core + colors + themes + names + describe + rasterize + agent tools | No |
809
+ | `solfaces/core` | Engine only (traits, renderer, colors, describe) | No |
810
+ | `solfaces/react` | React component (base + pixel + glass modes) | Yes |
811
+ | `solfaces/vanilla` | DOM helpers (mount, setImg, autoInit) | No |
812
+ | `solfaces/themes` | 11 preset themes | No |
813
+ | `solfaces/names` | SolNames derivation + validation | No |
453
814
  | `solfaces/agent` | AI agent tool definitions + framework adapters | No |
454
815
  | `solfaces/cdn` | IIFE for `<script>` tags | No |
455
816
 
@@ -459,22 +820,26 @@ For sites without a build step — Webflow, Notion embeds, plain HTML, WordPress
459
820
 
460
821
  | Trait | Variants | Options |
461
822
  |-------|----------|---------|
462
- | Face Shape | 4 | Round, Square, Oval, Hexagon |
463
- | Skin Color | 6 | Light Dark (6 tones) |
464
- | Eye Style | 8 | Round, Dots, Almond, Wide, Sleepy, Winking, Lashes, Narrow |
465
- | Eye Color | 5 | Dark Brown, Blue, Green, Amber, Gray |
466
- | Eyebrows | 5 | None, Thin, Thick, Arched, Angled |
467
- | Nose | 4 | None, Dot, Triangle, Button |
468
- | Mouth | 6 | Smile, Neutral, Grin, Open, Smirk, Wide Smile |
469
- | Hair Style | 8 | Bald, Short, Spiky, Swept, Mohawk, Long, Bob, Buzz |
470
- | Hair Color | 8 | Black, Brown, Blonde, Ginger, Neon Lime, Neon Blue, Solana Mint, Neon Magenta |
471
- | Accessory | 6 | None (×2), Round Glasses, Square Glasses, Earring, Bandana |
472
- | Background | 5 | Lime, Blue, Solana Mint, Sand, Red |
473
-
474
- **Total unique combinations: ~221,184,000**
823
+ | Face Shape | 4 | Squircle (all preserved for PRNG ordering) |
824
+ | Skin Color | 10 | Porcelain, Ivory, Fair, Light, Sand, Golden, Warm, Caramel, Brown, Deep |
825
+ | Eye Style | 8 | Round, Minimal, Almond, Wide, Relaxed, Joyful, Bright, Gentle |
826
+ | Eye Color | 5 | Chocolate, Sky, Emerald, Hazel, Storm |
827
+ | Eyebrows | 5 | Wispy, Straight, Natural, Arched, Angled |
828
+ | Nose | 4 | Shadow, Button, Soft, Nostrils |
829
+ | Mouth | 8 | Smile, Calm, Happy, Oh, Smirk, Grin, Flat, Pout |
830
+ | Hair Style | 10 | Bald, Short, Curly, Side Sweep, Puff, Long, Bob, Buzz, Wavy, Topknot |
831
+ | Hair Color | 10 | Black, Espresso, Walnut, Honey, Copper, Silver, Charcoal, Burgundy, Strawberry, Ginger |
832
+ | Accessory | 10 | None, Beauty Mark, Round Glasses, Rect Glasses, Earring, Headband, Freckles, Stud Earrings, Aviators, Band-Aid |
833
+ | Background | 10 | Rose, Olive, Sage, Fern, Mint, Ocean, Sky, Lavender, Orchid, Blush |
834
+
835
+ **Total unique combinations: ~2,560,000,000**
475
836
 
476
837
  Algorithm: **djb2 hash** → **mulberry32 PRNG** → sequential trait sampling. Sub-millisecond. Deterministic across JS and Python.
477
838
 
839
+ ### Color Derivation
840
+
841
+ v2 introduces skin-luminance-driven color derivation. Every face's shadow colors, highlights, cheek blush, lip color, nose shading, ear colors, brow colors, and eye white adaptation are automatically computed from the skin tone's luminance. This creates cohesive, natural-looking faces without manual palette tuning.
842
+
478
843
  ---
479
844
 
480
845
  ## Architecture
@@ -483,32 +848,59 @@ Algorithm: **djb2 hash** → **mulberry32 PRNG** → sequential trait sampling.
483
848
  solfaces/
484
849
  ├── src/
485
850
  │ ├── core/
851
+ │ │ ├── colors.ts # Color math: darken, lighten, blend, deriveSkinColors
486
852
  │ │ ├── traits.ts # Types, palettes, theme system, trait generation
487
- │ │ ├── renderer.ts # SVG string renderer, data URI, base64
488
- │ │ ├── describe.ts # Natural language descriptions for AI agents
853
+ │ │ ├── renderer.ts # SVG string renderer (gradient-rich, detail levels)
854
+ │ │ ├── describe.ts # (no names.ts moved to names/)
489
855
  │ │ ├── rasterize.ts # PNG output (sharp / resvg / canvas)
490
856
  │ │ └── index.ts
857
+ │ ├── names/
858
+ │ │ ├── constants.ts # 1000 adjectives, 1000 nouns, blocked combos
859
+ │ │ ├── sha256.ts # Pure-JS SHA-256 (sync, zero deps)
860
+ │ │ ├── derive.ts # deriveName(), deriveIdentity()
861
+ │ │ ├── validate.ts # isValidSolName(), parseSolName()
862
+ │ │ └── index.ts
491
863
  │ ├── react/
492
- │ │ ├── SolFace.tsx # React component
864
+ │ │ ├── SolFace.tsx # React component (base + pixel art + liquid glass)
865
+ │ │ ├── useSolName.ts # useSolName() hook
493
866
  │ │ └── index.ts
494
867
  │ ├── vanilla/
495
868
  │ │ └── index.ts # mountSolFace, setSolFaceImg, autoInit
496
869
  │ ├── themes/
497
- │ │ ├── presets.ts # 8 preset themes
870
+ │ │ ├── presets.ts # 11 preset themes
498
871
  │ │ └── index.ts
499
872
  │ ├── agent/
500
- │ │ ├── tools.ts # 5 canonical tool definitions + handlers
873
+ │ │ ├── tools.ts # 6 canonical tool definitions + handlers
501
874
  │ │ ├── index.ts # Format adapters (MCP, OpenAI, Anthropic, Vercel AI)
502
875
  │ │ └── mcp-server.ts # Standalone MCP server (npx solfaces)
503
876
  │ ├── cdn.ts # IIFE bundle for <script> tag
504
877
  │ ├── api-templates.ts # Copy-paste route handlers
505
878
  │ └── index.ts
506
879
  ├── python/
507
- │ └── solfaces.py # Full Python port (zero deps)
880
+ │ └── solfaces.py # Full Python port (zero deps, gradient rendering)
508
881
  ├── package.json
509
882
  └── tsup.config.ts
510
883
  ```
511
884
 
885
+ ### Key Design Decisions
886
+
887
+ - **`colors.ts` is the single source of truth** for all color math. Both `renderer.ts` and `SolFace.tsx` import from it, preventing renderer drift.
888
+ - **`effectiveAccessory()`** handles earring suppression: long and bob hairstyles suppress earring accessories.
889
+ - **`_` prefix** on theme fields marks React-only features (pixel, glass). The string renderer ignores these.
890
+ - **Detail levels** are resolved at render time: `"auto"` → full if size >= 48, simplified otherwise.
891
+
892
+ ---
893
+
894
+ ## Migration from v1
895
+
896
+ v2.0.0 is a breaking release:
897
+
898
+ - **All faces change.** Trait ranges expanded (skin 6→10, mouth 6→8, hair 8→10, accessories 6→10, bg 5→10), so every wallet generates a different face than in v1.
899
+ - **Old themes removed.** `solana`, `neon`, `jupiter`, `phantom`, `circle` themes are gone. Use `dark`, `light`, `mono`, `flat`, `transparent`, or the new `glass`/`pixel` themes.
900
+ - **New rendering engine.** Gradient-rich rendering with skin-luminance-driven colors, ears, hair-back layers, and face overlays.
901
+ - **New theme fields.** `flat`, `cheekEnabled`, `shadowEnabled`, `glowIntensity`, and React-only `_glass*`/`_pixel*` fields.
902
+ - **`colorOverrides` still supported.** Per-instance color overrides work the same as v1.
903
+
512
904
  ---
513
905
 
514
906
  ## License