Where ideas percolate and thoughts brew

The First Principles Fetish

About This Sketch

A visual metaphor for the cost of excessive deconstruction. Watch as one side builds confidently on accumulated knowledge while the other struggles to reconstruct from scratch—wobbling blocks representing the instability that comes from ignoring hard-won wisdom. The sketch demonstrates that real progress often comes from building on existing foundations rather than questioning everything from the ground up.

Algorithm

This sketch visualizes the contrast between building on accumulated knowledge versus attempting to rebuild everything from first principles. The animation creates two parallel construction processes. On the left, blocks representing accumulated knowledge are stacked quickly and stably—each new layer builds confidently on proven foundations. On the right, blocks representing "first principles thinking" wobble, crack, and sometimes fall as they attempt to reconstruct from scratch without the benefit of hard-won lessons. The visualization demonstrates how leveraging existing knowledge allows for faster, more stable progress, while excessive deconstruction leads to repeated mistakes and slower advancement. Each unstable block on the right shows visual cracks representing the failures that occur when ignoring accumulated wisdom. This sketch accompanies the blog post "The First Principles Fetish" which explores how tech culture's obsession with reasoning from first principles has become intellectual theater—a way to signal depth while actually slowing progress and repeating historical mistakes.

Pseudocode

SETUP:
  Create foundation blocks for both approaches
  Initialize accumulated knowledge stack (left)
  Initialize first principles stack (right)

DRAW (every frame):
  Get current theme colors
  Clear background
  Draw labels and dividing line

  FOR each accumulated knowledge block:
    Update with stable, quick placement
    Display solid, well-founded appearance
    Stack quickly on proven foundations

  FOR each first principles block:
    Update with wobbling, instability
    Randomly introduce failures and falls
    Show cracks for repeated mistakes
    Eventually stabilize after many attempts

  Periodically add new blocks:
    Accumulated side: add quickly if foundation stable
    First principles side: add slowly, only after previous stabilizes

  Display progress indicators showing height difference
  Show key insight about leveraging knowledge

Source Code

let sketch = function(p) {
    // Visualization: First Principles Fetish
    // Left side: Building on accumulated knowledge (fast, solid foundation)
    // Right side: Rebuilding from scratch (slow, unstable, repeating mistakes)

    let time = 0;
    let accumulatedBlocks = [];
    let firstPrinciplesBlocks = [];

    class Block {
        constructor(x, y, layer, isAccumulated) {
            this.x = x;
            this.y = y;
            this.layer = layer;
            this.targetY = y;
            this.age = 0;
            this.stable = false;
            this.isAccumulated = isAccumulated;
            this.wobble = isAccumulated ? 0 : p.random(-2, 2);
            this.fallSpeed = 0;
            this.failures = 0; // For first principles blocks
        }

        update() {
            this.age++;

            if (this.isAccumulated) {
                // Accumulated knowledge: stable, quick to place
                if (!this.stable && this.age > 10) {
                    this.stable = true;
                }
            } else {
                // First principles: unstable, needs repeated attempts
                if (!this.stable) {
                    this.wobble += p.random(-0.3, 0.3);
                    this.x += this.wobble;

                    // Sometimes fall and need to be replaced
                    if (p.random() < 0.02 && this.layer > 0) {
                        this.fallSpeed += 0.5;
                        this.y += this.fallSpeed;
                        this.failures++;

                        // Reset if fallen too far
                        if (this.y > this.targetY + 20) {
                            this.y = this.targetY - 30;
                            this.fallSpeed = 0;
                        }
                    }

                    if (this.age > 100 && p.random() < 0.3) {
                        this.stable = true;
                        this.wobble = 0;
                    }
                }
            }
        }

        display(colors) {
            let alpha = this.stable ? 200 : 100;

            if (this.isAccumulated) {
                // Solid, well-founded blocks
                p.fill(...colors.accent1, alpha);
                p.stroke(...colors.accent2, 150);
            } else {
                // Shaky, questioned blocks
                p.fill(...colors.accent2, alpha);
                p.stroke(...colors.accent1, 100);
            }

            p.strokeWeight(1);

            let blockWidth = 35;
            let blockHeight = 15;

            // Draw block
            p.push();
            p.translate(this.x, this.y);
            if (!this.stable && !this.isAccumulated) {
                p.rotate(this.wobble * 0.05);
            }
            p.rect(-blockWidth/2, -blockHeight/2, blockWidth, blockHeight, 2);
            p.pop();

            // Show cracks for unstable first principles blocks
            if (!this.stable && !this.isAccumulated && this.failures > 0) {
                p.stroke(...colors.accent3, 150);
                p.strokeWeight(1);
                for (let i = 0; i < this.failures; i++) {
                    let crackX = this.x + p.random(-blockWidth/3, blockWidth/3);
                    p.line(crackX, this.y - 3, crackX, this.y + 3);
                }
            }
        }
    }

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

        // Start with foundation blocks
        accumulatedBlocks.push(new Block(100, 260, 0, true));
        firstPrinciplesBlocks.push(new Block(300, 260, 0, false));
    };

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

        time++;

        // Labels
        p.fill(...colors.accent3, 220);
        p.noStroke();
        p.textAlign(p.CENTER, p.TOP);
        p.textSize(11);
        p.textFont('Georgia');
        p.text('Building on Knowledge', 100, 15);
        p.text('From First Principles', 300, 15);

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

        // Dividing line
        p.strokeWeight(1);
        p.stroke(...colors.accent3, 60);
        p.line(200, 30, 200, 270);

        // Add new blocks periodically
        if (time % 80 === 0) {
            // Accumulated side adds blocks quickly on stable foundation
            let topAccumulated = accumulatedBlocks.reduce((max, b) =>
                b.stable ? Math.min(max, b.y) : max, 270);
            if (topAccumulated > 100) {
                let newLayer = accumulatedBlocks.filter(b => b.stable).length;
                accumulatedBlocks.push(new Block(100, topAccumulated - 20, newLayer, true));
            }
        }

        if (time % 80 === 0) {
            // First principles side struggles to build
            let stableFirstPrinciples = firstPrinciplesBlocks.filter(b => b.stable);
            let topFirstPrinciples = stableFirstPrinciples.reduce((max, b) =>
                Math.min(max, b.y), 270);
            if (topFirstPrinciples > 100 && stableFirstPrinciples.length < accumulatedBlocks.filter(b => b.stable).length - 2) {
                let newLayer = stableFirstPrinciples.length;
                firstPrinciplesBlocks.push(new Block(300, topFirstPrinciples - 20, newLayer, false));
            }
        }

        // Update and display accumulated blocks
        for (let block of accumulatedBlocks) {
            block.update();
            block.display(colors);
        }

        // Update and display first principles blocks
        for (let block of firstPrinciplesBlocks) {
            block.update();
            block.display(colors);
        }

        // Progress indicators
        p.textSize(9);
        p.fill(...colors.accent3, 180);
        p.textAlign(p.CENTER);

        let accumulatedHeight = accumulatedBlocks.filter(b => b.stable).length;
        let firstPrinciplesHeight = firstPrinciplesBlocks.filter(b => b.stable).length;

        p.text(`${accumulatedHeight} layers built`, 100, 40);
        p.text(`${firstPrinciplesHeight} layers built`, 300, 40);

        // Key insight
        if (time > 200) {
            p.fill(...colors.accent2, 180);
            p.textSize(8);
            p.textAlign(p.CENTER);
            p.text('Leverage accumulated knowledge—don\'t rebuild from scratch', 200, 285);
        }
    };
};