dottomon
v0.12.0
Published
Turn any name into a unique pixel-art monster. Deterministic, animated, zero dependencies — with an optional React component.
Maintainers
Readme
dottomon
Turn any name into a unique pixel-art monster — deterministic, animated, zero dependencies.
The same seed always produces the same monster, complete with four views (front / back / left / right), a 2-frame walk animation, and RPG-style stats. Pure TypeScript, no DOM required — runs in browsers, Node.js, and Workers. React support ships in the same package as a separate entry (dottomon/react), so non-React users never load it.
Status: 0.x — generated pixels may change between minor releases (marked
[pixels-changed]in the changelog). If you need avatars that never change, pin your version.
Migrating from
@dotmon/core/@dotmon/react? Both are now deprecated re-exports of this package — just rename the imports:@dotmon/core→dottomon,@dotmon/react→dottomon/react(subpaths follow the same pattern).
日本語の説明は下にあります。
Try it in 5 seconds
No install needed — meet your monster right in the terminal:
npx dottomon Poko # any name works. Try yours!
npx dottomon --card # a random monster with an RPG-style stat card
npx dottomon Poko --walk # watch it walk for a couple of secondsFull color where your terminal supports it. Every option — siblings, stat bars, saving PNG/GIF/SVG files, the all-in-one asset ZIP — is in the CLI section below.
Install
npm i dottomonQuick start
import { generateSvg, createMonster, getStats } from "dottomon";
// One-shot: get an SVG string
const { svg } = generateSvg("Poko");
// Facade with per-view/frame caching
const mon = createMonster("Poko", { preset: "retro" });
mon.svg(); // front, standing
mon.svg("left", 1); // left view, walk frame 1
mon.stats; // { lv, nature, hp, mp, atk, def, spd, luck }
// Stats only
getStats("Poko"); // deterministic, same seed → same stats
// Raw pixel grid (terminals, canvases, game engines):
// pixels[y][x] = CSS color string or null for transparency
import { generatePixels } from "dottomon";
const { pixels } = generatePixels("Poko", { preset: "retro" });CLI
The dottomon command ships inside the package (zero dependencies) and covers the web app's features from the terminal:
npx dottomon ポコ --card --lang ja # stat card, Japanese labels
npx dottomon Zugon --card-full --style retro # card with colored stat bars
npx dottomon Poko -n 6 --walk # a herd taking a walk
npx dottomon Poko -o poko.png --size 1024 # save as PNG (.svg / .gif too)
npx dottomon Poko --zip # → monster-Poko.zip, every asset| Option | Description |
|---|---|
| <name> | The seed (positional). Omitted → a random name, shown in the label |
| -s, --style <mochi\|retro\|chaos> | Style preset (default: mochi) |
| --view <front\|back\|left\|right> | Viewing direction (default: front) |
| -c, --card | RPG-style stat card |
| -C, --card-full | Card with colored stat bars, like the web app |
| -n, --count <1-10> | Siblings born from the same name (name-1, name-2, …) in a grid that wraps to your terminal width |
| -w, --walk | Play the 2-frame walk animation for ~2.5 s, then exit |
| -o, --out <file> | Save the monster as .svg, .png or .gif (format by extension) |
| --size <px> | Image size for --out (default: png 512 / gif 256, range 16–4096) |
| -z, --zip | Write <name>.zip with every asset — README, 12 PNGs (4 views × 3 poses), 4 animated GIFs, sprite sheet + atlas. Identical to the web app's ZIP |
| --lang <ja\|en> | Card and ZIP README language (default: from $LANG) |
| --no-name | Hide the name label under each sprite |
| --no-color | Plain block characters (also automatic for pipes / NO_COLOR) |
| -h, --help | Usage |
Colors use 24-bit where the terminal advertises it and fall back to the 256-color palette otherwise.
Terminal compatibility: the sprite is drawn with Unicode half-block characters, so how it looks depends on your terminal — it may render slightly off (or not at all) in some environments. It looks best in modern terminals (Ghostty, iTerm2, VS Code, Windows Terminal, etc.). If the sprite appears stretched or has horizontal seams: use a monospace font, set the line spacing to 1.0, and turn OFF any "treat East Asian ambiguous-width characters as wide" option (block and box-drawing characters are ambiguous-width — this matters in macOS Terminal.app with Japanese setups in particular).
React
The React component lives at the dottomon/react entry (peer dependency: react >= 18, optional — Node-only users are unaffected):
import { MonsterAvatar } from "dottomon/react";
// A deterministic avatar for a user name — one line
<MonsterAvatar seed="Poko" size={64} />
// Retro style, walking, on a colored background
<MonsterAvatar seed="Poko" preset="retro" size={96} animate background="#a5bdd2" />
// Any view, with fine-grained generation options
<MonsterAvatar seed="Poko" view="left" options={{ preset: "chaos", gapFill: true }} /><MonsterAvatar /> props
| Prop | Type | Default | Description |
|---|---|---|---|
| seed | string | (required) | The name. Same seed → same monster |
| size | number \| string | "100%" | Pixel number or any CSS length |
| preset | "mochi" \| "retro" \| "chaos" | "mochi" | Style preset |
| options | GenerateOptions | — | Fine-grained overrides (outline, face, legs, gapFill, ...). Its preset wins over the preset prop |
| view | "front" \| "back" \| "left" \| "right" | "front" | Viewing direction |
| animate | boolean | false | 2-frame walk animation. All animated avatars on the page tick in sync |
| background | string | "transparent" | CSS color behind the sprite |
| className / style | — | — | Passed to the wrapper element |
| title | string | the seed | Tooltip on the wrapper element |
Hooks
import { subscribeTicker, useMonster, useMonsterTicker } from "dottomon/react";
// Cached generator facade (per seed+options): mon.svg(view, frame), mon.stats, ...
const mon = useMonster("Poko", { preset: "retro" });
// The shared walk clock used by MonsterAvatar — the current frame, 0 | 1
const frame = useMonsterTicker();
// The same clock as an imperative subscription (for non-React code);
// returns an unsubscribe function
const unsubscribe = subscribeTicker((frame) => {
/* ... */
});Presets
| Preset | Look | How it works |
|---|---|---|
| mochi (default) | Round, connected, pet-like | Random-walk width profile, mirrored; horns, face and legs on top |
| retro | Space-invader style | Independent noise dots, mirrored — faces emerge from symmetry |
| chaos | Something is off... | Clustered noise (dense cores around hidden attractor points, no mirroring) with complementary accent pixels sprinkled on top |
Options
generateSvg(seed, {
preset: "retro", // "mochi" | "retro" | "chaos"
view: "left", // "front" | "back" | "left" | "right"
frame: 1, // 0 (stand) | 1 | 2 (walk poses)
// fine-grained overrides:
connected: false, // connected body vs. noise dots
symmetric: true, // mirror the left half
outline: true, // auto outline around the body
face: false, // eyes + mouth
legs: "none", // "auto" | "none" | "two" | "many" (connected × symmetric bodies only)
gapFill: true, // fill sealed interior gaps with white so backgrounds don't show through (non-connected bodies only)
});Views and frames never change who the monster is: view/frame branches consume no randomness (or consume-and-discard), so every angle and pose renders the same individual.
- back: same silhouette with the face omitted; retro additionally fills its see-through holes with the body color (a plain back)
- left / right: retro derives an asymmetric profile from the front half with face-side gaps bridged; mochi and chaos keep their body and move the face to a single edge-aligned eye.
rightis always the mirror ofleft - frame 1 / 2: alternating leg-up walk poses; frame 2 adds a one-pixel body bounce
Stats
import { getStats, NATURE_IDS } from "dottomon";
getStats("Poko");
// { lv: 1, nature: "easygoing", hp: 151, mp: 66, atk: 6, def: 4, spd: 6, luck: 44 }Stats are derived from the seed and preset. Display names for natures (and presets, legs, etc.) live in the locale dictionaries:
import { ja } from "dottomon/locales/ja"; // only the locales you import get bundled
import { en } from "dottomon/locales/en";
import { pickLocale } from "dottomon/locales";
ja.natures[getStats("Poko").nature]; // "のんびり"Rendering to files (browser only)
The render entry rasterizes with Canvas and encodes GIF/ZIP itself (still zero dependencies):
import { toPng, toGif, toSpriteSheet, toAssetZip } from "dottomon/render";
const png = await toPng(svg, { size: 512 }); // Blob
const gif = await toGif([frameA, frameB], { size: 512 }); // animated 2-frame GIF
const sheet = await toSpriteSheet("Poko", { preset: "retro" }); // Phaser/PixiJS-ready sheet
const zip = await toAssetZip("Poko"); // everything, zipped, with a READMEUtilities
import { randomName, safeFileName } from "dottomon";
randomName("ja"); // "ポコ" — random pronounceable monster name
safeFileName("ポコ/7"); // safe for downloadsLicense
MIT
dottomon は、名前(シード)からユニークなドット絵モンスターを生成するライブラリです。同じ名前からは必ず同じ子が生まれます。4方向ビュー・2コマ歩行アニメ・RPG風ステータス付き。依存ゼロ・DOM不要で、ブラウザ / Node.js / Worker で動きます。React コンポーネントも同じパッケージの dottomon/react エントリに入っています(React を使わない場合は一切ロードされません)。
開発中 (0.x): 生成されるピクセルはマイナーリリース間で変わることがあります(CHANGELOG に
[pixels-changed]と明記されます)。見た目を固定したい場合はバージョンを固定してください。
@dotmon/core/@dotmon/reactは本パッケージ(dottomon)への再エクスポートとして廃止されました。import の書き換えだけで移行できます:@dotmon/core→dottomon,@dotmon/react→dottomon/react。
import { generateSvg, createMonster, getStats } from "dottomon";
const { svg } = generateSvg("ポコ", { preset: "retro", view: "left" });
const mon = createMonster("ポコ");
mon.svg("left", 1); // 左向き・歩行フレーム1
getStats("ポコ"); // { lv, nature, hp, mp, atk, def, spd, luck }import { MonsterAvatar } from "dottomon/react";
<MonsterAvatar seed="ポコ" size={64} />
<MonsterAvatar seed="ポコ" preset="retro" size={96} animate background="#a5bdd2" />- プリセット:
mochi(もちもち・連結でまるい体)/retro(レトロ・ミラーしたノイズで顔が浮かぶ)/chaos(カオス・かたまり状ノイズ+アクセント色、左右非対称) - オプション:
outline(ふちどり),face(かお),legs(あし),gapFill(すきまなくし: 密閉された穴を白で埋めて背景の透けを防ぐ),view,frame - ビューとフレームは個体を変えません: 分岐では乱数を消費しない設計なので、どの向き・どのコマでも同一個体です
- ステータス:
getStats(seed)。せいかく等の表示名はdottomon/locales/jaの辞書にあります - ファイル出力(ブラウザ専用):
dottomon/renderから PNG / 2コマGIF / スプライトシート(Phaser・PixiJS対応)/ アセット一式ZIP - React:
dottomon/reactの<MonsterAvatar />(2コマ歩行アニメはページ内の全アバターが同期)と hooks(useMonster,useMonsterTicker,subscribeTicker) - CLI(インストール不要・
npx dottomon ポコだけで動きます)- 表示: そのままでスプライト+名前ラベル /
--cardステータスカード /--card-fullWeb同様の色付きバー /-n 5なかまたちをターミナル幅に合わせたグリッド表示(最大10) /--walk2コマ歩行アニメ(約2.5秒で自動終了) - 保存:
-o poko.png(.svg/.gifも拡張子で判別、--sizeでサイズ指定) /--zipで Web版と同一構成の全部入りZIP(README + 12 PNG + 4 GIF + スプライトシート) - その他:
--style/--view/--lang ja|en(カードとZIPのREADMEに反映) /--no-name/--no-color。全オプションの一覧は上の CLI セクションへ - 表示はターミナル依存です(半ブロック文字で描画するため、環境によっては崩れる・表示できないことがあります)。Ghostty / iTerm2 / VS Code 等のモダンなターミナル推奨。崩れる場合は等幅フォント・行間1.0にし、「東アジア曖昧文字幅を広くする」設定をオフにしてください(macOS 標準ターミナル+日本語環境で特に該当)
- 表示: そのままでスプライト+名前ラベル /
- ピクセルAPI:
generatePixels(seed)が色付きピクセルグリッドを返します(ターミナル・canvas・ゲームエンジン向け)
ライセンス: MIT
