Where ideas percolate and thoughts brew

The Productivity Paradox

About This Sketch

Visualizing the productivity paradox Center: actual productive work (small, simple, direct) Surrounding: layers and layers of productivity infrastructure Meta-work growing to consume all available space Shows how optimization overhead exceeds the work itself

This sketch accompanies the blog post "The Productivity Paradox" and visualizes its core concepts through generative art.

Algorithm

Visualizing the productivity paradox Center: actual productive work (small, simple, direct) Surrounding: layers and layers of productivity infrastructure Meta-work growing to consume all available space Shows how optimization overhead exceeds the work itself This sketch was originally created as a visual companion to the blog post "The Productivity Paradox" and explores its themes through generative art.

Pseudocode

SETUP:
  Initialize canvas (400x300)
  Set up drawing parameters

DRAW (every frame):
  Get current theme colors
  Clear background
  Draw generative visualization
  Update animation state

Source Code

let sketch = function(p) {

    // Visualizing the productivity paradox
    // Center: actual productive work (small, simple, direct)
    // Surrounding: layers and layers of productivity infrastructure
    // Meta-work growing to consume all available space
    // Shows how optimization overhead exceeds the work itself

    let time = 0;
    let workCore; // The actual work (small)
    let metaLayers = []; // The productivity infrastructure (large and growing)

    class WorkCore {
        constructor() {
            this.x = 200;
            this.y = 150;
            this.size = 30;
            this.pulse = 0;
        }

        update() {
            this.pulse = (this.pulse + 0.03) % (p.TWO_PI);
        }

        display(colors) {
            // Simple, small core representing actual productive work
            p.push();
            p.translate(this.x, this.y);

            let pulseSize = this.size + p.sin(this.pulse) * 3;
            p.noStroke();
            p.fill(...colors.accent1, 200);
            p.circle(0, 0, pulseSize);

            // Label
            p.fill(...colors.bg, 200);
            p.textAlign(p.CENTER, p.CENTER);
            p.textSize(9);
            p.text("WORK", 0, 0);

            p.pop();
        }
    }

    class MetaLayer {
        constructor(radius, label, complexity) {
            this.radius = radius;
            this.label = label;
            this.complexity = complexity; // How many segments
            this.rotation = 0;
            this.rotationSpeed = 0.005 + complexity * 0.002;
            this.segments = [];

            // Create segments for this layer
            for (let i = 0; i < complexity; i++) {
                this.segments.push({
                    angle: (p.TWO_PI / complexity) * i,
                    active: false,
                    activeTimer: 0
                });
            }
        }

        update() {
            this.rotation += this.rotationSpeed;

            // Randomly activate segments (showing "work" on infrastructure)
            for (let seg of this.segments) {
                if (seg.active) {
                    seg.activeTimer--;
                    if (seg.activeTimer <= 0) {
                        seg.active = false;
                    }
                } else if (p.random() < 0.01) {
                    seg.active = true;
                    seg.activeTimer = 60;
                }
            }
        }

        display(colors) {
            p.push();
            p.translate(200, 150);
            p.rotate(this.rotation);

            // Draw the orbit ring
            p.noFill();
            p.stroke(...colors.accent3, 60);
            p.strokeWeight(1);
            p.circle(0, 0, this.radius * 2);

            // Draw segments
            for (let seg of this.segments) {
                let x = p.cos(seg.angle) * this.radius;
                let y = p.sin(seg.angle) * this.radius;

                // Segment as small box or icon
                p.push();
                p.translate(x, y);
                p.rotate(-this.rotation); // Counter-rotate so boxes stay upright

                if (seg.active) {
                    // Active segment (being worked on)
                    p.fill(...colors.accent2, 180);
                    p.stroke(...colors.accent2, 200);
                } else {
                    // Inactive segment (just overhead)
                    p.fill(...colors.accent3, 100);
                    p.stroke(...colors.accent3, 150);
                }

                p.strokeWeight(1);
                p.rect(-4, -4, 8, 8, 1);

                p.pop();
            }

            // Label for this layer
            if (time > 60) {
                let labelAlpha = Math.min((time - 60) * 2, 150);
                p.push();
                p.rotate(-this.rotation);
                p.noStroke();
                p.fill(...colors.accent3, labelAlpha);
                p.textAlign(p.CENTER, p.CENTER);
                p.textSize(6);
                p.text(this.label, 0, -this.radius - 15);
                p.pop();
            }

            p.pop();
        }
    }

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

        // The actual work (small and simple)
        workCore = new WorkCore();

        // Layers of productivity infrastructure (growing outward)
        metaLayers.push(new MetaLayer(50, "Task Manager", 8));
        metaLayers.push(new MetaLayer(75, "Time Blocking", 12));
        metaLayers.push(new MetaLayer(100, "Habit Tracker", 16));
        metaLayers.push(new MetaLayer(125, "Goal Review", 20));
    };

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

        // Title
        p.noStroke();
        p.fill(...colors.accent3, 180);
        p.textAlign(p.CENTER, p.TOP);
        p.textSize(11);
        p.text("The Productivity Paradox", 200, 15);

        // Subtitle
        if (time > 30) {
            let subtitleAlpha = Math.min((time - 30) * 2, 140);
            p.textSize(7);
            p.fill(...colors.accent3, subtitleAlpha);
            p.text("Actual work (center) vs. Productivity infrastructure (orbiting)", 200, 30);
        }

        // Draw all meta layers (productivity infrastructure)
        for (let layer of metaLayers) {
            layer.update();
            layer.display(colors);
        }

        // Draw the actual work core
        workCore.update();
        workCore.display(colors);

        // Show time spent ratio
        if (time > 120) {
            let ratioAlpha = Math.min((time - 120) * 1.5, 170);

            // Calculate "area" representation
            let workArea = Math.PI * (workCore.size/2) * (workCore.size/2);
            let metaArea = 0;
            for (let layer of metaLayers) {
                metaArea += layer.complexity * 64; // Approximate area of all segments
            }

            // Bottom annotations
            p.textAlign(p.LEFT, p.BOTTOM);
            p.textSize(8);
            p.noStroke();
            p.fill(...colors.accent1, ratioAlpha);
            p.text("Actual work: ~10%", 15, 275);

            p.fill(...colors.accent3, ratioAlpha);
            p.text("Productivity infrastructure: ~90%", 15, 290);
        }

        // Message about the paradox
        if (time > 240) {
            let msgAlpha = Math.min((time - 240) * 1.5, 160);

            p.textAlign(p.CENTER, p.BOTTOM);
            p.textSize(9);
            p.fill(...colors.accent2, msgAlpha);
            p.text("Time spent optimizing > Time spent producing", 200, 280);
        }

        // Final wisdom
        if (time > 360) {
            let wisdomAlpha = Math.min((time - 360) * 2, 150);

            p.textAlign(p.CENTER, p.BOTTOM);
            p.textSize(8);
            p.fill(...colors.accent1, wisdomAlpha);
            p.text("The simpler the system, the more you actually produce", 200, 295);
        }

        // Show growth of infrastructure over time
        if (time > 480 && time < 600) {
            // Add temporary extra layer to show bloat
            let tempAlpha = Math.sin((time - 480) / 20) * 80 + 100;
            p.push();
            p.translate(200, 150);
            p.noFill();
            p.stroke(...colors.accent3, tempAlpha);
            p.strokeWeight(2);
            p.drawingContext.setLineDash([5, 5]);
            p.circle(0, 0, 300);

            p.noStroke();
            p.fill(...colors.accent3, tempAlpha);
            p.textAlign(p.CENTER, p.TOP);
            p.textSize(7);
            p.text("(The system keeps growing...)", 0, 160);

            p.pop();
        }

        // Insight about what's actually productive
        if (time > 600 && time < 720) {
            let insightAlpha = Math.min((time - 600) * 2, 170);

            p.push();
            p.translate(200, 150);

            // Arrow pointing at work core
            p.stroke(...colors.accent1, insightAlpha);
            p.strokeWeight(2);
            p.fill(...colors.accent1, insightAlpha);

            // Arrow from top
            p.line(0, -70, 0, -40);
            // Arrowhead
            p.triangle(0, -40, -4, -48, 4, -48);

            p.noStroke();
            p.fill(...colors.accent1, insightAlpha);
            p.textAlign(p.CENTER, p.BOTTOM);
            p.textSize(9);
            p.text("This is what\nactually matters", 0, -75);

            p.pop();
        }

        time++;

        // Loop
        if (time > 900) {
            time = 0;
        }
    };
};