ALGORITHM is one of 25 sites designed and built by Formwork to demonstrate web design, motion, and generative craft. Here is exactly how this one was made — a hero that repaints on every visit, yet stays perfectly reproducible.
The brief was "code-drawn art that renders unique every visit." So the site's entire identity is a seed: a single 32-bit integer that fixes the palette, the noise field, and every mark on screen. Reload with the same seed and you get the same drawing to the pixel; change one digit and the whole composition reorganises. The seed rides in the URL, so a visit is a shareable original.
<canvas> — thousands of particles advected through Perlin noise, leaving fading ink trails.mulberry32 PRNG — 7 lines, deterministic, seeded once and drawn from in a fixed order.Each frame, every particle reads the noise field beneath it, turns that value into an angle, steps forward, and draws the tiny segment it just travelled. A near-transparent black rectangle painted over the canvas each frame lets old trails fade, so the field breathes like ink in water. This is the actual loop that runs the hero:
function advance(fadeOn) {
if (fadeOn) { ctx.fillStyle = 'rgba(12,13,15,0.024)'; ctx.fillRect(0,0,w,h); }
ctx.lineWidth = 1.15; ctx.lineCap = 'round';
for (let i = 0; i < particles.length; i++) {
const pt = particles[i];
const ang = fbm(noise, pt.x*cfg.scale, pt.y*cfg.scale) * TAU * cfg.turns;
const nx = pt.x + Math.cos(ang)*cfg.speed;
const ny = pt.y + Math.sin(ang)*cfg.speed;
ctx.strokeStyle = pt.col;
ctx.beginPath(); ctx.moveTo(pt.x, pt.y); ctx.lineTo(nx, ny); ctx.stroke();
pt.x = nx; pt.y = ny; pt.life++;
if (pt.life > pt.max || nx < -12 || nx > w+12) spawn(Math.random, pt);
}
}
The noise function is a seeded Perlin generator (its permutation table is shuffled by the
same PRNG), wrapped in four octaves of fractal Brownian motion so the field has both broad currents and
fine detail. Because the field, palette, and initial particle positions are all drawn from the seed in a
fixed order, the opening frame is identical every time — after that the particles wander freely.
?seed= with history.replaceState; "Copy link" hands someone the exact drawing.devicePixelRatio is capped at 1.5 and the particle count scales with screen area, so phones throttle down automatically..no-canvas class swaps in a CSS gradient; nothing throws.js class is on <html>, so a failed script never leaves a blank page.Every site here is static, so hosting is three commands:
git init -b main && git add -A && git commit -m "ship"
gh repo create formwork-algorithm --public --source=. --push
gh api --method POST /repos/OWNER/formwork-algorithm/pages \
-f 'source[branch]=main' -f 'source[path]=/'
Use relative paths (./main.js, not /main.js) because project
Pages live under /repo-name/. Add an empty .nojekyll file so every asset serves verbatim.
That's the whole recipe: one PRNG, one noise field, a canvas, and strong type. The other 24 sites each swap the central technique — shaders, kinetic type, 3D — but the discipline is the same.