Building a Browser-Based Voxel Editor with React Three Fiber
I have been building VoxelDraft , a voxel editor that runs entirely in the browser without an account or installation. The editor supports block painting, layers, keyframe animation, GIF recording, local projects, and exports for OBJ/MTL, GLB, VOX, Minecraft Schematic, and Roblox RBXL. This post covers the architecture choices that kept those features manageable. Keep edit data serializable The editable model is an array of plain voxel records rather than a collection of Three.js objects: type VoxelData = { position : [ number , number , number ] color : string layerId ?: string } That decision makes JSON backups, local persistence, undo/redo snapshots, sharing, and format conversion much simpler. Three.js objects are derived render state, not the source of truth. Render repeated cubes with InstancedMesh Creating one mesh and one React component per cube becomes expensive as a model grows. VoxelDraft uses THREE.InstancedMesh where geometry and material can be shared. Each voxel contributes a transform matrix. Pointer intersections return the instanced mesh and instance ID, which can be mapped back to the editable voxel record. There are tradeoffs. Per-voxel colors need instance colors or grouping by material, and changing a single block still requires carefully updating the instance buffers. The reduction in draw calls is worth that complexity. Make exporters independent from UI The format exporters accept voxel records and produce a Blob . The UI is only responsible for validation and triggering a download. const blob = exportToVOX ( voxels ) const url = URL . createObjectURL ( blob ) VOX, Minecraft Schematic, and RBXL are generated directly. For GLB, the app builds a temporary Three.js scene and sends it to GLTFExporter from three-stdlib . Keeping binary generation separate from React event handlers makes exporters easier to test and reuse. Move GIF encoding off the main thread VoxelDraft records both animation output and modeling timelapses. GIF encoding can easi