Generative art
Skill nimadorostkar/Claude-Skills-collection/skills/design/generative-art
Use when creating algorithmic or generative visual art. Covers composition through code, controlled randomness, colour systems, and building work that is varied without being arbitrary.From its SKILL.md
npx -y skills add nimadorostkar/Claude-Skills-collection --skill generative-artAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
5.7 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
Generative Art
Purpose
Create visual work through code, where the interesting output comes from constrained randomness rather than unconstrained noise. Pure randomness produces mush; the craft is in the constraints.
When to Use
- Creating algorithmic or procedural visual work.
- Building a generative system that produces a family of related outputs.
- Data-driven visual work.
- Exploring composition computationally.
Capabilities
- Controlled randomness: distributions, noise fields, seeded reproducibility.
- Composition: grids, subdivision, packing, flow fields.
- Colour systems for generative palettes.
- Output at print resolution.
Inputs
- The visual idea or the underlying system.
- Constraints: palette, format, medium.
- Whether outputs must be reproducible (they should be).
Outputs
- A system producing a family of related, non-identical works.
- Seeded, reproducible output.
- Assets at the resolution the medium requires.
Workflow
- Seed the randomness — Always. An unseeded generative system produces something beautiful once and can never produce it again. This is the first thing to get right and the most commonly skipped.
- Constrain the space — Randomness within a structure. A grid whose cells vary, a palette whose members are sampled, an angle that jitters within a range. Unconstrained randomness is visual noise.
- Use noise, not uniform random, for anything spatial — Perlin or simplex noise produces coherent variation.
Math.random()per pixel produces static. - Build the palette as a system — Sample from a small set, or from a ramp. Per-element random colour destroys any coherence the composition had.
- Generate many, select few — The output of a generative system is a distribution. Produce a hundred, choose the ones that work, and adjust the constraints toward them.
- Render at the output resolution — Not scaled up afterwards. A generative composition designed at 800px and upscaled to print looks exactly like that.
Best Practices
- An unseeded system is a system that cannot be reproduced, iterated on, or printed at a different size. Seed it from the start.
- Perlin and simplex noise are what make generative work look organic rather than random. The difference between
random()andnoise(x, y)is the difference between static and a landscape. - Constrain the colour: sample from a palette of four, or from a single ramp. Fully random colour is the most reliable way to make generative work look amateurish.
- Symmetry and repetition give the eye something to hold. Pure variation with no structure is exhausting to look at.
- The best generative systems have one or two parameters that meaningfully change the output. A system with forty knobs is unexplorable.
- Produce original systems. Do not reimplement a recognizable artist's signature work.
Examples
Seeded, constrained, and using noise for coherence:
import { createNoise2D } from "simplex-noise";
import Alea from "alea";
// Seeded: this exact image can be regenerated, at any resolution, forever.
const SEED = "2026-07-14-a";
const prng = new Alea(SEED);
const noise2D = createNoise2D(prng);
// A palette, sampled — not random colour per element.
const PALETTE = ["#0f172a", "#1e40af", "#0891b2", "#f59e0b"];
const PAPER = "#faf8f3";
function draw(ctx, width, height) {
ctx.fillStyle = PAPER;
ctx.fillRect(0, 0, width, height);
const GRID = 48;
const cell = width / GRID;
for (let x = 0; x < GRID; x++) {
for (let y = 0; y < GRID; y++) {
// Noise, not random: adjacent cells are RELATED, which is what makes
// the field read as a structure rather than as static.
const n = noise2D(x * 0.06, y * 0.06); // -1..1, spatially coherent
const angle = n * Math.PI; // a flow field
const length = cell * (0.4 + Math.abs(n) * 0.9); // varies with the field
// Colour is sampled from the palette, indexed by the field — so colour
// varies coherently too, rather than speckling.
const colour = PALETTE[Math.floor(((n + 1) / 2) * PALETTE.length * 0.999)];
// Sparse: skip cells where the field is weak. Negative space is composition.
if (Math.abs(n) < 0.18) continue;
const cx = x * cell + cell / 2;
const cy = y * cell + cell / 2;
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(angle);
ctx.strokeStyle = colour;
ctx.lineWidth = cell * 0.14;
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(-length / 2, 0);
ctx.lineTo(length / 2, 0);
ctx.stroke();
ctx.restore();
}
}
}
// Print: render at the final resolution, not upscaled.
// A2 at 300 DPI = 4961 x 7016 px. The grid and line widths scale with `width`,
// so the same seed produces the same composition at any size.
Notes
- The line
if (Math.abs(n) < 0.18) continue;is doing a disproportionate amount of the compositional work: it creates negative space where the field is weak, which gives the piece structure. A generative system that fills every cell is almost always worse than one that does not. - Seeded PRNGs (Alea, and similar) are essential.
Math.random()cannot be seeded in JavaScript, which makes any system built on it irreproducible. - Generate in batches and curate. The system's output is a distribution; your job is to shape the distribution and then choose from it.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.