Where ideas percolate and thoughts brew

Do One Thing

About This Sketch

A visual meditation on ruthless prioritization. Watch as dozens of competing tasks fade away, leaving only the one thing that mattersโ€”growing larger, clearer, and more vibrant as distractions disappear into the background.

Algorithm

This sketch visualizes the core argument of "Do One Thing": that true productivity comes from ruthless focus on a single priority while ignoring everything else. The animation shows two distinct phases. First, dozens of tasks compete for attention, creating visual chaos and cognitive overhead. Then, focus narrows to just one task, which grows larger and clearer while all distractions fade away and disappear. The primary task pulses with energy and remains centered, while competing priorities are shown as smaller, dimmer circles that eventually vanish. Connections between distraction tasks represent the mental overhead of trying to manage multiple priorities simultaneously.

Pseudocode

SETUP:
  Create one primary task at center (larger, brighter)
  Create 35 distraction tasks in orbit around it
  Set initial phase to "managing everything"

DRAW (looping animation):
  Phase 0 - Managing Everything (0-3 seconds):
    All tasks jostle and compete for attention
    Show connections between nearby distractions
    Display chaos of multiple priorities
    Label: "Managing everything: constant distraction"

  Phase 1 - Focus (3-7 seconds):
    Primary task grows larger (reaching 80px)
    Primary task pulses with energy
    All distraction tasks fade out (alpha decreases)
    Remove dead tasks from scene
    Label: "Ignore everything else: pure focus"

  Phase 2 - Reset:
    Return to initial state
    Recreate all tasks
    Loop the cycle

INTERACTION:
  Tasks move towards target positions smoothly
  Distraction tasks fade at constant rate
  Primary task grows and pulses continuously
  Visual metaphor for letting go of distractions

Source Code

let sketch = function(p) {
    let tasks = [];
    let focusTask = null;
    let time = 0;
    let phase = 0; // 0: many tasks, 1: focusing on one

    class Task {
        constructor(x, y, isPrimary) {
            this.x = x;
            this.y = y;
            this.targetX = x;
            this.targetY = y;
            this.isPrimary = isPrimary;
            this.size = isPrimary ? 30 : 12;
            this.alpha = isPrimary ? 255 : 150;
            this.fadeSpeed = 3;
            this.dead = false;
        }

        update() {
            // Move towards target
            this.x += (this.targetX - this.x) * 0.05;
            this.y += (this.targetY - this.y) * 0.05;

            // Fade out non-primary tasks in phase 1
            if (phase === 1 && !this.isPrimary) {
                this.alpha -= this.fadeSpeed;
                if (this.alpha <= 0) {
                    this.alpha = 0;
                    this.dead = true;
                }
            }

            // Grow primary task in phase 1
            if (phase === 1 && this.isPrimary && this.size < 80) {
                this.size += 0.8;
            }
        }

        display(colors) {
            if (this.isPrimary) {
                // Primary task - bold and clear
                p.noStroke();
                p.fill(...colors.accent2, this.alpha);
                p.circle(this.x, this.y, this.size);

                // Pulsing glow
                let pulseSize = this.size + p.sin(time * 0.05) * 8;
                p.fill(...colors.accent2, this.alpha * 0.2);
                p.circle(this.x, this.y, pulseSize);

                // Inner highlight
                p.fill(...colors.bg, this.alpha * 0.3);
                p.circle(this.x, this.y, this.size * 0.4);
            } else {
                // Distraction tasks - fading away
                p.noStroke();
                p.fill(...colors.accent3, this.alpha * 0.6);
                p.circle(this.x, this.y, this.size);
            }
        }
    }

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

        // Create the primary task at center
        focusTask = new Task(200, 150, true);
        tasks.push(focusTask);

        // Create many distraction tasks scattered around
        for (let i = 0; i < 35; i++) {
            let angle = (i / 35) * p.TWO_PI;
            let radius = p.random(80, 140);
            let x = 200 + p.cos(angle) * radius;
            let y = 150 + p.sin(angle) * radius;
            tasks.push(new Task(x, y, false));
        }
    };

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

        time++;

        // Phase 0: All tasks competing for attention (first 180 frames)
        if (time < 180) {
            phase = 0;
            // Tasks orbit and jostle
            for (let task of tasks) {
                if (!task.isPrimary) {
                    task.targetX = task.x + p.random(-2, 2);
                    task.targetY = task.y + p.random(-2, 2);
                }
            }
        }
        // Phase 1: Focus on one, let others fade (180-420 frames)
        else if (time < 420) {
            if (phase === 0) {
                // Just entered phase 1 - set targets
                phase = 1;
                focusTask.targetX = 200;
                focusTask.targetY = 150;
            }
        }
        // Reset cycle
        else if (time > 480) {
            time = 0;
            phase = 0;
            tasks = [];

            focusTask = new Task(200, 150, true);
            tasks.push(focusTask);

            for (let i = 0; i < 35; i++) {
                let angle = (i / 35) * p.TWO_PI;
                let radius = p.random(80, 140);
                let x = 200 + p.cos(angle) * radius;
                let y = 150 + p.sin(angle) * radius;
                tasks.push(new Task(x, y, false));
            }
        }

        // Update and display all tasks
        for (let task of tasks) {
            task.update();
            task.display(colors);
        }

        // Remove dead tasks
        tasks = tasks.filter(t => !t.dead);

        // Draw connections between nearby distraction tasks in phase 0
        if (phase === 0) {
            p.stroke(...colors.accent3, 30);
            p.strokeWeight(1);
            for (let i = 0; i < tasks.length; i++) {
                for (let j = i + 1; j < tasks.length; j++) {
                    let d = p.dist(tasks[i].x, tasks[i].y, tasks[j].x, tasks[j].y);
                    if (d < 60 && !tasks[i].isPrimary && !tasks[j].isPrimary) {
                        p.line(tasks[i].x, tasks[i].y, tasks[j].x, tasks[j].y);
                    }
                }
            }
        }

        // Labels
        p.noStroke();
        p.fill(...colors.accent3, 180);
        p.textAlign(p.CENTER);
        p.textSize(11);

        if (phase === 0) {
            p.text('Managing everything: constant distraction', 200, 280);
            p.textSize(9);
            let nonPrimaryCount = tasks.filter(t => !t.isPrimary).length;
            p.text(`(${nonPrimaryCount} competing priorities)`, 200, 20);
        } else {
            p.text('Ignore everything else: pure focus', 200, 280);
            p.textSize(9);
            let remaining = tasks.filter(t => !t.isPrimary && t.alpha > 0).length;
            if (remaining > 0) {
                p.text(`(${remaining} distractions fading...)`, 200, 20);
            } else {
                p.text('(one thing)', 200, 20);
            }
        }

        // Task count
        p.textAlign(p.RIGHT);
        p.textSize(10);
        p.fill(...colors.accent2, 150);
        p.text(`Active: ${tasks.length}`, 390, 290);
    };
};