Guide · Character design
How to draw a character with SVG and AI
How Arttie the otter is drawn: hand-written SVG paths, a Python builder, a written "character bible" and a QA checklist that Claude follows for every post.
Last updated

1Start from one model sheet
The model sheet is a turnaround (front, side, back), the expressions and the colours, all drawn in SVG inside one HTML file. It's the source of truth. The rule in the workspace's CLAUDE.md is short:
1. reference/arttie-model-sheet.png / source/Main.dc.html: the official turnaround. If anything disagrees with it, the model sheet wins. 2. ARTTIE.md: written spec derived from the model sheet. 3. Posts.
2Write the look down as numbers
"Cute otter" means something different to every model, every time. The character bible (ARTTIE.md) pins each part down as exact path data in a 400×440 box:
Head: M88 172 Q86 96 200 76 Q314 96 312 172 Q310 246 200 254 Q90 246 88 172 Z Ears: circle (102,120) r14 and (298,120) r14, drawn before the head Tail: M262 350 Q312 358 342 384 Q358 400 344 410 Q330 416 310 404 Q286 392 262 386 Z
It also has the palette as hex values (fur #A97850, tee #41527A, shorts #DCCAA0), the line weights (6px outlines, 3–4px inner lines) and the draw order.
3Build the figure from code, never from an old post
Old posts can be on an older version of the design (Arttie is on v6), so copying from one brings old mistakes back. So a Python builder, arttie.py, produces the full front view, and each post only adds arms, a face and props:
arttie(uid, arms=[HANG_L, WAVE_R], face='happy') # emits the defs (hand-drawn "wobble" filter, sleeve masks) and the full figure in draw order
Running python source/arttie.py on its own checks the output against the model sheet.
4Turn every repeated mistake into a written rule
Shoulders were the hardest part. The profile photo took five rounds because one sleeve kept starting lower than the other. After that, the fix went into the bible as numbered rules, for example:
1. Both sleeves start from the same shoulder point. Left pivot=(126,254), right pivot=(274,254) (±2px), shift=5. If the two sleeve tops aren't level, the torso reads lopsided.
The same goes for small things: a single raised finger on a mitten paw reads as a rude gesture, so the rule is "point sideways".
5Render and check every post
A post is an HTML file at 1080×1350 (Instagram's 4:5). Headless Chrome turns it into a PNG, and a checker lints the post before it's saved:
python source/render.py posts/<folder> # post.html -> post.png, waits for the fonts python source/check_posts.py # must show 0 errors
Then Claude zooms into the PNG and runs the bible's QA checklist: proportions, arm gaps, sleeves with cuffs, nothing covering the face.
6Keep the context lean
The bible says it in its first line: it's a "quick reference so future sessions don't need to re-read the HTML/PNG files". Re-reading the 106 KB model-sheet HTML every session would burn tokens. A short text spec gives Claude the same facts for a fraction of the cost (more on saving tokens).