Building Autonomous Generative Art with JavaScript and SVG
BloodRemembers.art
BloodRemembers.art is a generative art project that creates unique visual artworks autonomously using JavaScript and SVG. Each piece is algorithmically composed, meaning no two outputs are identical. The system uses mathematical functions, controlled randomness, and compositional rules to generate artwork that feels intentional rather than random.
This is a deeply personal project. The name "Blood Remembers" comes from the idea that certain aesthetic sensibilities and patterns are carried in us, almost instinctually. The art explores organic forms, natural patterns, and emergent complexity arising from simple rules.
Why SVG?
I chose SVG over canvas or WebGL for several reasons:
- Resolution independence: SVG scales perfectly to any size, which matters for print
- Manipulability: Every element is a DOM node that can be inspected, styled, and animated
- File size: Generated artworks are typically 50-200KB, making them easy to store and serve
- Accessibility: SVG elements can carry semantic meaning via titles and descriptions
The Composition Engine
The core of the system is a composition engine that works in layers. Each layer applies a different generative algorithm, and the layers combine to create the final piece.
Layer Types
- Substrate layer: Background textures and gradients using Perlin noise
- Structural layer: Geometric frameworks based on golden ratio divisions, Voronoi diagrams, or recursive subdivision
- Organic layer: Flowing curves generated by particle systems or L-system inspired algorithms
- Detail layer: Small elements that add texture and visual interest
class CompositionEngine {
constructor(config) {
this.width = config.width || 1000;
this.height = config.height || 1000;
this.seed = config.seed || Math.random();
this.rng = createSeededRandom(this.seed);
this.layers = [];
}
addLayer(generator, params) {
this.layers.push({ generator, params });
return this;
}
render() {
const svg = createSVGElement(this.width, this.height);
for (const layer of this.layers) {
const elements = layer.generator(this.rng, layer.params);
elements.forEach(el => svg.appendChild(el));
}
return svg;
}
}
Seeded Randomness
Every artwork is generated from a seed value. This is crucial because it means any piece can be reproduced exactly by using the same seed. I use a mulberry32 PRNG (pseudorandom number generator) seeded with a 32-bit integer:
function createSeededRandom(seed) {
let state = seed | 0;
return function() {
state = (state + 0x6D2B79F5) | 0;
let t = Math.imul(state ^ (state >>> 15), 1 | state);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
Algorithmic Techniques
Flow Fields
One of the most visually striking techniques I use is flow fields. A 2D vector field is generated using Perlin noise, and particles trace paths through this field, leaving SVG path elements as their trails:
function generateFlowField(rng, params) {
const paths = [];
const noiseScale = params.noiseScale || 0.005;
for (let i = 0; i < params.particleCount; i++) {
let x = rng() * params.width;
let y = rng() * params.height;
const points = [`M ${x} ${y}`];
for (let step = 0; step < params.stepCount; step++) {
const angle = noise2D(x * noiseScale, y * noiseScale) * Math.PI * 2;
x += Math.cos(angle) * params.stepSize;
y += Math.sin(angle) * params.stepSize;
points.push(`L ${x} ${y}`);
}
paths.push(createPath(points.join(" "), params.style));
}
return paths;
}
Recursive Subdivision
Another technique I use frequently is recursive subdivision of the canvas. Starting with the full rectangle, the algorithm divides it into smaller regions with varying aspect ratios, creating compositions reminiscent of Mondrian but with organic variation.
Colour Systems
Colour is generated algorithmically too. I work in HSL colour space and define palettes using harmonic relationships:
- Analogous palettes: Hues within 30 degrees of a base hue, producing harmonious, natural-feeling schemes
- Complementary with variation: Two opposing hues with random walks in saturation and lightness
- Monochromatic: Single hue with wide variation in saturation and lightness for depth
The Autonomous Generation System
The "autonomous" aspect means the system generates new artworks on a schedule without any input from me. A Node.js script runs daily, creates a new piece with a random seed, renders it to SVG, generates a PNG preview, and publishes it to the website.
Each generated piece is also stored with its seed and configuration, so any piece can be regenerated or used as a starting point for exploration by tweaking parameters.
Exhibition and Output Formats
The generated artworks are published in multiple formats. The primary output is SVG for web display and archiving. I also render high-resolution PNGs at 4000x4000 pixels for print. Some pieces are rendered at even larger sizes for physical printing. The website displays a gallery of recent pieces with their seed values, generation parameters, and the specific algorithms used. This transparency is intentional: generative art is as much about the process as the output, and showing the parameters invites exploration and understanding.
Community and Open Source
I released several of the core algorithms as standalone JavaScript modules that other generative artists can use and modify. The flow field generator, the seeded random utilities, and the colour palette generator are all available as open source. This has connected me with a small but passionate community of creative coders who share techniques and inspiration. Some of my most interesting pieces came from combining my algorithms with techniques I learned from others in this community.
What Makes Generative Art Interesting
The thing I find most fascinating about generative art is the tension between control and emergence. I define the rules, the algorithms, the colour relationships, and the compositional structure. But within those constraints, the output is unpredictable. Occasionally the system produces something genuinely beautiful that I could never have designed manually. Those moments are why I keep building.
From an engineering perspective, this project has taught me a lot about algorithm design, performance optimisation in the browser, and the surprisingly deep intersection between mathematics and aesthetics. Every generative artist is, at some level, an algorithm designer exploring the space between order and chaos.