Library / SDK
jeremy-prt/bloub avatar
jeremy-prt/bloub

bloub: an SVG x.ai bot avatar that morphs through 14 measured states

SVG recreation of the x.ai bot avatar. One shape morphing through 14 states, measured off the reference video frame by frame.

1,512 stars186 forksTypeScriptMIT

At a glance

What is it?
bloub recreates the x.ai bot avatar as a single filled SVG shape plus two masked eyes, with all geometry measured off a reference video. It is a Vue 3 component, not an animation library, and its constants are measurements rather than style choices.
Who is it for?
Adopt bloub if you need a small, framework-light morphing avatar that renders deterministically from a pure sample(t) function and can be frozen to an exact frame for thumbnails or tests. Do not adopt it if you want a general purpose animation library, a drop-in React component, or a design you are free to reuse commercially: the MIT licence covers the code, and the README states it does not cover the design it imitates.
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 last received commits 32 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

DEEP OPEN-SOURCE ANALYSIS

What bloub actually solves for a Vue project

Most avatar animations in a web app are a sprite sheet, a Lottie file, or a CSS keyframe loop. Each of those ties the avatar to a fixed timeline and a fixed resolution. bloub takes a different route: it describes the avatar as a filled black body shape plus two white eye shapes, and morphs them between 14 named states. The README describes the result as "one filled black shape" that morphs between 14 states, with two white shapes for the eyes that morph independently, on a plain background, and states that no animation library is used.

The intended audience is narrow. This is for a developer who wants the x.ai bot avatar look inside a Vue 3 app, who is willing to accept measured constants instead of tunable ones, and who wants export paths (SVG, PNG, GIF, MP4) without pulling in a drawing or video library for the still formats. It is not a general purpose avatar framework and it does not ship a set of unrelated characters. If you need a talking head, a mascot builder, or a physics-driven blob, this is the wrong shape of tool.

The engine is a pure function of time, and that drives everything else

The core design decision is in src/bot/, which the README calls framework-free and clock-free. The entry point is engine.sample(t), a pure function of time. Pausing, resuming, jumping to an arbitrary date and running tests all produce the same image, according to the README.

That single property explains several features that would otherwise look unrelated. The frozen state board works because rendering one frame needs no running loop. The DOM-less test suite works for the same reason. The component exposes a frozenAt prop that renders one exact frame with no animation loop, which is how the thumbnails and the state board are drawn. The eyes are implemented as mask holes rather than as separate painted shapes, so the body silhouette and the eye cutouts stay consistent while both morph.

The trade-off is that anything time-dependent has to be expressed as a function of the cursor. A montage can play the same state twice, so the README distinguishes block, the playback cursor index, from state, which follows it as an output. If your own code wants to know where the animation is, it has to track block, not state.

Installing bloub and getting a frozen state on screen

The README gives the setup. The project uses pnpm, and package.json pins packageManager to pnpm@11.17.0. After installing, pnpm dev starts Vite and the app is served on port 5190.

bash
pnpm install
pnpm dev

Open http://localhost:5190. The README notes two hash URLs worth knowing: #planche shows the 14 states side by side, frozen, as a quick visual check, and #etat=orbit&stop opens one state directly with playback paused.

To use the component rather than the demo app, the README gives these two forms. The first is the two-way bound version, where block is the playback cursor and state follows it as an output.

vue
<BloubBot v-model:block="block" v-model:state="state" v-model:playing="playing" />
<BloubBot state="orbit" :size="120" :frozen-at="1.2" />

The second line is the one to copy if you want a static render: passing frozenAt makes the component render one exact frame with no animation loop. The README lists the props as size, shape, color, expression, paper, frozenAt, cycle, follow and gaze, and the models as block, state, playing and elapsed. It points to src/components/BloubBot.vue for the details, which is the honest place to look, because the README does not document every prop's accepted values.

Before you consider a change finished, run the build. The README is explicit that there is no ESLint and no Prettier, and that vue-tsc is the only gate.

bash
pnpm build

That command runs vue-tsc --noEmit and then vite build. A separate pnpm test runs vitest.

The constants are measurements, and rounding them breaks the point

This is the part that will surprise anyone who opens the source expecting to tidy it up. The README states the numbers are measured, not chosen. The reference video was cut at 10 fps and each state was measured off the frames: silhouettes by sub-pixel ray casting, eyes by capsule fitting, colours and stroke widths by direct sampling. The README then warns that rounding the constants to friendlier values breaks the resemblance, which it calls the only thing the project is trying to get right.

Several measured results contradict what a designer would guess. The eyes lean the opposite way from the usual assumption, around 26 degrees off vertical. The body is a perfect circle with radial deviation under 0.7 percent, not a squircle. Transitions are exponential ease-outs and the body never overshoots, so there are no springs. In the comet animation the dot stays put and the trail orbits it. At rest the avatar does not float; the life comes from gaze drift and blinking.

