Isometric diagrams in plain SVG: projection, four-tone shading and painter's order
Isometric drawings explain hardware and systems better than flat boxes and arrows: a reader sees depth, which part sits on which, and where things connect. You don't need a 3D engine for them. About 45 lines of JavaScript and plain SVG polygons are enough to start, and the three ideas below are the ones that decide whether the result looks crafted or broken.
The cover image is exactly what the script at the end draws: a base plate with a tank, a pipe, a pump and a valve.
1. The projection
In a classic isometric view the x and y axes sit 30 degrees below the horizontal and z points straight up. A world point (x, y, z) lands on screen at:
const COS30 = Math.cos(Math.PI / 6), SIN30 = 0.5;
function project([x, y, z], s = 20, ox = 280, oy = 190) {
return [ox + (x - y) * COS30 * s, oy + (x + y) * SIN30 * s - z * s];
}
s is the pixel size of one world unit and (ox, oy) is where the world origin lands. On screen +x runs down-right, +y runs down-left and +z runs up. That means a bigger x + y is closer to the viewer, which matters in step 3.
2. A box is three faces, and each face gets its own tone
From this camera you only ever see three faces of a box: the top, the face at x + w (screen right) and the face at y + d (screen left). Draw those three as polygons and skip the rest.
Flat colour makes boxes look like stickers. The trick is four tones from one base colour: the top lightest (it faces the light), the right face at the base colour, the left face darker, and an outline darker still so edges read on any background.
function tones(hex) {
const n = parseInt(hex.slice(1), 16), c = [n >> 16, (n >> 8) & 255, n & 255];
const mix = k => '#' + c.map(v => Math.round(Math.min(255, v * k)).toString(16).padStart(2, '0')).join('');
return { top: mix(1.25), right: mix(1.0), left: mix(0.75), line: mix(0.45) };
}
Keep the same four multipliers for every material and the whole drawing reads as lit from one direction.
3. Painter's order (the bug that bites first)
SVG paints in document order, so whatever comes later covers what came before. You have to emit far things first.
The obvious first try is to sort every box by its near corner, (x + w) + (y + d). It looks reasonable on paper and fails at once on this scene: the base plate is the widest part, so its near corner is the biggest, so it is drawn last and buries the pipe and the valve, the lower half of the tank and most of the pump.
For drawings built in layers (a plate, then parts standing on it) a two-key sort fixes it: the bottom z first, then the near corner inside each layer.
const order = (a, b) => (a.z - b.z) || ((a.x + a.w + a.y + a.d) - (b.x + b.w + b.y + b.d));
Know its limits. It holds for compact, similar-sized parts. A long member breaks it even when nothing touches: a long pipe running along x behind a short pump has the bigger near-corner sum, so it gets drawn after the pump and paints over it. Parts that float above another layer can fail the same way. For anything beyond simple layered scenes, use the separation test: with this camera, box A is behind box B when A.x + A.w <= B.x, or A.y + A.d <= B.y, or A.z + A.h <= B.z. Add an edge for each pair whose screen outlines overlap, then sort topologically. If the graph has a cycle (three bars in a pinwheel, each in front of the next), split one box in two to break it.
The whole script
Save it as iso.mjs and run node iso.mjs > machine.svg. Open the SVG in any browser. Node 18 or newer is enough; there are no dependencies.
// iso.mjs: isometric boxes in plain SVG, no libraries. Run: node iso.mjs > machine.svg
const COS30 = Math.cos(Math.PI / 6), SIN30 = 0.5;
// World -> screen. On screen, +x runs down-right, +y runs down-left, +z runs straight up. One unit = `s` px.
function project([x, y, z], s = 20, ox = 280, oy = 190) {
return [ox + (x - y) * COS30 * s, oy + (x + y) * SIN30 * s - z * s];
}
// Four tones per material: top lightest, right face mid, left face darker, outline darkest.
function tones(hex) {
const n = parseInt(hex.slice(1), 16), c = [n >> 16, (n >> 8) & 255, n & 255];
const mix = k => '#' + c.map(v => Math.round(Math.min(255, v * k)).toString(16).padStart(2, '0')).join('');
return { top: mix(1.25), right: mix(1.0), left: mix(0.75), line: mix(0.45) };
}
const pts = p => p.map(q => project(q).map(v => v.toFixed(1)).join(',')).join(' ');
// A box at (x, y, z) with size (w, d, h). Only the three faces the viewer sees are drawn.
function box({ x, y, z, w, d, h, color }) {
const t = tones(color);
const top = [[x, y, z + h], [x + w, y, z + h], [x + w, y + d, z + h], [x, y + d, z + h]];
const right = [[x + w, y, z], [x + w, y + d, z], [x + w, y + d, z + h], [x + w, y, z + h]];
const left = [[x, y + d, z], [x + w, y + d, z], [x + w, y + d, z + h], [x, y + d, z + h]];
const face = (p, fill) => `<polygon points="${pts(p)}" fill="${fill}" stroke="${t.line}" stroke-width="1" stroke-linejoin="round"/>`;
return face(left, t.left) + face(right, t.right) + face(top, t.top);
}
// Painter's order: draw what is farther from the viewer first. For parts that sit on layers
// (a plate, then things standing on it), sort by the bottom z first, then by the near corner
// (x + w) + (y + d) inside each layer.
const order = (a, b) => (a.z - b.z) || ((a.x + a.w + a.y + a.d) - (b.x + b.w + b.y + b.d));
const parts = [
{ x: 0, y: 0, z: 0, w: 10, d: 6, h: 1, color: '#5b6b82' }, // base plate
{ x: 1, y: 1, z: 1, w: 3, d: 3, h: 5, color: '#2f7de1' }, // tank
{ x: 4, y: 2, z: 1, w: 3, d: 1, h: 1, color: '#9aa7b8' }, // pipe
{ x: 7, y: 1, z: 1, w: 2, d: 3, h: 3, color: '#e2a03f' }, // pump
{ x: 7.5, y: 4.5, z: 1, w: 1, d: 1, h: 0.6, color: '#d9534f' } // valve
];
const body = [...parts].sort(order).map(box).join('\n ');
process.stdout.write(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 460" width="600" height="460">
<rect width="600" height="460" fill="#0f1420"/>
${body}
</svg>
`);
To add a part, add one line to parts. To change the look, change the four multipliers in tones. Pick mid-tone base colours: tones clamps at 255, so a very light base loses the contrast between its top and right faces. On Windows PowerShell 5.1, node iso.mjs | Out-File -Encoding utf8 machine.svg avoids a UTF-16 file.
Where to take it next
Real explainer figures need more than boxes: cylinders and rounded parts, labels that never collide, cutaways that open a wall to show the inside, live numbers on gauges, and motion. Each of those is its own small project.
For detailed figures without building the renderer yourself, the open-source anatomy skill (MIT) is an agent skill that has Claude Code create detailed, interactive isometric SVG illustrations of machines and systems. Its source is a good place to learn the techniques.
Disclosure: I'm the founder of Homingo; Homingo Learn is our learning brand. We built a paid Claude Code skill that includes that open-source skill with our reel and explainer kit on top. Isometric Explainers adds a 1080x1920 reel kit (camera moves, cutaways, callouts locked to parts, named cues synced to your narration), live readouts, and built-in layout, motion and geometry checks, so one figure becomes both a docs illustration and a vertical explainer reel. It's Rs 1,499 one-time: Isometric Explainers for Claude Code. Everything above works without it.
Mentions
Isometric diagrams in plain SVG: projection, four-tone shading and painter's order Isometric drawings explain hardware and systems better than flat boxes and arrows: a reader sees depth, which part sits on which, and where things connect. You don't need a 3D engine for them. About 45 lines of JavaScript and plain SVG polygons are enough to start, and the three ideas below are the ones that decide whether the result looks crafted or broken. The cover image is exactly what the script at the end draws: a base plate with a tank, a pipe, a pump and a valve. 1. The projection In a classic isometric view the x and y axes sit 30 degrees below the horizontal and z points straight up. A world point (x, y, z) lands on screen at: const COS30 = Math.cos(Math.PI / 6), SIN30 = 0.5; function project([x, y, z], s = 20, ox = 280, oy = 190) { return [ox + (x - y) * COS30 * s, oy + (x + y) * SIN30 * s - z * s]; } s is the pixel size of one world unit and (ox, oy) is where the world origin lands. On screen +x runs down-right, +y runs down-left and +z runs up. That means a bigger x + y is closer to the viewer, which matters in step 3. 2. A box is three faces, and each face gets its own tone From this camera you only ever see three faces of a box: the top, the face at x + w (screen right) and the face at y + d (screen left). Draw those three as polygons and skip the rest. Flat colour makes boxes look like stickers. The trick is four tones from one base colour: the top lightest (it faces the light), the right face at the base colour, the left face darker, and an outline darker still so edges read on any background. function tones(hex) { const n = parseInt(hex.slice(1), 16), c = [n >> 16, (n >> 8) & 255, n & 255]; const mix = k => '#' + c.map(v => Math.round(Math.min(255, v * k)).toString(16).padStart(2, '0')).join(''); return { top: mix(1.25), right: mix(1.0), left: mix(0.75), line: mix(0.45) }; } Keep the same four multipliers for every material and the whole drawing reads as lit from one direction. 3. Painter's order (the bug that bites first) SVG paints in document order, so whatever comes later covers what came before. You have to emit far things first. The obvious first try is to sort every box by its near corner, (x + w) + (y + d). It looks reasonable on paper and fails at once on this scene: the base plate is the widest part, so its near corner is the biggest, so it is drawn last and buries the pipe and the valve, the lower half of the tank and most of the pump. For drawings built in layers (a plate, then parts standing on it) a two-key sort fixes it: the bottom z first, then the near corner inside each layer. const order = (a, b) => (a.z - b.z) || ((a.x + a.w + a.y + a.d) - (b.x + b.w + b.y + b.d)); Know its limits. It holds for compact, similar-sized parts. A long member breaks it even when nothing touches: a long pipe running along x behind a short pump has the bigger near-corner sum, so it gets drawn after the pump and paints over it. Parts that float above another layer can fail the same way. For anything beyond simple layered scenes, use the separation test: with this camera, box A is behind box B when A.x + A.w <= B.x, or A.y + A.d <= B.y, or A.z + A.h <= B.z. Add an edge for each pair whose screen outlines overlap, then sort topologically. If the graph has a cycle (three bars in a pinwheel, each in front of the next), split one box in two to break it. The whole script Save it as iso.mjs and run node iso.mjs > machine.svg. Open the SVG in any browser. Node 18 or newer is enough; there are no dependencies. // iso.mjs: isometric boxes in plain SVG, no libraries. Run: node iso.mjs > machine.svg const COS30 = Math.cos(Math.PI / 6), SIN30 = 0.5; // World -> screen. On screen, +x runs down-right, +y runs down-left, +z runs straight up. One unit = `s` px. function project([x, y, z], s = 20, ox = 280, oy = 190) { return [ox + (x - y) * COS30 * s, oy + (x + y) * SIN30 * s - z * s]; } // Four tones per material: top lightest, right face mid, left face darker, outline darkest. function tones(hex) { const n = parseInt(hex.slice(1), 16), c = [n >> 16, (n >> 8) & 255, n & 255]; const mix = k => '#' + c.map(v => Math.round(Math.min(255, v * k)).toString(16).padStart(2, '0')).join(''); return { top: mix(1.25), right: mix(1.0), left: mix(0.75), line: mix(0.45) }; } const pts = p => p.map(q => project(q).map(v => v.toFixed(1)).join(',')).join(' '); // A box at (x, y, z) with size (w, d, h). Only the three faces the viewer sees are drawn. function box({ x, y, z, w, d, h, color }) { const t = tones(color); const top = [[x, y, z + h], [x + w, y, z + h], [x + w, y + d, z + h], [x, y + d, z + h]]; const right = [[x + w, y, z], [x + w, y + d, z], [x + w, y + d, z + h], [x + w, y, z + h]]; const left = [[x, y + d, z], [x + w, y + d, z], [x + w, y + d, z + h], [x, y + d, z + h]]; const face = (p, fill) => `<polygon points="${pts(p)}" fill="${fill}" stroke="${t.line}" stroke-width="1" stroke-linejoin="round"/>`; return face(left, t.left) + face(right, t.right) + face(top, t.top); } // Painter's order: draw what is farther from the viewer first. For parts that sit on layers // (a plate, then things standing on it), sort by the bottom z first, then by the near corner // (x + w) + (y + d) inside each layer. const order = (a, b) => (a.z - b.z) || ((a.x + a.w + a.y + a.d) - (b.x + b.w + b.y + b.d)); const parts = [ { x: 0, y: 0, z: 0, w: 10, d: 6, h: 1, color: '#5b6b82' }, // base plate { x: 1, y: 1, z: 1, w: 3, d: 3, h: 5, color: '#2f7de1' }, // tank { x: 4, y: 2, z: 1, w: 3, d: 1, h: 1, color: '#9aa7b8' }, // pipe { x: 7, y: 1, z: 1, w: 2, d: 3, h: 3, color: '#e2a03f' }, // pump { x: 7.5, y: 4.5, z: 1, w: 1, d: 1, h: 0.6, color: '#d9534f' } // valve ]; const body = [...parts].sort(order).map(box).join('\n '); process.stdout.write(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 460" width="600" height="460"> <rect width="600" height="460" fill="#0f1420"/> ${body} </svg> `); To add a part, add one line to parts. To change the look, change the four multipliers in tones. Pick mid-tone base colours: tones clamps at 255, so a very light base loses the contrast between its top and right faces. On Windows PowerShell 5.1, node iso.mjs | Out-File -Encoding utf8 machine.svg avoids a UTF-16 file. Where to take it next Real explainer figures need more than boxes: cylinders and rounded parts, labels that never collide, cutaways that open a wall to show the inside, live numbers on gauges, and motion. Each of those is its own small project. For detailed figures without building the renderer yourself, the open-source anatomy skill (MIT) is an agent skill that has Claude Code create detailed, interactive isometric SVG illustrations of machines and systems. Its source is a good place to learn the techniques. Disclosure: I'm the founder of Homingo; Homingo Learn is our learning brand. We built a paid Claude Code skill that includes that open-source skill with our reel and explainer kit on top. Isometric Explainers adds a 1080x1920 reel kit (camera moves, cutaways, callouts locked to parts, named cues synced to your narration), live readouts, and built-in layout, motion and geometry checks, so one figure becomes both a docs illustration and a vertical explainer reel. It's Rs 1,499 one-time: Isometric Explainers for Claude Code. Everything above works without it.
This AI skill explains tech ideas by inventing a working machine and drawing it as an interactive isometric figure ⚙️ 🔗 wheresryan22/anatomy Credits: wheresryan22/anatomy #anatomy #javascript #svg
This looks very similar to wheresryan22/anatomy which popularized a very similar style of figure a few weeks ago. You can also quickly make similar diagrams with sites like diagrams.ink (disclaimer: affiliated) or three.ws
⚠️ Limits: not a chart library, no people or exact maps, and builds are deliberately slow. 3D mode is beta. MIT licensed, 17.1k stars. #DevTools #DataViz wheresryan22/anatomy
"An agent skill for creating detailed, interactive isometric illustrations of real-world machines and complex systems. Generates polished SVGs with optional WebGL shaders and 3D effects." ➡️ this is the first time i see such a skill! wheresryan22/anatomy Community Overview: lifehubber.com Resources are shared for discovery and are not independently vetted—please do your own due diligence. New resources are added regularly — feel free to join the sub for updates. Full searchable archive of all resources posted so far on our community site, LifeHubber: lifehubber.com 300+ open-ish AI models, agents, tools, datasets, and related resources, with filtering and sorting.
"An agent skill for creating detailed, interactive isometric illustrations of real-world machines and complex systems. Generates polished SVGs with optional WebGL shaders and 3D effects." ➡️ this is the first time i see such a skill! wheresryan22/anatomy Community Overview: lifehubber.com Resources are shared for discovery and are not independently vetted—please do your own due diligence. New resources are added regularly — feel free to join the sub for updates. Full searchable archive of all resources posted so far on our community site, LifeHubber: lifehubber.com 300+ open-ish AI models, agents, tools, datasets, and related resources, with filtering and sorting.
AI Just Made Physics Interactive. This Is Insane. (Anatomy) Anatomy is a new open-source Claude Code skill that turns complex algorithms, technical concepts, and engineering systems into interactive machines instead of traditional boxes-and-arrows diagrams. In this video, I test how Anatomy works with Claude Code, Codex, OpenCode, and Antigravity, explore its interactive SVG, WebGL, and experimental 3D capabilities, and show examples including an LRU cache, TCP handshake, Raptor rocket engine, turbofan, and other interactive technical visualizations. 🔗 Relevant Links Anatomy Repo - wheresryan22/anatomy Anatomy Docs - skills.wheresryan.sh ❤️ More about us Radically better observability stack: betterstack.com Written tutorials: betterstack.com Example projects: github.com/BetterStackHQ 📱 Socials Twitter: twitter.com Instagram: instagram.com TikTok: tiktok.com LinkedIn: linkedin.com 📌 Chapters: 00:00 – This Claude Code Skill Turns Algorithms Into Interactive Machines 00:27 – Anatomy Demos: Rocket Engines, LRU Cache & Interactive SVGs 01:01 – Showcasing Anatomy Repo 02:05– How Anatomy Builds Interactive Simulations with Real Data 02:20 – How Anatomy Works with Claude Code, Codex & OpenCode 02:53 – How Does Anatomy Behave 03:15 – Our Final Output in Anatomy 04:00 – Anatomy vs Mermaid, D2 & Traditional Diagrams 04:12 – The Catch: Generation Times, Token Costs & Performance 05:20 – Who Should Actually Use Anatomy? 05:45 – Final Thoughts: Are Interactive AI Diagrams Worth It?
5 Free GitHub Repos That Blew Up This Year Five free AI tools on GitHub that blew up this year, and what each one does. 1. God's Eye View - a spy-satellite globe in your browser, built on real public data (planes, ships, satellites) bilawalsidhu/gods-eye-view 2. Anatomy - a Claude skill that turns one sentence into an interactive machine you can click through wheresryan22/anatomy 3. VoiceStudio - voice cloning and dubbing like ElevenLabs, running on your own computer debpalash/VoiceStudio 4. PhotoCraft - a free Photoshop-style editor with layers and curves, part of the ArtCraft set of free Adobe-style apps (early alpha) storytold/photocraft 5. REA - point an AI agent at any app and it shows you how it works (332K stars) morluto/rea Star counts checked 19 Oct 2026. Music: "Listen Up" by Rama Low - bsta.rs #ai #github #claude
使用自己的声音,加讲解,配合👇 做讲解视频真的太爽了! Skill:wheresryan22/anatomy t.co
「Github一周热点135期」艺术家的IDE、交互式技术图解Skill、AI 生成原生PPT、多个 Agent 组织工具和复活的QQ宠物 1、项目名称:ArtCraft - 艺术家的AI IDE GitHub 链接:storytold/artcraft 2、项目名称:Anatomy - 生成交互式技术图解的 Skill GitHub 链接:wheresryan22/anatomy 3、项目名称:OpenRig - 组织多个 Agent 的工具 GitHub 链接:mvschwarz/openrig 4、项目名称:PPT Master - 生成原生PPT的工作流 GitHub 链接:hugohe3/ppt-master 5、项目名称:QQPet - QQ 宠物开源复刻版 GitHub 链接:AnkioTomas/qqpet