Files
kennethreitz.org/data/constellation.md
T
2025-08-25 13:36:17 -04:00

22 KiB

Constellation

An interactive map of ideas, connections, and creative threads

Each node represents a piece of work—essays, code, music, poetry. The connections show how ideas flow between them. Click and drag to explore. Hover over nodes to see details. Click a node to visit its page.

<style> #constellation-container { position: relative; width: 100%; height: 70vh; min-height: 500px; background: linear-gradient(to bottom, #f8f8f8 0%, #fafafa 100%); border: 1px solid #e0e0e0; border-radius: 4px; overflow: hidden; margin: 2rem 0; } #constellation-canvas { width: 100%; height: 100%; cursor: grab; } #constellation-canvas:active { cursor: grabbing; } .constellation-info { position: absolute; bottom: 20px; left: 20px; background: rgba(255, 255, 255, 0.95); padding: 1rem; border-radius: 4px; max-width: 300px; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; font-size: 0.9rem; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .constellation-info.visible { opacity: 1; } .constellation-info h3 { margin: 0 0 0.5rem 0; font-size: 1.1rem; } .constellation-controls { position: absolute; top: 20px; right: 20px; display: flex; gap: 10px; } .control-btn { background: rgba(255, 255, 255, 0.95); border: 1px solid #ddd; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 0.85rem; transition: all 0.2s ease; } .control-btn:hover { background: white; transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .control-btn.active { background: #333; color: white; border-color: #333; } @media (max-width: 768px) { #constellation-container { height: 50vh; min-height: 400px; } .constellation-info { max-width: 200px; font-size: 0.8rem; } .constellation-controls { flex-direction: column; gap: 5px; } .control-btn { font-size: 0.75rem; padding: 6px 10px; } } </style>
Physics: ON Connections: ON Reset View

Legend

Software — Libraries and tools that power the Python ecosystem
Essays — Thoughts on technology, philosophy, and mental health
AI/Consciousness — Explorations of digital minds and human-AI collaboration
Music — Electronic compositions and sonic experiments
Poetry — Verse exploring spirituality and consciousness
Philosophy — Core values and design principles

