~/lab/doodle
Doodle
Black-ink doodles on textured paper for my Substack posts
claude --plugin-dir /path/to/hidkit| Preset | Size in pixels | Use |
|---|---|---|
| `cover` | 1456 × 1048 | Post header and social preview |
| `wide` | 1200 × 630 | Wide social preview |
| `inline` | 1460 wide, free height | Drawing inside the text, such as a diagram |
| `spot` | 600 × 600 | Small icon between sections |Why I built it
I want my Substack posts to have drawings that look made by a person, with a small joke in them. Stock images and clip art do not do that. Doodle gives me a black-ink sketch from the idea of the post.
I ask for it in plain words, such as “header image for Substack”, “doodle”, or “dibújame”. The table in the snippet lists the formats, and cover is the default. The sizes come from third-party guides, not from the Substack help pages, so they are not verified.
The style guide
The model thinks of 3 concepts and picks the one that reads fastest. The guide asks for a twist on a familiar object instead of a literal scene. It avoids stock symbols, such as the light bulb and the rocket, unless a twist changes their meaning.
- Voice: self-deprecating and tender. The character doubts, makes small mistakes, and tries again.
- Composition: one focal point off center, 40 to 60 percent of the sheet empty, and 3 to 7 elements.
- Line: one pen with 3 weights. Shapes are paths, not
<rect>or<circle>, because a perfect shape looks like clip art.
Unless I ask for other people, a person in a drawing is the recurring character. He is a dark-skinned man with a short afro, a mustache, a goatee, and round glasses. He has 5 expressions (neutral, happy, worried, surprised, and tired) and a blink face for animation.
The ink script
node <skill-dir>/scripts/ink.mjs --preset <preset> <dir>/<slug>.svg
The script checks that the drawing has no color: it refuses gray, color, gradients, and opacity. It adds a hand-drawn ink filter and a second, thinner pen line.
Then it puts the drawing on paper: newsprint, sketchbook, kraft, or white. By default it also adds tape on 2 corners and 2 ink specks. --material full adds a coffee ring, and --material none removes the marks.
The script exports a PNG with headless Chrome. The model then looks at the PNG and answers a taste check, such as “does the idea read in 2 seconds without the title?”. If a check fails, it fixes the SVG one time.