For an adopter this is a real constraint. If you want a different lean to the eyes, or a softer resting pose, you are not tuning a parameter, you are departing from the measurement. docs/measurements.md is said to cover the rest, including how to regenerate the extracted profiles, and profiles.ts is the generated file. Changing the geometry without regenerating that file will leave the two out of step.

Where bloub stops being the right tool

The framework-free engine is the selling point and also the boundary. If your app is React, Svelte or plain JavaScript, you are not importing a component; you are either reading src/bot/ and wiring your own renderer, or embedding a Vue 3 app. The README documents the component in Vue only, and package.json lists Vue and mediabunny as the sole runtime dependencies.

The second limitation is the design provenance. The README states plainly that the project is not affiliated with, endorsed by or connected to x.ai, that it recreates the visual behaviour of their bot avatar as an exercise, and that the MIT licence covers the code in this repository but not the design it imitates. That is a licensing boundary you have to judge for yourself, and it is not a legal opinion anyone else can give you.

The third is scope. There are 14 states. There is no documented way to author a new state from the README alone; the Customise view offers 8 body shapes, 12 colours and 16 rest expressions, and the Animations view lets you arrange existing states into a timeline and set how long each is held. That is arrangement, not new geometry. If you need a character that does things outside those 14 states, this repository gives you a starting point and a measurement method, not a finished product.

bloub versus a general SVG animation library

The obvious alternative is an SVG animation library that interpolates between path data, or a runtime like Lottie that plays an exported animation file. The difference is where the knowledge lives. In a path-interpolation library you supply keyframes and the library computes the tween; the morph is generic and the designer owns the shapes. In bloub the morph itself is the product: radial-profile morphing, eyes as mask holes, and a fixed set of measured states, with engine.sample(t) returning the frame for any time value.

That has a practical consequence for testing. A DOM-less test suite is possible here because sampling is pure. With a typical animation runtime the interesting state lives inside a running player, and verifying a specific frame usually means rendering and comparing images. bloub's frozenAt prop gives you the same frame in a component tree.

The cost is flexibility. A path-interpolation library will morph any two compatible paths you hand it. bloub will morph its own body profiles and its own eye capsules, and the README's warning about rounding constants suggests the geometry is not meant to be edited casually. If your requirement is "animate this logo I drew", bloub is the wrong tool. If your requirement is "reproduce this specific avatar faithfully, and be able to freeze any frame of it", the measured approach is the one that gets there.

Maintenance, upgrades and what the licence does not cover

The repository is not archived and the last push was on 2026-08-17, the same day as the v0.1.1 release, which the release notes describe as the first batch of post-launch fixes. The README points at CHANGELOG.md, with one entry per release, and says that is how you tell whether the copy you have carries a given fix. That is a small but useful habit: before upgrading, read the changelog entry rather than the version number.

The upgrade surface is small. Runtime dependencies are Vue 3 and mediabunny. The README notes the video encoder is only fetched the first time you ask for a video export, so the MP4 and timeline GIF paths carry a lazy download that the still formats do not. The dev toolchain is Vite, TypeScript, Tailwind 4, vitest and vue-tsc, and because there is no linter or formatter, a TypeScript error is the only thing that will stop a bad change. Budget for that: a contributor used to ESLint will get no stylistic feedback at all.

On licensing, MIT applies to the code. The README draws the line at the design, stating the licence does not cover the design it imitates, and that Grok and x.ai belong to their owners. Treat that as the constraint to resolve before commercial use, and get your own advice rather than relying on a README.

Editorial conclusion

Adopt bloub if you need a small, framework-light morphing avatar that renders deterministically from a pure sample(t) function and can be frozen to an exact frame for thumbnails or tests. Do not adopt it if you want a general purpose animation library, a drop-in React component, or a design you are free to reuse commercially: the MIT licence covers the code, and the README states it does not cover the design it imitates. Before committing, open #planche to compare all 14 states against your reference, read docs/measurements.md to see whether you can regenerate profiles.ts if you change the geometry, and run pnpm build, since vue-tsc is the only gate and there is no ESLint or Prettier.

Frequently asked questions

What does bloub do?

It recreates the x.ai bot avatar as SVG: one filled black shape that morphs between 14 states, plus two white eye shapes that morph independently, on a plain background. The README states that no animation library is used.

What does "bloobs" mean in the context of bloub?

The repository does not define the word. bloub is the project name for an SVG avatar component, and the README does not include a glossary or an explanation of related slang terms.

How do I install bloub and run it locally?

The README gives pnpm install followed by pnpm dev, then opening http://localhost:5190. The package.json pins packageManager to pnpm@11.17.0, and pnpm build runs vue-tsc --noEmit followed by vite build.

Can I use bloub with React or plain JavaScript?

The README documents the component as a Vue 3 component and package.json lists Vue and mediabunny as the runtime dependencies. It describes src/bot/ as framework-free, so the engine can be read and reused, but no non-Vue integration is documented.

Does the MIT licence let me reuse the avatar design?

The README states that the MIT licence covers the code in the repository but not the design it imitates, and that the project is not affiliated with or endorsed by x.ai. The README does not give legal advice on reuse.

Official sources

  1. jeremy-prt/bloub on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes