The Process

How it’s made

Every print here is drawn by code — no AI, no image models. Scroll, and watch one happen.

Scroll to begin

stage 1 of 6
01

It starts with one shape.

No canvas of paint — a literal <canvas> in your browser, and a single instruction: put a dark square here. That one command is the only drawing tool the rest of this needs.

Show the code
ctx.fillStyle = '#1C1A16';
ctx.fillRect(150, 150, 200, 200);
02

Repeat it on a grid.

Run that one instruction across rows and columns and you get structure — a checkerboard. Tidy, but perfectly predictable: it looks the same every single time. This is rules with no chance.

Show the code
for (let r = 0; r < 5; r++)
  for (let c = 0; c < 5; c++)
    ctx.fillRect(c*100, r*100, 100, 100);
03

Now, a roll of the dice.

Let each cell flip a coin — dark or light, decided at random. Suddenly it’s alive, and different on every refresh. But there’s a catch: make one you love and it’s gone the moment you look away.

Show the code
// each cell flips a coin
ctx.fillStyle = rng() < 0.5 ? ink : cream;
04

Pin the dice to a seed.

Here’s the trick that makes it art you can own. The randomness is tied to a single starting number — a seed. Same seed, same piece, forever, on any device. That little code in the corner of every print is the seed: the entire recipe, written once.

Show the code
// same seed -> same art, forever
const rng = makeRng(0x9E3779B9);
05

Layer colour, many times over.

Now vary everything from that one seed — position, size, translucency — and lay dozens of soft shapes over each other. The overlaps mix into colours the palette never named. The hues themselves come from documented historical sources, chosen by hand.

Show the code
ctx.globalAlpha = 0.35 + rng()*0.4;
ctx.arc(x, y, 10 + rng()*80, 0, 2*Math.PI);
06

Add grain so it feels printed.

Flat colour reads as “computer.” A last pass nudges every pixel a hair brighter or darker — the difference between a screenshot and something that looks like ink on paper. Then it’s rendered at 300 DPI, ready to print at any size.

Show the code
// nudge each pixel a little
d[i] += (rng() - 0.5) * 16;

Built with

HTML Canvas 2D Vanilla JavaScript Seeded randomness Historical palettes 300 DPI export Static · no servers
No AI · Code only

Made by hand, in code.

Every piece is drawn by algorithms I wrote — not generated by an AI image model, not traced, and not assembled from anyone else’s work. The seed in the corner is the proof: it’s the whole recipe, and it produces a piece that has never existed before and will never be drawn the same way twice.

rules + a seed → a composition → a print.

Visit the shop See the collections