Turtles all the way down
Tue Jul 01 2025
Articles in the On Grids series
- Let's go deeper
- Iterating on a theme
- Some useful functions
- On Grids
- Turtles all the way down
I've been meaning to get back into working with plotted generative art for some time now, and I have a few ideas for the development of a few posts about it. But in order to get there, I wanted a simple, SVG based canvas to create such artwork. There are a number of prebuilt options out there - paper.js, SCG.js etc. - but they're either too fully-featured or too opinionated for what I want to achieve.
Something that's always been really cool in this space is the turtle graphics API. It's super simple, and very easy to understand. It uses a convention of a turtle that has three attributes - location, orientation, and a pen. You send commands to the turtle to change one of these properties in a variety of ways, and it draws lines.

The turtle moves around the canvas with simple-to-understand commands like forward, backward, left, right etc.
There is a fantastic website called Turtletoy, created and operated by the incredibly talented Reinder Nijhoff, that implements this API using javascript and provides a community tool to allow people to create and publish tutles. Make sure you check it out, there is some incredible work over there.
So I've created a simple class called Turtleman that allows me to create these sorts of drawings, you can check it out on codepen or github. This library provides a relatively simple API, as demonstrated here:
const toy = new Turtleman();
container.appendChild(toy.svg);
const squareCommands = `
forward 100
right 90
forward 100
right 90
forward 100
right 90
forward 100
`;
toy.drawCommands(squareCommands);
What's cool about this is that you can generate some relatively complex drawings with relatively simple building blocks. Here's the code to generate the spiral in the above example:
// Coil spacing
const tightness = .6;
// The distance between points
const step_size = 3;
// Current angle in radians
let theta = 0;
// Current radius
let radius = .1;
i = 0;
while (radius < 500) {
const d_theta = step_size /
Math.sqrt(
tightness * tightness +
radius * radius
);
theta += d_theta;
radius = tightness * theta;
let x = Math.cos(theta) * radius +
toy.width / 2;
let y = Math.sin(theta) * radius +
toy.height / 2;
toy.goto(x, y);
}

But with some relatively straightforward changes, you can create something which appears much more complex.
const tightness = .6;
const step_size = 3;
let theta = 0;
let radius = .1;
i = 0;
while (radius < 500) {
const d_theta = step_size /
Math.sqrt(
tightness * tightness +
radius * radius
);
theta += d_theta;
radius = tightness * theta;
let x = Math.cos(theta) * radius +
toy.width / 2;
let y = Math.sin(theta) * radius +
toy.height / 2;
const scale = .04;
const size = 20;
x += (
Math.sin((x*scale)) +
Math.cos(y*scale)) * size;
y += (
Math.cos((x*scale)) +
Math.sin(y*scale)) * size;
toy.goto(x, y);
}

What's next?
I think I want to do a series of posts on generative art using this system. Probably starting with a breakdown of grids and their uses with systems like this.