The Curation Trap
About This Sketch
A grid that oscillates between perfect curation and messy authenticity. Watch as the same underlying pattern transforms from Instagram-ready perfection to organic chaos and back again. This sketch accompanies the post "The Curation Trap" and explores how we've learned to filter every aspect of our lives into polished performances—and what we lose in the process.
Algorithm
This sketch visualizes the tension between curated perfection and authentic messiness. A grid of cells oscillates between two states:
**Curated Mode:** Perfect geometric pattern, uniform squares, predictable checkerboard arrangement. Every cell is aligned, sized consistently, and follows a clear pattern. This represents the polished, Instagram-ready version of reality.
**Authentic Mode:** Messy, inconsistent, organic. Circles instead of squares, varying sizes, random brightness and positioning. Some cells are "messy" by nature, others follow their own rules. This represents unfiltered reality.
The sketch smoothly transitions between these states every few seconds, showing how the same underlying grid (the same reality) can be presented in radically different ways. The transition reveals that curation isn't about changing what's there—it's about how it's presented.
Pseudocode
SETUP:
Create grid of cells (20x15)
Each cell has:
- Position in grid
- "Messy" flag (random)
- Brightness value (random)
- Size variation (random)
DRAW (every frame):
Get current theme colors
Update transition timer
Calculate filter amount (0 = authentic, 1 = curated)
For each cell in grid:
Calculate "curated" appearance:
- Uniform checkerboard pattern
- Perfect square shape
- Standard size
Calculate "authentic" appearance:
- Random brightness/messiness
- Organic circle shape
- Varying sizes
Interpolate between the two based on filter amount
Draw the cell
Display label ("curated" or "authentic")
Toggle between states every 3 seconds
METAPHOR:
Same grid, same underlying data, drastically different presentations.
Curation is a filter over reality, not reality itself.
Source Code
let sketch = function(p) {
let grid = [];
let gridSize = 20;
let cols, rows;
let time = 0;
let showFiltered = true;
let transitionTime = 0;
let transitionDuration = 180;
class Cell {
constructor(x, y) {
this.x = x;
this.y = y;
this.rawValue = p.noise(x * 0.1, y * 0.1, 0) * 255;
this.messy = p.random(0, 1) > 0.5;
this.brightness = p.random(100, 255);
this.size = p.random(0.7, 1.3);
}
getFilteredValue(colors) {
let pattern = Math.floor((this.x + this.y) / 2) % 2;
return pattern === 0 ? colors.accent1 : colors.accent2;
}
getRawValue(colors) {
if (this.messy) {
return colors.accent3;
} else {
return this.brightness > 180 ? colors.accent1 : colors.accent2;
}
}
display(colors, filterAmount) {
let filtered = this.getFilteredValue(colors);
let raw = this.getRawValue(colors);
let r = p.lerp(raw[0], filtered[0], filterAmount);
let g = p.lerp(raw[1], filtered[1], filterAmount);
let b = p.lerp(raw[2], filtered[2], filterAmount);
p.fill(r, g, b);
p.noStroke();
let cellSize = gridSize * p.lerp(this.size, 1.0, filterAmount);
let xPos = this.x * gridSize + gridSize / 2;
let yPos = this.y * gridSize + gridSize / 2;
if (filterAmount > 0.5) {
p.rect(xPos - cellSize / 2, yPos - cellSize / 2, cellSize, cellSize);
} else {
p.circle(xPos, yPos, cellSize);
}
}
}
p.setup = function() {
p.createCanvas(400, 300);
cols = Math.floor(400 / gridSize);
rows = Math.floor(300 / gridSize);
for (let i = 0; i < cols; i++) {
grid[i] = [];
for (let j = 0; j < rows; j++) {
grid[i][j] = new Cell(i, j);
}
}
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time += 0.01;
transitionTime += 1;
if (transitionTime > transitionDuration * 2) {
transitionTime = 0;
showFiltered = !showFiltered;
}
let targetFilter = showFiltered ? 1.0 : 0.0;
let currentPhase = (transitionTime % (transitionDuration * 2)) / transitionDuration;
let filterAmount;
if (currentPhase < 1) {
filterAmount = showFiltered ? currentPhase : 1 - currentPhase;
} else {
filterAmount = targetFilter;
}
filterAmount = p.constrain(filterAmount, 0, 1);
filterAmount = filterAmount * filterAmount * (3 - 2 * filterAmount);
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
grid[i][j].display(colors, filterAmount);
}
}
p.fill(...colors.accent3, 150);
p.noStroke();
p.textSize(11);
p.textAlign(p.LEFT);
if (filterAmount > 0.5) {
p.text('curated', 10, 20);
} else {
p.text('authentic', 10, 20);
}
};
};