Three.js to Canvas 2D migration: eliminated WebGL issues, enabled L-system encoding

Stripped out Three.js and replaced it with Canvas 2D. The result: no more WebGL context errors, faster hit testing, and a rendering pipeline that maps developer metrics to plant growth naturally.
Context
BloomNet’s garden visualization was built on Three.js : a 3D graphics library : despite the visualization being fundamentally two-dimensional (a top-down garden view). The 3D library was carrying significant overhead: WebGL context initialization, raycasting for mouse hit testing, and an object hierarchy optimized for 3D scenes. WebGL context tainted errors were a recurring issue that broke the visualization without warning. Raycasting on a 2D plane is geometrically equivalent to a quadtree lookup, but far more expensive. The architecture was solving a 2D problem with 3D tools.
What Changed
The migration replaced the Three.js scene graph with a native Canvas 2D rendering context. Hit testing moved from raycasting to a quadtree spatial index : the same logical operation, but purpose-built for 2D. The most significant unlock was architectural: Canvas 2D enabled L-system botanical encoding, where developer metrics map directly to plant growth properties (commit frequency drives growth rate, PR count drives branching factor). This metaphor is natural in 2D; it would have been awkward to implement on top of Three.js’s 3D scene hierarchy.
WebGL context tainted errors disappeared entirely because there is no WebGL context to taint.
Impact
Eliminated the root cause of the WebGL context errors that had been intermittently breaking the visualization. Every rendering issue traced back to the mismatch between 3D tooling and a 2D problem : removing Three.js removed the entire failure class.
Before: Three.js 3D scene with WebGL context tainted errors, raycasting hit testing, 3D overhead on a 2D view. After: Canvas 2D, quadtree spatial index, L-system botanical encoding. Zero WebGL dependency. Hit testing is faster and predictable.
The L-system encoding was only possible after the migration : it unlocked the core visual metaphor that makes BloomNet’s garden view distinctive rather than a generic graph.