Where ideas percolate and thoughts brew

The Authenticity Paradox

About This Sketch

A visual contrast between rigid authenticity (particles tethered to fixed identities) and fluid growth (particles free to explore and change). The left side shows how commitment to an "authentic self" constrains movement to tiny orbits around a fixed point. The right side demonstrates the freedom of allowing identity to flow, change, and explore new territories through experimentation.

Algorithm

This sketch visualizes the paradox of authenticity through two contrasting particle systems. The left side shows "authentic" particles tethered to fixed positionsโ€”they can only orbit within a small radius of their original location, representing how authenticity thinking traps us in rigid identities. The right side shows fluid particles free to explore the entire space, leaving flowing trails that represent growth and change through experimentation. The visualization accompanies the blog post "The Authenticity Paradox" which argues that rigid commitment to an "authentic self" prevents the kind of experimentation and change that leads to genuine growth.

Pseudocode

SETUP:
  Create canvas (400x300)
  Initialize rigid particles in fixed grid on left side
  Initialize fluid particles with random positions on right side
  Each particle type has different movement rules

DRAW (every frame):
  Get current theme colors
  Clear background

  FOR each rigid particle:
    Pull strongly back toward fixed starting position
    Allow tiny orbital movement around that point
    Draw particle with visible tether to origin

  FOR each fluid particle:
    Move based on Perlin noise field
    Apply momentum and damping
    Wrap around canvas edges
    Store position history for trail
    Draw flowing trail and current position

  Draw dividing line between systems
  Label each side with its meaning

Source Code

let sketch = function(p) {
    let rigidParticles = [];
    let fluidParticles = [];
    let time = 0;

    class RigidParticle {
        constructor(x, y) {
            this.startX = x;
            this.startY = y;
            this.x = x;
            this.y = y;
            this.baseAngle = p.random(p.TWO_PI);
            this.orbitRadius = p.random(2, 5);
            this.locked = true;
        }

        update() {
            // Rigidly returns to fixed position
            let pullX = this.startX - this.x;
            let pullY = this.startY - this.y;
            this.x += pullX * 0.3;
            this.y += pullY * 0.3;

            // Small orbit around fixed point
            this.x += p.cos(this.baseAngle + time * 0.02) * this.orbitRadius * 0.5;
            this.y += p.sin(this.baseAngle + time * 0.02) * this.orbitRadius * 0.5;
        }

        draw(colors) {
            // Draw as small, constrained circle
            p.fill(...colors.accent2, 150);
            p.noStroke();
            p.circle(this.x, this.y, 6);

            // Draw tether to fixed point
            p.stroke(...colors.accent2, 50);
            p.strokeWeight(1);
            p.line(this.x, this.y, this.startX, this.startY);
        }
    }

    class FluidParticle {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.vx = p.random(-1, 1);
            this.vy = p.random(-1, 1);
            this.trail = [];
            this.maxTrail = 15;
            this.angle = p.random(p.TWO_PI);
            this.wobble = p.random(0.02, 0.05);
        }

        update() {
            // Fluid movement with noise
            let noiseVal = p.noise(this.x * 0.01, this.y * 0.01, time * 0.01);
            this.angle += (noiseVal - 0.5) * 0.3;

            // Move based on angle with wobble
            this.vx += p.cos(this.angle) * 0.2;
            this.vy += p.sin(this.angle) * 0.2;

            // Damping
            this.vx *= 0.95;
            this.vy *= 0.95;

            // Update position
            this.x += this.vx;
            this.y += this.vy;

            // Wrap around edges
            if (this.x < 0) this.x = p.width;
            if (this.x > p.width) this.x = 0;
            if (this.y < 0) this.y = p.height;
            if (this.y > p.height) this.y = 0;

            // Trail
            this.trail.push({x: this.x, y: this.y});
            if (this.trail.length > this.maxTrail) {
                this.trail.shift();
            }
        }

        draw(colors) {
            // Draw trail
            for (let i = 0; i < this.trail.length - 1; i++) {
                let alpha = (i / this.trail.length) * 100;
                p.stroke(...colors.accent1, alpha);
                p.strokeWeight(2);
                p.line(
                    this.trail[i].x, this.trail[i].y,
                    this.trail[i + 1].x, this.trail[i + 1].y
                );
            }

            // Draw particle
            p.fill(...colors.accent1, 200);
            p.noStroke();
            p.circle(this.x, this.y, 7);
        }
    }

    p.setup = function() {
        p.createCanvas(400, 300);
        p.colorMode(p.RGB);

        // Create rigid particles in a fixed pattern (left side)
        let gridSize = 25;
        let offsetX = 80;
        let offsetY = 50;
        for (let i = 0; i < 6; i++) {
            for (let j = 0; j < 4; j++) {
                let x = offsetX + i * gridSize;
                let y = offsetY + j * gridSize;
                rigidParticles.push(new RigidParticle(x, y));
            }
        }

        // Create fluid particles (right side)
        for (let i = 0; i < 25; i++) {
            let x = p.random(p.width * 0.5, p.width - 40);
            let y = p.random(40, p.height - 40);
            fluidParticles.push(new FluidParticle(x, y));
        }
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg);

        time++;

        // Draw rigid particles (left - trapped by authenticity)
        for (let particle of rigidParticles) {
            particle.update();
            particle.draw(colors);
        }

        // Draw fluid particles (right - free to change)
        for (let particle of fluidParticles) {
            particle.update();
            particle.draw(colors);
        }

        // Draw dividing line
        p.stroke(...colors.accent3, 100);
        p.strokeWeight(1);
        p.line(p.width / 2, 0, p.width / 2, p.height);

        // Draw labels
        p.fill(...colors.accent3);
        p.noStroke();
        p.textAlign(p.CENTER, p.TOP);
        p.textSize(10);
        p.text("\"Authentic\"", p.width * 0.25, 15);
        p.text("(Rigid, tethered to fixed identity)", p.width * 0.25, 28);

        p.text("Fluid", p.width * 0.75, 15);
        p.text("(Free to explore and change)", p.width * 0.75, 28);
    };
};