Model or dataset
draftbit/avatar-generator avatar
draftbit/avatar-generator

Personas, an avatar generator whose output is a URL you can paste anywhere

Personas, an avatar generator by Draftbit

1,313 stars121 forksJavaScriptMIT

At a glance

What is it?
Draftbit's Personas generates SVG avatars from query parameters, exposes a JSON options endpoint, serves short share links, and ships an MCP server so an assistant can draw an avatar. It is a small static site in ReScript, React and Vite, deployed to Cloudflare Workers.
Who is it for?
Adopt Personas if you need placeholder or profile avatars at scale and want the whole thing addressed by URL, because a link that encodes the configuration is a far better primitive than an uploaded file, and the SVG endpoint means no binary assets land in your repository. Do not adopt it if you need user accounts, saved profiles or moderation, since the short links are stateless and the options array is append-only by design.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An avatar generator built to be addressed by URL

Personas is an avatar generator by Draftbit, described as a delightful one, and it runs at personas.draftbit.com. The interesting part is not the artwork, it is the interface.

The project describes itself as fully addressable by URL, and it publishes a concise specification in an llms.txt file so an assistant can read it. An avatar is a URL.

code
https://personas.draftbit.com/?hair=Mohawk&hairColor=F2C94C&eyes=Hearts

That single line is the whole product in miniature. The style parameters name the parts of the avatar, hair, facial hair, body, eyes, mouth, nose and accessories, and the colour parameters, skinColor, hairColor, facialHairColor, bodyColor, accessoriesColor and bgColor, are hex values. There is no upload, no account and no state.

The stated reason for the project is short and human rather than technical. The team was exploring Reason and ReScript, and they wanted to put together an inclusive avatar generator for placeholders and profile photos. That second half is the actual use case, and it is why the options are structured as a set of named styles with colour variants rather than as a set of opaque numbered assets.

For an engineer, the value proposition is that an avatar is a string. A string can be stored in a database column, put in a URL, generated in a test fixture, and rendered as an image or as an SVG without a file ever existing.

The options array is append-only, and that is a hard constraint

The short share links are a stateless base64url encoding of the avatar configuration. A link such as personas.draftbit.com/<code> carries the whole configuration inside itself.

That design has a consequence that the project states as a rule: it makes the option arrays in src/data/config.json append-only, and you should never remove or reorder entries, only append.

The reasoning follows directly. A short code decodes to a configuration that names options by their position or identity in that file. If you remove an option, every link in the wild that referenced it decodes to a configuration naming something that no longer exists, and the generator has to decide what to draw. If you reorder, a code that used to mean a red-haired Mohawk can decode to a different hairstyle entirely, and every shared link silently changes meaning. Appending is the only operation that leaves old links valid.

This is the sort of constraint that is invisible in a README and expensive to discover later, and it is the single most important thing to understand before building anything on top of the service. It also tells you something about the intended lifetime of the options: they are a growing catalogue, and the links in them are treated as permanent.

The client libraries and tools that consume the service are built on the same assumption, which is why the endpoints accept the same parameter names as the URL and the short code decodes to the same structure.

Two endpoints: the options catalogue and the SVG renderer

The service exposes two HTTP endpoints, and the split between them is the sensible one. The catalogue comes first.

code
GET /api/options

That returns the valid options as JSON. Any client that wants to present a picker, validate a saved configuration or generate a random avatar needs the list of what exists, and getting it from the server rather than hardcoding it means the client cannot drift from the catalogue.

The renderer comes second.

code
GET /api/avatar.svg?<same params>

It accepts the same query parameters as the page, and it adds two more forms. The first is a code parameter, which takes a short code, and the second is a random parameter, which asks for a random avatar with the value 1.

The output is SVG rather than PNG, and that is the choice that matters most for the intended use. An SVG avatar scales to any size, can be styled with CSS by the embedding page, and costs nothing to store. If you are using these as placeholders in a list of a thousand rows, the difference between an inline SVG and a raster image is the difference between a page that renders instantly and a page that issues a thousand requests.

The random form is worth a second look too. A random avatar that is reproducible only by storing the resulting URL is a common pattern for placeholder systems, and this one supports it because the renderer will hand you a configuration you can then freeze into a link.

An MCP server with three tools, for assistants that draw

The third surface is an MCP server, which is the part of this project that is ahead of its time in a way worth understanding.

code
POST /mcp

It exposes three tools, list_avatar_options, generate_avatar and random_avatar, and it can be added to a client over HTTP transport with a command like this.

bash
claude mcp add --transport http personas https://personas.draftbit.com/mcp

The point of the design is that the model does not have to know the URL format. A client that can list the options, ask for a specific avatar and ask for a random one can produce a working avatar without ever composing a query string, and without knowing that the parameters are named hair, eyes and skinColor. The catalogue and the renderer are exposed as tools with names, so the model reasons about intent rather than about encoding.

That is the same reason the service publishes llms.txt. If an assistant is going to produce avatars, it needs the option names and the parameter names, and both are published in a form designed to be read by a machine.

The MCP server also fits the project's nature. Because the generator is stateless and cheap, an assistant can call it freely, and because the result is a URL, the assistant can hand that URL back to a user as a finished artefact rather than as a description of one.

ReScript, React 18 and Vite, with the compiler running beside the dev server

The implementation stack is unusual enough to explain the project. Personas is built with ReScript, React 18 and Vite, and the developer requirements are Node 22 or later, as pinned in the .nvmrc, and Yarn 4 via corepack.

