[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-94963":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":8,"language":10,"languages":8,"totalLinesOfCode":8,"stars":11,"forks":12,"watchers":13,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":15,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":16,"compositeScore":17,"rankGlobal":8,"rankLanguage":8,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":8,"pushedAt":8,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":14,"starSnapshotCount":14,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},94963,"blobatar","Alain00\u002Fblobatar","Alain00",null,"https:\u002F\u002Fblobatar.dev","TypeScript",625,38,1,0,215,31,75.77,"MIT License",false,"main",true,[],"2026-08-24 04:01:23","# blobatar\n\nDeterministic geometric blobatars from any string. No dependencies, ~4.4 KB\ngzipped.\n\n![A field of forty-odd blobatars, no two alike, each generated from an ordinary handle like alain, tove or kasper](.\u002Fdocs\u002Fmedia\u002Fcrowd.png)\n\n```sh\nbun add blobatar    # npm \u002F pnpm \u002F yarn all work too\n```\n\n## Usage\n\nA blobatar always stands for somebody — a user, a bot, a team, a repo — so the\nvalue it is generated from is that somebody's `name`: a username, a display\nname, an email, a handle, an id. Any string works, and the same string always\nrenders the same blobatar.\n\n### React\n\n```tsx\nimport { Blobatar } from \"blobatar\u002Freact\";\n\n\u003CBlobatar name={user.email} size={48} \u002F>;\n```\n\nEverything but `name` is optional. Remaining props land on the underlying\nelement, so `className`, `alt` and the rest behave as you would expect.\n\n### Vue\n\n```html\n\u003Cscript setup>\nimport { Blobatar } from \"blobatar\u002Fvue\";\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CBlobatar name=\"alain@example.com\" :size=\"48\" \u002F>\n\u003C\u002Ftemplate>\n```\n\nThe same props and the same behavior as the React adapter. Anything not\ndeclared as a prop lands on the underlying element, so `class`, `style`, `alt`\nand the rest behave as you would expect.\n\n### Anywhere else\n\n`blobatar()` returns SVG markup as a string, and `blobatarUri()` wraps it in a\n`data:` URI for `\u003Cimg src>` or `background-image`:\n\n```ts\nimport { blobatar } from \"blobatar\";\nimport { blobatarUri } from \"blobatar\u002Furi\";\n\nblobatar(\"alain@example.com\"); \u002F\u002F '\u003Csvg xmlns=\"...\" viewBox=\"0 0 100 100\">…'\n\nel.style.backgroundImage = `url(\"${blobatarUri(user.id)}\")`;\n```\n\nThe main entry also carries the palette and trait utilities. If all you do is\nrender, import the renderer on its own and save about a kilobyte:\n\n```ts\nimport { blobatar } from \"blobatar\u002Fblob\";\n```\n\n### Configuring\n\nOptions are the same across the React, Vue and string APIs. `background`, `hue`\nand `tone` cover the common cases; `traits` pins any individual axis as the 0–1\nposition the hash would otherwise have produced:\n\n```tsx\n\u003CBlobatar name={user.email} background=\"circle\" hue={210} size={48} \u002F>;\n\n\u002F\u002F Always a sun with wide eyes — colour and everything else still per name.\nblobatar(user.email, { traits: { shape: 0.95, \"eye.ratio\": 0 } });\n```\n\nKeys you leave out still come from the name — lock the two things that carry\nyour brand, and every user still gets their own creature. Pin everything and the\nname stops mattering, which is how you build one fixed blobatar.\n\nEvery value those options take, and what each one draws:\n\n![The ten silhouettes from round and organic through capsule, triangle, hexagon and droplet; the eight hue stops from 12 to 320 degrees; the fourteen expressions from idle through happy, sad and mad to love, shy, sick and thinking; the four backgrounds none, squircle, circle and square](.\u002Fdocs\u002Fmedia\u002Fsheet.png)\n\n### Animation and expressions\n\nBoth are opt-in. `animate` idles the blobatar — breathe, bob, blink, glance —\nand expressions are imported as values so you ship only the poses you use:\n\n```tsx\nimport { Blobatar } from \"blobatar\u002Freact\";\nimport { happy } from \"blobatar\u002Fexpression\";\nimport \"blobatar\u002Fmotion.css\"; \u002F\u002F required — nothing animates without it\n\n\u003CBlobatar name={user.email} animate=\"hover\" expression={happy} size={64} \u002F>;\n```\n\nThe same props work with `blobatar\u002Fvue` — only the component import changes.\n\n`animate` changes the rendering mode: a static blobatar is a single `\u003Cimg>`, an\nanimated one is inline SVG. Use `\"hover\"` in a grid and `\"always\"` for the\nsingle-blobatar case. Motion respects `prefers-reduced-motion`.\n\n## Over HTTP\n\nNo install and no build step — a URL that renders one:\n\n```html\n\u003Cimg src=\"https:\u002F\u002Fblobatar.dev\u002Favatar\u002Falain00?size=48\" width=\"48\" height=\"48\" alt=\"\">\n```\n\nThe path segment is the name, percent-encoded, and the query string is the\noptions under the names the library gives them — `size` (or `s`), `background`,\n`hue`, `tone`, `expression`, `title`, `gen`:\n\n```\nhttps:\u002F\u002Fblobatar.dev\u002Favatar\u002Falain%40example.com?size=64&background=squircle\nhttps:\u002F\u002Fblobatar.dev\u002Favatar\u002Fteam-rocket?expression=smug\n```\n\nGravatar's `d`, `f` and `r` are accepted and ignored, so an existing Gravatar\nURL becomes a blobatar by changing the host and nothing else:\n\n```diff\n- https:\u002F\u002Fwww.gravatar.com\u002Favatar\u002F\u003Chash>?s=200&d=identicon\n+ https:\u002F\u002Fblobatar.dev\u002Favatar\u002F\u003Chash>?s=200&d=identicon\n```\n\nThe hash is used as the name. It is one-way, so the email cannot be recovered —\nbut it is itself derived from the email, so each person still gets one stable\nblobatar of their own. It will not be the same one `\u002Favatar\u002F\u003Cemail>` gives:\npick one scheme per application.\n\n`gen` picks the shape vocabulary. New silhouettes cannot be added without\nreshuffling existing ones — the thresholds partition a single range — so they\narrive as a new **generation** instead:\n\n| | silhouettes |\n| --- | --- |\n| `gen=1` | round, organic, boxy, nub, cloud, sun |\n| `gen=2` | …and capsule, triangle, hexagon, droplet |\n\nAn unversioned URL follows the current package major and now renders gen 2.\nPin `?gen=1` on existing URLs that must keep the original six shapes:\n\n```\nhttps:\u002F\u002Fblobatar.dev\u002Favatar\u002Falain00?gen=1\nhttps:\u002F\u002Fblobatar.dev\u002Favatar\u002Falain00?gen=2\n```\n\nA generation that has appeared in a URL keeps answering. The list only ever\ngrows: `gen=1` will not be retired, redirected to a newer vocabulary, or\nanswered with a placeholder, because a URL that renders someone's face is\nusually written down somewhere its author no longer controls. That is what\nnaming a generation buys, and it is why a pinned URL earns a year-long\nimmutable cache rather than a day — it cannot come back different. The cost\nfalls on the endpoint, which depends on every frozen package major it still\nserves; the library itself carries only the current one.\n\n`GET \u002Favatar\u002F` returns the whole parameter list as plain text, which is the\nreference this section is a summary of.\n\n### Deploy your own\n\n[![Deploy to Cloudflare](https:\u002F\u002Fdeploy.workers.cloudflare.com\u002Fbutton)](https:\u002F\u002Fdeploy.workers.cloudflare.com\u002F?url=https:\u002F\u002Fgithub.com\u002FAlain00\u002Fblobatar\u002Ftree\u002Fmain\u002Fapps\u002Fapi)\n\n`blobatar.dev\u002Favatar` is free to use, but it is one small Worker rather than\nsomething you have an agreement with, and it is rate-limited. If avatars are\nload-bearing for you, run the endpoint yourself. The button clones\n[`apps\u002Fapi`](.\u002Fapps\u002Fapi) into your GitHub or GitLab account and deploys it to\nyour Cloudflare account — no configuration, no card, about a minute — and you\nget:\n\n```\nhttps:\u002F\u002Fblobatar-api.\u003Cyour-subdomain>.workers.dev\u002Favatar\u002F\u003Cname>\n```\n\nAttach your own hostname afterwards in the Cloudflare dashboard, or as a\n`routes` entry in `wrangler.jsonc`, and every push to your clone redeploys.\n\nIt stays inside the Workers free plan for anything short of real scale:\n100,000 requests a day, and a blobatar costs 12µs of CPU against the 10ms\nallowed per request and 357 gzipped bytes to send. There is no database, no\nbucket and no state — the avatar is a pure function of the URL, which is also\nwhy every cache between you and it does the actual work.\n\n**[Full docs — options table, guarantees, and how it works →](.\u002Fpackages\u002Fblobatar\u002FREADME.md)**\n\n## Workspace\n\n| Path                | What it is                                                        |\n| ------------------- | ----------------------------------------------------------------- |\n| `packages\u002Fblobatar` | The library. [Docs here](.\u002Fpackages\u002Fblobatar\u002FREADME.md).          |\n| `apps\u002Fapi`          | The HTTP endpoint, deployable on its own. Serves `\u002Favatar\u002F\u003Cname>`. |\n| `apps\u002Fsite`         | The landing page, plus `apps\u002Fapi` behind blobatar.dev.            |\n| `apps\u002Fdemo`         | The tuning grid — the internal design tool, not a demo.           |\n\n```sh\nbun install\nbun dev        # tuning grid   → localhost:3001\nbun site       # landing page  → localhost:3000\nbun api        # the endpoint  → localhost:8787\u002Favatar\u002Falain\nbun test       # library tests\nbun run check  # tests + size budgets\nbun run media  # redraw the README images (needs Chrome + ImageMagick)\n```\n\n[`CONTEXT.md`](.\u002FCONTEXT.md) is the glossary — worth two minutes before changing\nanything, since `shape` and the `name`\u002F`seed` split mean specific and\neasily-confused things here. Architectural decisions live in [`docs\u002Fadr\u002F`](.\u002Fdocs\u002Fadr\u002F).\n","Blobatar 是一个轻量级的 TypeScript 库，用于从任意字符串（如用户名、邮箱）确定性地生成唯一、可复现的几何风格头像（blob avatar）。其核心特点是零依赖、体积小（约 4.4 KB gzipped），支持 React\u002FVue 组件化调用，也提供纯函数式 SVG 字符串与 data URI 输出；内置可配置的形状、色调、背景和表情系统，并支持动画与按需导入。适用于需要轻量、无图床、隐私友好型用户标识的 Web 应用场景，如登录页、评论系统、协作工具或代码托管平台的用户头像渲染。",2,"2026-08-19 02:30:03","CREATED_QUERY"]