Where ideas percolate and thoughts brew

The Productivity Guilt Machine

About This Sketch

Tasks fall like rain. A few get completed. Most pile up at the bottom. The pile grows. New tasks keep coming. You adopt a new system—brief relief, a small surge of completion—then back to the endless accumulation. This is the productivity guilt machine: mathematically designed to keep you feeling behind, no matter how much you do.

This sketch accompanies the blog post "The Productivity Guilt Machine" and visualizes its central claim: the productivity industry profits from your perpetual inadequacy by creating systems where completion is structurally impossible.

Algorithm

This sketch visualizes the never-ending cycle of productivity guilt. Tasks continuously spawn and fall like rain, representing the constant influx of things to do. Only about 15% are marked as "completed" (shown in lighter tones), while the rest accumulate in a growing pile at the bottom. The visualization demonstrates the core thesis of the accompanying post: the productivity system is designed to make you feel perpetually behind. Tasks appear faster than they can be completed, creating a mathematical impossibility that generates constant guilt. Occasionally, there's a brief surge of completion (representing the adoption of a new productivity system), but it's quickly overwhelmed by new tasks. The pile grows inexorably, and the bottom text alternates between two messages: "The pile grows faster than you can clear it" and "You were never meant to finish."

Pseudocode

SETUP:
  Initialize canvas (400x300)
  Create empty arrays for active tasks, completed tasks, and incomplete tasks

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

  EVERY 15 FRAMES:
    Spawn new task with random position, speed, size
    15% chance of being "completable"

  FOR each active task:
    Move task downward with drift
    Display task with anxiety color (red for incomplete, gold for complete)

    IF task reaches bottom:
      Move to completed or incomplete pile
      Remove from active tasks

  DRAW incomplete pile:
    Visualize accumulated incomplete tasks as growing pile
    Show stats: completed vs incomplete count

  EVERY 400 FRAMES:
    Simulate "new productivity system" adoption
    Brief surge: complete 5 tasks from pile
    (Quickly overwhelmed by new tasks)

  Display alternating message:
    "The pile grows faster than you can clear it"
    "You were never meant to finish"

Source Code

let sketch = function(p) {
    // Visualization: The Productivity Guilt Machine
    // Shows tasks constantly spawning and falling like rain
    // A few get "completed" but most just pile up at the bottom
    // The pile grows while new tasks keep falling - never-ending inadequacy

    let tasks = [];
    let completedTasks = [];
    let incompleteTasks = [];
    let time = 0;

    class Task {
        constructor() {
            this.x = p.random(50, 350);
            this.y = -10;
            this.speed = p.random(0.5, 1.5);
            this.size = p.random(4, 8);
            this.completed = p.random() < 0.15; // Only 15% get "done"
            this.anxiety = p.random(100, 255);
        }

        update() {
            this.y += this.speed;

            // Add some drift
            this.x += p.sin(this.y * 0.05) * 0.5;

            // Has it reached the bottom?
            if (this.y > 260) {
                return false; // Remove from active tasks
            }
            return true;
        }

        display(colors) {
            if (this.completed) {
                // Brief moment of relief - completed task
                p.fill(...colors.accent1, this.anxiety * 0.6);
            } else {
                // Growing anxiety as task falls
                p.fill(...colors.accent2, this.anxiety);
            }
            p.noStroke();
            p.circle(this.x, this.y, this.size);

            // Guilt trail
            if (!this.completed) {
                p.stroke(...colors.accent2, this.anxiety * 0.3);
                p.strokeWeight(1);
                p.line(this.x, this.y, this.x, this.y - 10);
            }
        }
    }

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

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

        time++;

        // Title
        p.fill(...colors.accent3, 220);
        p.noStroke();
        p.textAlign(p.LEFT, p.TOP);
        p.textSize(12);
        p.textFont('Georgia');
        p.text('The Productivity Guilt Machine', 15, 15);

        // Spawn new tasks constantly
        if (p.frameCount % 15 === 0) {
            tasks.push(new Task());
        }

        // Update and display active tasks
        for (let i = tasks.length - 1; i >= 0; i--) {
            if (!tasks[i].update()) {
                // Task reached bottom - goes to appropriate pile
                if (tasks[i].completed) {
                    completedTasks.push(tasks[i]);
                    // Completed tasks fade quickly
                    if (completedTasks.length > 15) {
                        completedTasks.shift();
                    }
                } else {
                    incompleteTasks.push(tasks[i]);
                    // Incomplete tasks pile up forever
                    if (incompleteTasks.length > 150) {
                        incompleteTasks.shift(); // Eventually have to clear some
                    }
                }
                tasks.splice(i, 1);
            } else {
                tasks[i].display(colors);
            }
        }

        // Draw the pile at the bottom - the weight of undone tasks
        let pileHeight = Math.min(incompleteTasks.length * 0.3, 40);

        // Guilt pile visualization
        for (let i = 0; i < incompleteTasks.length; i++) {
            let pileX = 50 + (i % 70) * 4;
            let pileY = 270 - (Math.floor(i / 70) * 2);
            p.fill(...colors.accent2, 180);
            p.noStroke();
            p.circle(pileX, pileY, 3);
        }

        // Ground line
        p.stroke(...colors.accent3, 100);
        p.strokeWeight(2);
        p.line(0, 270, 400, 270);

        // Stats showing the impossible ratio
        p.textAlign(p.LEFT);
        p.textSize(9);
        p.fill(...colors.accent3, 200);

        let totalCreated = incompleteTasks.length + completedTasks.length + tasks.length;
        let completionRate = totalCreated > 0 ?
            Math.floor((completedTasks.length / totalCreated) * 100) : 0;

        p.text(`Tasks completed: ${completedTasks.length}`, 15, 245);
        p.text(`Tasks incomplete: ${incompleteTasks.length}`, 15, 260);

        // The core message
        p.textAlign(p.CENTER);
        p.textSize(9);
        if (time % 300 < 150) {
            p.fill(...colors.accent2, 180);
            p.text('The pile grows faster than you can clear it', 200, 285);
        } else {
            p.fill(...colors.accent3, 180);
            p.text('You were never meant to finish', 200, 285);
        }

        // Add occasional "system change" event - briefly speeds completion
        if (time % 400 === 0) {
            // New productivity system adopted! Brief surge of completion
            for (let i = 0; i < 5; i++) {
                if (incompleteTasks.length > 0) {
                    incompleteTasks.shift();
                    completedTasks.push({completed: true});
                }
            }
        }
    };
};