The scripts show how the two compilers cooperate, and that is the part worth understanding before you clone it.

bash
yarn
yarn re:watch
yarn dev
yarn build
yarn preview

The dependency install is the plain yarn command. The re:watch script starts the ReScript compiler in watch mode, and the dev script starts the Vite dev server, and the documentation is explicit that you run them alongside each other, which means two terminals. The build script runs the ReScript compiler and then the Vite build, producing a production build in dist, and the preview script serves that production build locally.

The package manifest matches. The dependencies are @rescript/react, react and react-dom, plus html2canvas and normalize.css, and the dev dependencies are the rescript compiler, Vite with the React plugin, wrangler and prettier. There is also a rescript.json and a vite.config.js at the root, alongside a worker directory and a wrangler.jsonc for the deployment side.

So the shape is a ReScript application that compiles to JavaScript, bundled by Vite, with the React bindings supplied by @rescript/react rather than by JSX in source files. If you are not used to ReScript, expect a different error and iteration model from a plain React project, and note that the ReScript compiler has to be running for the dev server to see your changes.

Deploying to Cloudflare Workers, automatically on push

The site deploys to Cloudflare Workers as a static-assets Worker, and the deployment story has two paths.

The automatic one is the interesting one. Pushes to master deploy automatically via GitHub Actions, using the workflow in .github/workflows/deploy.yml, and that workflow requires two repository secrets, CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID.

The manual one is a script.

bash
yarn deploy

That script is a build followed by a wrangler deploy, and wrangler is in the dev dependencies at version 4. There is a .wrangler directory in the repository, which is where the tool keeps its local state, and a wrangler.jsonc for the configuration.

The two paths together are a sensible arrangement for a small public site. The automatic deployment means a pull request merged into master is live, and the manual path means you can ship a fix from a laptop without waiting for a merge.

One thing to note for anyone planning to run their own instance: the two GitHub secrets are the account-level credentials for a Cloudflare account, not something scoped to a single Worker. A fork of this project cannot deploy as it stands, and anyone who wants their own version of the site needs their own Cloudflare account and their own values for those two secrets.

The repository also carries a public directory for static assets, an index.html at the root, and a src directory holding the application and the data file with the option arrays.

MIT licensed, private to npm, and with no test suite

The licence is MIT, so the code, the artwork configuration and the service design can be reused as long as the copyright and licence notices are kept, and the project is marked private in the package manifest, which means the package is not published to the npm registry under that name.

The package name is @draftbit/personas at version 2.0.0, with a description of Avatar Generator by Draftbit. The repository field points at the GitHub project, and the keywords list personas, persona-avatar-generator and rescript. The engines field requires Node 22 or newer, and the package manager is pinned to Yarn 4.17.0.

There is one thing in the manifest that tells you where the project is in its life, and it is the test script.

code
"test": "echo \"Error: no test specified\" && exit 1"

That is the default placeholder value a package manager writes into a new project, and it is still there. There is no test suite. For a project whose correctness claim rests on a configuration file being append-only and on short codes decoding to the right avatar, that is a gap, and it is the kind of gap a fork would want to close first.

The other gap worth naming is the absence of a moderation or reporting layer. The service generates a deterministic image from parameters, and there is no account system, no history and no way to report a specific code, which keeps the service simple and also means a bad avatar cannot be recalled. The last push was on 2026-10-16 and the repository is not archived, so the work is current rather than frozen.

Editorial conclusion

Adopt Personas if you need placeholder or profile avatars at scale and want the whole thing addressed by URL, because a link that encodes the configuration is a far better primitive than an uploaded file, and the SVG endpoint means no binary assets land in your repository. Do not adopt it if you need user accounts, saved profiles or moderation, since the short links are stateless and the options array is append-only by design. Before you rely on it, read the append-only rule for the option arrays in src/data/config.json, because removing or reordering an entry breaks every short link that referenced it, and check the style parameter names and the hex color parameters against the JSON at GET /api/options rather than assuming the list in the documentation is complete.

Frequently asked questions

How do I generate an avatar with Personas?

The avatar page is addressed by URL with style parameters such as hair, eyes and mouth and hex colour parameters such as skinColor, hairColor and bgColor. You can also fetch the image directly at GET /api/avatar.svg with the same parameters.

Where do I get the list of valid avatar options?

The JSON catalogue is served at GET /api/options. The project also publishes a concise specification for assistants in an llms.txt file.

What are the share codes and why must the options file be append-only?

The short share links are a stateless base64url encoding of the avatar configuration. Because a code decodes to a reference into the option arrays, the project requires those arrays in src/data/config.json to be append-only, so entries are never removed or reordered, only appended.

Does Personas have an MCP server for AI assistants?

Yes. A server is available at POST /mcp with the tools list_avatar_options, generate_avatar and random_avatar, and it can be added over HTTP transport, for example with `claude mcp add --transport http personas https://personas.draftbit.com/mcp`.

How do I run Personas locally?

You need Node 22 or later and Yarn 4 via corepack. Run `yarn` to install, then `yarn re:watch` for the ReScript compiler in watch mode alongside `yarn dev` for the Vite dev server. `yarn build` produces a production build in dist and `yarn preview` serves it.

Official sources

  1. draftbit/avatar-generator on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/draftbit-avatar-generator.svg)](https://hysenlabs.com/projects/draftbit-avatar-generator)

Was this useful?