DEV Community

Daniel Amah
Daniel Amah

Posted on • Originally published at spaces.forge3d.ai

I built a browser CAD where you type a sentence and walk through the house

Concept design for a building is slow and expensive. A homeowner planning an extension, or a contractor trying to win a job, is stuck between two bad options: pay a drafter $500–2,000 for a concept package, or fight SketchUp's learning curve for a week. Meanwhile the actual idea — "a 4-bed duplex with a garage and a palm out front" — fits in one sentence.

So I built Forge3D Spaces: you type that sentence, and a few seconds later you're walking through a furnished 3D house in your browser — with measured floor plans, DXF for AutoCAD, and a cost estimate that come out of the same model. No install. Here's how it works under the hood.

The pipeline: sentence → structured plan → building

The naive approach — "ask an LLM to emit a 3D scene" — falls apart fast. Models are bad at spatial consistency; walls don't meet, rooms overlap, doors float. So the LLM never touches geometry directly. It emits a structured program, and a deterministic solver turns that into a watertight building.

  1. The prompt becomes a spec. A strict JSON-schema call (OpenRouter, json_schema response format with every field required) turns "4-bed duplex with a garage" into a room program: room types, target areas, adjacencies, storeys.
  2. A slicing-tree solver lays it out. This is the old floorplanning trick from chip design — recursively split a rectangle with horizontal/vertical cuts until every room has its area. A squarify pass keeps rooms from collapsing into corridors. The output is exact rectangles with real dimensions, guaranteed non-overlapping and gap-free.
  3. Walls, openings, roof, furniture get generated from the solved plan. Every door and window is placed by rule, not by vibes.

Because the plan is a real data structure, the 2D floor plan, the 3D model, the elevations, and the bill of quantities are all views of the same thing. Drag a wall and they all move together. Nothing drifts out of sync, because there's nothing to sync — it's one model.

The rendering: WebGPU, and the fallback you actually need

The viewport is React Three Fiber on a WebGPURenderer. WebGPU is genuinely on ~75% of browsers now, but "available" and "survives a real session" are different numbers. The failure modes that bit me:

  • requestAdapter() succeeds, then renderer.init() throws on specific driver/OS combos.
  • In-app browsers (Instagram/Facebook WebViews) report capabilities they don't have.
  • Mobile Safari drops the GPU device on tab-suspend, mid-session.

So the renderer caches its init promise per-canvas and cleanly falls back to WebGL when init rejects, and there's an empty-draw guard around device loss. Assume the happy path will fail and it mostly won't.

The hard part: cutting holes in walls

A wall with a door in it isn't a box minus a box you can precompute. Openings move, resize, and change type while the user edits, and the cut has to stay clean for both the 3D mesh and the exported drawings. This is CSG (constructive solid geometry), and doing it naively per-frame will melt a laptop.

The thing that made it viable was three-mesh-bvh + three-bvh-csg: build a bounding-volume hierarchy over the geometry so boolean ops are fast, and — crucially — cache the brush geometry per node so you only re-evaluate what actually changed. The perf cliff between "demo scene with three walls" and "real project with forty" was brutal until that caching went in.

The AI editor: edits as one undo

Generating the house is step one; the real product is editing it. There's a chat panel where you say "move the sofa off the front door" or "add a gable roof" or "plant two palms out front," and it happens.

Same trick as generation: the model doesn't move meshes, it emits operations against a scene summary (node ids + positions the client sends up). add_item, move_node, add_wall, add_roof, add_tree, delete_node. The client validates each op against the real catalog and scene graph, then applies the whole batch as one Zustand store transaction — so a five-op edit is a single Ctrl+Z. Unknown ids are skipped and reported, never thrown, so a partially-valid plan still lands cleanly.

Whole-building requests ("design me a duplex") are detected and handed back to the parametric generator instead of hand-built op-by-op — the solver does that job far better than 40 LLM operations ever could.

Stack, briefly

  • Next.js 16 (Turbopack) frontend, deployed on Heroku
  • React Three Fiber + WebGPU viewport, WebGL fallback
  • A vendored, MIT-licensed 3D editor core for the scene graph + node schemas (Zod-validated)
  • A headless slicing-tree solver + drawing/BoQ generators on the backend
  • OpenRouter for the structured LLM calls, metered per message

Try it

It's live and free to start: spaces.forge3d.ai. Type a building, walk through it, cut the roof off, drag in furniture, export the DXF.

I'm a solo founder and this week I'm giving away 30 free design concepts — drop your project (beds, rough size, style) in the comments and I'll generate it and post the walkthrough back. Brutally honest feedback is the most useful thing you can give me.

What would you build first?

Top comments (0)