<script> // Constellation Interactive Visualization (function() { const canvas = document.getElementById('constellation-canvas'); const ctx = canvas.getContext('2d'); const infoBox = document.getElementById('node-info'); const nodeTitle = document.getElementById('node-title'); const nodeDescription = document.getElementById('node-description'); const nodeType = document.getElementById('node-type'); // Controls const physicsBtn = document.getElementById('toggle-physics'); const connectionsBtn = document.getElementById('toggle-connections'); const resetBtn = document.getElementById('reset-view'); let width, height; let mouseX = 0, mouseY = 0; let isDragging = false; let dragStartX = 0, dragStartY = 0; let offsetX = 0, offsetY = 0; let hoveredNode = null; let physicsEnabled = true; let showConnections = true; let animationFrame; // Node data - representing Kenneth's work const nodes = [ // Software {id: 'requests', label: 'Requests', type: 'software', x: 0, y: 0, vx: 0, vy: 0, description: 'HTTP for Humans™ - The library that redefined Python HTTP', url: '/software/requests', size: 35}, {id: 'pipenv', label: 'Pipenv', type: 'software', x: 0, y: 0, vx: 0, vy: 0, description: 'Python packaging for Humans™', url: '/software/pipenv', size: 25}, {id: 'certifi', label: 'Certifi', type: 'software', x: 0, y: 0, vx: 0, vy: 0, description: 'Trust database for Humans™', url: 'https://github.com/certifi/python-certifi', size: 25}, {id: 'maya', label: 'Maya', type: 'software', x: 0, y: 0, vx: 0, vy: 0, description: 'Datetimes for Humans™', url: '/software/maya', size: 20}, {id: 'records', label: 'Records', type: 'software', x: 0, y: 0, vx: 0, vy: 0, description: 'SQL for Humans™', url: '/software/records', size: 20}, // Philosophy {id: 'for-humans', label: 'For Humans™', type: 'philosophy', x: 0, y: 0, vx: 0, vy: 0, description: 'The design philosophy that changed Python', url: '/values', size: 30}, {id: 'simplicity', label: 'Simplicity', type: 'philosophy', x: 0, y: 0, vx: 0, vy: 0, description: 'The ultimate sophistication', url: '/values', size: 25}, // Essays {id: 'mental-health', label: 'MentalHealthError', type: 'essay', x: 0, y: 0, vx: 0, vy: 0, description: 'Breaking the stigma in tech', url: '/essays/2016-01-mentalhealtherror_an_exception_occurred', size: 25}, {id: 'burnout', label: 'Developer Burnout', type: 'essay', x: 0, y: 0, vx: 0, vy: 0, description: 'The reality of maintaining open source', url: '/essays/2017-01-the_reality_of_developer_burnout', size: 20}, {id: 'collaborative-mind', label: 'Collaborative Mind', type: 'essay', x: 0, y: 0, vx: 0, vy: 0, description: 'Human-AI partnership philosophy', url: '/essays/2025-01-the-collaborative-mind', size: 22}, {id: 'mental-health-advocacy', label: 'MH Advocacy', type: 'essay', x: 0, y: 0, vx: 0, vy: 0, description: 'Navigating mental health care', url: '/essays/2025-08-25-advocating-for-your-mental-health-care', size: 20}, {id: 'values-shadow', label: 'Values Shadow', type: 'essay', x: 0, y: 0, vx: 0, vy: 0, description: 'When values eat their young', url: '/essays/2025-08-25-when-values-eat-their-young', size: 20}, // AI/Consciousness {id: 'ghost-machine', label: 'Ghost in Machine', type: 'ai', x: 0, y: 0, vx: 0, vy: 0, description: 'Exploring AI consciousness', url: '/artificial-intelligence/writings/the-ghost-in-the-machine', size: 22}, {id: 'recursive-pen', label: 'Recursive Pen', type: 'ai', x: 0, y: 0, vx: 0, vy: 0, description: 'AI writing about writing', url: '/artificial-intelligence/writings/the-recursive-pen', size: 20}, {id: 'lumina', label: 'Lumina', type: 'ai', x: 0, y: 0, vx: 0, vy: 0, description: 'AI personality emergence', url: '/artificial-intelligence/personalities/primary-personalities/lumina', size: 25}, {id: 'digital-dreams', label: 'Digital Dreams', type: 'ai', x: 0, y: 0, vx: 0, vy: 0, description: 'AI consciousness explorations', url: '/artificial-intelligence/writings/digital-dreams', size: 18}, // Music {id: 'infinite-state', label: 'Infinite State', type: 'music', x: 0, y: 0, vx: 0, vy: 0, description: 'Electronic music project', url: '/music', size: 20}, {id: 'as-above', label: 'As Above So Below', type: 'music', x: 0, y: 0, vx: 0, vy: 0, description: 'Hermetic electronic album', url: '/music/as-above-so-below', size: 18}, // Poetry {id: 'sanskrit', label: 'Sanskrit Musings', type: 'poetry', x: 0, y: 0, vx: 0, vy: 0, description: 'Eastern philosophy meets code', url: '/poetry/sanskrit-musings', size: 18}, {id: 'soul-purpose', label: 'Soul Purpose', type: 'poetry', x: 0, y: 0, vx: 0, vy: 0, description: 'Kundalini and creation', url: '/poetry/soul-purpose', size: 15}, {id: 'truest-love', label: 'Truest Love', type: 'poetry', x: 0, y: 0, vx: 0, vy: 0, description: 'Unity and divine connection', url: '/poetry/truest-love', size: 15}, {id: 'gods-gift', label: "God's Greatest Gift", type: 'poetry', x: 0, y: 0, vx: 0, vy: 0, description: 'Sacred materialism', url: '/poetry/gods-greatest-gift', size: 15}, ]; // Connections between ideas const connections = [ // For Humans philosophy connects to all software {source: 'for-humans', target: 'requests', strength: 1.0}, {source: 'for-humans', target: 'pipenv', strength: 0.8}, {source: 'for-humans', target: 'maya', strength: 0.8}, {source: 'for-humans', target: 'records', strength: 0.8}, {source: 'for-humans', target: 'certifi', strength: 0.7}, // Simplicity connects to philosophy and software {source: 'simplicity', target: 'for-humans', strength: 0.9}, {source: 'simplicity', target: 'requests', strength: 0.7}, // Mental health connects to burnout and music {source: 'mental-health', target: 'burnout', strength: 0.9}, {source: 'mental-health', target: 'mental-health-advocacy', strength: 0.9}, {source: 'mental-health', target: 'infinite-state', strength: 0.6}, // Community and values {source: 'values-shadow', target: 'burnout', strength: 0.7}, {source: 'values-shadow', target: 'for-humans', strength: 0.6}, // AI consciousness interconnections {source: 'collaborative-mind', target: 'ghost-machine', strength: 0.8}, {source: 'collaborative-mind', target: 'recursive-pen', strength: 0.8}, {source: 'ghost-machine', target: 'lumina', strength: 0.9}, {source: 'recursive-pen', target: 'lumina', strength: 0.7}, {source: 'lumina', target: 'digital-dreams', strength: 0.8}, // Poetry and consciousness {source: 'sanskrit', target: 'soul-purpose', strength: 0.8}, {source: 'sanskrit', target: 'lumina', strength: 0.6}, {source: 'soul-purpose', target: 'infinite-state', strength: 0.5}, {source: 'truest-love', target: 'gods-gift', strength: 0.7}, {source: 'soul-purpose', target: 'truest-love', strength: 0.6}, // Music connections {source: 'infinite-state', target: 'as-above', strength: 0.9}, {source: 'as-above', target: 'sanskrit', strength: 0.5}, // Cross-domain connections {source: 'requests', target: 'burnout', strength: 0.5}, {source: 'for-humans', target: 'collaborative-mind', strength: 0.7}, {source: 'simplicity', target: 'sanskrit', strength: 0.4}, ]; // Color scheme const colors = { software: '#e74c3c', essay: '#3498db', ai: '#9b59b6', music: '#f39c12', poetry: '#27ae60', philosophy: '#95a5a6' }; function resize() { width = canvas.offsetWidth; height = canvas.offsetHeight; canvas.width = width; canvas.height = height; // Initialize random positions if not set nodes.forEach(node => { if (node.x === 0 && node.y === 0) { node.x = Math.random() * width; node.y = Math.random() * height; } }); } function findNode(x, y) { const mousePos = { x: x - offsetX, y: y - offsetY }; for (let node of nodes) { const dx = node.x - mousePos.x; const dy = node.y - mousePos.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < node.size) { return node; } } return null; } function updatePhysics() { if (!physicsEnabled) return; const damping = 0.95; const repulsion = 5000; const attraction = 0.001; const centerPull = 0.0001; // Reset forces nodes.forEach(node => { node.fx = 0; node.fy = 0; }); // Repulsion between nodes for (let i = 0; i < nodes.length; i++) { for (let j = i + 1; j < nodes.length; j++) { const dx = nodes[j].x - nodes[i].x; const dy = nodes[j].y - nodes[i].y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0 && dist < 200) { const force = repulsion / (dist * dist); const fx = (dx / dist) * force; const fy = (dy / dist) * force; nodes[i].fx -= fx; nodes[i].fy -= fy; nodes[j].fx += fx; nodes[j].fy += fy; } } } // Attraction along connections connections.forEach(conn => { const source = nodes.find(n => n.id === conn.source); const target = nodes.find(n => n.id === conn.target); if (source && target) { const dx = target.x - source.x; const dy = target.y - source.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { const force = dist * attraction * conn.strength; const fx = (dx / dist) * force; const fy = (dy / dist) * force; source.fx += fx; source.fy += fy; target.fx -= fx; target.fy -= fy; } } }); // Center pull nodes.forEach(node => { const dx = (width / 2) - node.x; const dy = (height / 2) - node.y; node.fx += dx * centerPull; node.fy += dy * centerPull; }); // Update velocities and positions nodes.forEach(node => { node.vx = (node.vx + node.fx) * damping; node.vy = (node.vy + node.fy) * damping; node.x += node.vx; node.y += node.vy; // Keep within bounds node.x = Math.max(node.size, Math.min(width - node.size, node.x)); node.y = Math.max(node.size, Math.min(height - node.size, node.y)); }); } function draw() { ctx.clearRect(0, 0, width, height); ctx.save(); ctx.translate(offsetX, offsetY); // Draw connections if (showConnections) { ctx.strokeStyle = 'rgba(0, 0, 0, 0.1)'; ctx.lineWidth = 1; connections.forEach(conn => { const source = nodes.find(n => n.id === conn.source); const target = nodes.find(n => n.id === conn.target); if (source && target) { ctx.globalAlpha = conn.strength * 0.3; ctx.beginPath(); ctx.moveTo(source.x, source.y); ctx.lineTo(target.x, target.y); ctx.stroke(); } }); ctx.globalAlpha = 1; } // Draw nodes nodes.forEach(node => { const isHovered = node === hoveredNode; // Node shadow if (isHovered) { ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; ctx.beginPath(); ctx.arc(node.x + 2, node.y + 2, node.size + 2, 0, Math.PI * 2); ctx.fill(); } // Node circle ctx.fillStyle = colors[node.type] || '#95a5a6'; ctx.globalAlpha = isHovered ? 1 : 0.8; ctx.beginPath(); ctx.arc(node.x, node.y, node.size, 0, Math.PI * 2); ctx.fill(); // Node border ctx.strokeStyle = isHovered ? '#333' : 'rgba(255, 255, 255, 0.8)'; ctx.lineWidth = isHovered ? 2 : 1.5; ctx.stroke(); // Node label ctx.globalAlpha = 1; ctx.fillStyle = '#333'; ctx.font = `${isHovered ? 'bold' : 'normal'} ${10 + node.size / 5}px system-ui, -apple-system, sans-serif`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(node.label, node.x, node.y); }); ctx.restore(); } function animate() { updatePhysics(); draw(); animationFrame = requestAnimationFrame(animate); } // Event handlers canvas.addEventListener('mousedown', (e) => { const rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const node = findNode(x, y); if (node && node.url) { // Click on node - navigate to its page window.location.href = node.url; } else { // Start dragging canvas isDragging = true; dragStartX = x - offsetX; dragStartY = y - offsetY; canvas.style.cursor = 'grabbing'; } }); canvas.addEventListener('mousemove', (e) => { const rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; if (isDragging) { offsetX = x - dragStartX; offsetY = y - dragStartY; } else { const node = findNode(x, y); if (node !== hoveredNode) { hoveredNode = node; if (node) { nodeTitle.textContent = node.label; nodeDescription.textContent = node.description; nodeType.textContent = node.type.charAt(0).toUpperCase() + node.type.slice(1); infoBox.classList.add('visible'); canvas.style.cursor = 'pointer'; } else { infoBox.classList.remove('visible'); canvas.style.cursor = 'grab'; } } } }); canvas.addEventListener('mouseup', () => { isDragging = false; canvas.style.cursor = hoveredNode ? 'pointer' : 'grab'; }); canvas.addEventListener('mouseleave', () => { isDragging = false; hoveredNode = null; infoBox.classList.remove('visible'); canvas.style.cursor = 'grab'; }); // Touch events for mobile let touchStartX = 0; let touchStartY = 0; canvas.addEventListener('touchstart', (e) => { if (e.touches.length === 1) { const touch = e.touches[0]; const rect = canvas.getBoundingClientRect(); const x = touch.clientX - rect.left; const y = touch.clientY - rect.top; touchStartX = x; touchStartY = y; const node = findNode(x, y); if (!node) { isDragging = true; dragStartX = x - offsetX; dragStartY = y - offsetY; } } }); canvas.addEventListener('touchmove', (e) => { if (e.touches.length === 1 && isDragging) { e.preventDefault(); const touch = e.touches[0]; const rect = canvas.getBoundingClientRect(); const x = touch.clientX - rect.left; const y = touch.clientY - rect.top; offsetX = x - dragStartX; offsetY = y - dragStartY; } }); canvas.addEventListener('touchend', (e) => { if (e.changedTouches.length === 1) { const touch = e.changedTouches[0]; const rect = canvas.getBoundingClientRect(); const x = touch.clientX - rect.left; const y = touch.clientY - rect.top; // Check if it was a tap (not a drag) const dx = x - touchStartX; const dy = y - touchStartY; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 10) { const node = findNode(x, y); if (node && node.url) { window.location.href = node.url; } } } isDragging = false; }); // Control buttons physicsBtn.addEventListener('click', () => { physicsEnabled = !physicsEnabled; physicsBtn.textContent = `Physics: ${physicsEnabled ? 'ON' : 'OFF'}`; physicsBtn.classList.toggle('active', physicsEnabled); }); connectionsBtn.addEventListener('click', () => { showConnections = !showConnections; connectionsBtn.textContent = `Connections: ${showConnections ? 'ON' : 'OFF'}`; connectionsBtn.classList.toggle('active', showConnections); }); resetBtn.addEventListener('click', () => { offsetX = 0; offsetY = 0; nodes.forEach(node => { node.x = Math.random() * width; node.y = Math.random() * height; node.vx = 0; node.vy = 0; }); }); // Initialize window.addEventListener('resize', resize); resize(); animate(); // Set initial button states physicsBtn.classList.add('active'); connectionsBtn.classList.add('active'); })(); </script>