Webstructor
A browser-based kitbashing tool for assembling 3D scenes from a library of
parts and exporting the result as a single .glb file. No install, no
account, no cloud round-trip — open the page, build, export.
The longer-term goal is to make procedural widgets — parameterised, generative geometries — first-class citizens of the kit. The current primitive and GLB libraries are scaffolding for that bigger idea.
Why I’m building it
Most 3D tools optimise for either modelling from scratch (Blender, Maya) or viewing finished assets (Sketchfab, model viewers). The middle ground — fast, gestural assembly of pre-made parts into a new whole — is where a lot of real creative work happens, and it’s underserved on the web.
Webstructor is my answer to that gap:
- Compose, don’t model. Drag parts in, transform them, group them, ship a GLB.
- Live in the browser. Three.js does the heavy lifting; everything else is plain TypeScript.
- Stay open at the seams. Every library entry — primitive, GLB asset, or
future procedural widget — implements the same
ElementDefinitioninterface. One factory, infinite content types.
What’s in it today
A working v0.3.0 editor with:
- Library of 8 geometric primitives + GLB-backed assets, all served from a data-driven registry.
- Selection (single / multi), translate-rotate-scale gizmo with snapping, centroid-pivot multi-select transforms.
- Undo / redo across add, delete, duplicate, group, and transform operations.
- Image-based lighting via PMREM-prefiltered room environment.
- Named camera views (perspective + 6 axis views), animated transitions, FOV presets, frame-selection.
- Session save / restore + autosave with toast feedback.
- One-click GLB export of the entire composed scene.
How it’s wired
src/
├── library/ — registry + primitives + GLB-backed assets
├── scene/ — renderer, camera, IBL, named views
├── editing/ — selection, transform, picking, history, commands
├── export/ — GLTFExporter wrapper
└── ui/ — sidebar + right rail
Two design decisions carry the project:
- Element registry. Every entry is
{ id, label, category, create }. Thecreate()factory returns an arbitraryObject3D(sync or async). Primitives, GLBs, and future procedural widgets all plug into the same one-line interface — no parallel systems. - Helpers vs. content. Everything user-created lives under
viewport.root; that’s what the exporter sees. Grid, axes, and selection outlines live underviewport.helpersand are never exported. The split keeps “what you see” and “what you ship” cleanly separated.
What’s next
The roadmap is openly tracked in the repo. The headline items unlocking the procedural direction:
- Parameter schema on
ElementDefinition— let factories take a typed bag of values (numbers, ints, bools, colors, enums) instead of zero args. - Inspector panel — TRS values and live parameter sliders for the active selection. Editing procedural widgets has to be immediate.
- First procedural widget — one real, useful generator (panel, hull frame, bolted plate) to validate the pipeline end-to-end.
After that, the editor essentials queue up: outliner, JSON scene save/load, drag-and-drop GLB import, material overrides, pivot controls.
Links
- Repo & releases: github.com/sebastjan-rijavec/webstructor
- Current version: v0.3.0 — see CHANGELOG