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;
}
};
};