Pascal Editor — 3D Building Editor with R3F
Pascal Editor is an open-source 3D building editor built with React Three Fiber and WebGPU — create, edit, and share architectural projects.
Most architectural design tools are either expensive proprietary software (Revit, ArchiCAD) or limited web tools. Pascal Editor is neither — it’s an open-source 3D building editor built with modern web technologies, specifically React Three Fiber and WebGPU, designed for creating and sharing architectural projects in the browser.
What is Pascal Editor?#
Pascal Editor is a 3D building editor developed by PascalOrg. It’s a Turborepo monorepo with a sophisticated architecture that separates concerns across five packages:
@pascal-app/core— Node schemas, scene state (Zustand), registry contracts, spatial queries, and event bus@pascal-app/viewer— 3D rendering via React Three Fiber, shared render systems, camera/controls, and post-processing@pascal-app/editor— Editing tools, panels, selection, and direct-manipulation UI@pascal-app/nodes— Built-in registry plugin with node definitions, renderers, geometry, and systems@pascal-app/ui— Shared UI components
The editor runs as a Next.js 16 application with React 19, using WebGPU for rendering and Bun as the package manager.
Core Architecture#
Node-Based Scene Graph#
Everything in Pascal Editor is a node. All nodes extend a base type:
BaseNode {
id: string // Auto-generated with type prefix
type: string // Discriminator for type-safe handling
parentId: string | null
visible: boolean
camera?: Camera // Optional saved camera position
metadata?: JSON // Arbitrary metadata
}typescriptNodes form a hierarchy:
Site
└── Building
└── Level
├── Wall → Item (doors, windows)
├── Slab
├── Ceiling → Item (lights)
├── Roof
├── Zone
├── Scan (3D reference)
└── Guide (2D reference)textThe smart part: nodes are stored in a flat dictionary (Record<id, Node>), not a nested tree. Parent-child relationships are maintained via parentId and children arrays, making lookups fast and state management straightforward.
State Management with Zustand#
Each package has its own Zustand store:
| Store | Package | Responsibility |
|---|---|---|
useScene | @pascal-app/core | Scene data: nodes, CRUD, undo/redo (50-step history via Zundo), persisted to IndexedDB |
useViewer | @pascal-app/viewer | Viewer state: selection, level display modes |
useEditor | apps/editor | Editor state: active tool, panel states, preferences |
Dirty Node System#
When a node changes, it’s marked as dirty. Systems check the dirty set each frame and only recompute geometry for affected nodes. This is how Pascal Editor achieves real-time performance in the browser:
// Automatic: createNode, updateNode, deleteNode mark nodes dirty
useScene.getState().updateNode(wallId, { thickness: 0.2 })
// → wallId added to dirtyNodes
// → WallSystem regenerates geometry next frametypescriptSystems Architecture#
Systems are React components running in the render loop (useFrame) that update geometry and transforms:
| System | Responsibility |
|---|---|
| WallSystem | Generates wall geometry with mitering and CSG cutouts for doors/windows |
| SlabSystem | Generates floor geometry from polygons |
| CeilingSystem | Generates ceiling geometry |
| RoofSystem | Generates roof geometry |
| ItemSystem | Positions items on walls, ceilings, or floors |
| LevelSystem | Handles level visibility and positioning (stacked/exploded/solo) |
Scene Registry#
The registry maps node IDs to their Three.js objects for fast lookup — no scene graph traversal needed:
sceneRegistry = {
nodes: Map<id, Object3D>,
byType: { wall: Set<id>, item: Set<id>, zone: Set<id>, ... }
}typescriptSpatial Grid Manager#
Handles collision detection and placement validation — used by item placement tools to validate positions and calculate slab elevations.
Event Bus#
A typed event emitter (mitt) handles inter-component communication for node interactions, grid clicks, and context menus.
Editing Tools#
The editor provides a toolbar with specialized tools:
- SelectTool — Selection and manipulation with hierarchical navigation (Site → Building → Level → Zone → Items)
- WallTool — Draw walls with mitering and cutouts
- ZoneTool — Create functional zones
- ItemTool — Place furniture, fixtures, doors, windows
- SlabTool — Create floor slabs
Plugin System#
Pascal Editor is extensible via plugins. A plugin ships node kinds (schema, 3D/2D rendering, placement tools, inspector parametrics) and left-rail panels through the same manifest as built-ins.
There’s even a worked example: pascalorg/plugin-trees ↗ — a standalone plugin with procedural trees, flowers, grass, and a presets panel.
Technology Stack#
| Layer | Technology |
|---|---|
| Framework | React 19 + Next.js 16 |
| 3D Rendering | Three.js (WebGPU renderer) + React Three Fiber + Drei |
| State | Zustand + Zundo (undo/redo) + IndexedDB persistence |
| Validation | Zod |
| Geometry | three-bvh-csg (Boolean operations) |
| Monorepo | Turborepo |
| Package Manager | Bun |
Getting Started#
# Clone and install
git clone https://github.com/pascalorg/editor
cd editor
bun install
# Start development server (hot reload for all packages)
bun dev
# Opens http://localhost:3002bashFor production:
turbo buildbashUsing Published Packages#
You can use Pascal Editor’s components in your own projects:
npm install @pascal-app/core @pascal-app/viewer @pascal-app/editor @pascal-app/nodesbashimport { loadPlugin } from '@pascal-app/core'
import { builtinPlugin } from '@pascal-app/nodes'
await loadPlugin(builtinPlugin)typescriptWhy Pascal Editor Matters#
Most open-source 3D editors are either game engines (Godot, Three.js playgrounds) or generic CAD tools. Pascal Editor is purpose-built for architectural design — with wall mitering, slab generation, level management, and door/window cutouts built in.
Its WebGPU renderer means it can handle complex building models in the browser with real-time performance. And its plugin architecture means it can grow from a building editor into a full architectural design platform.
For developers, it’s also a masterclass in React Three Fiber architecture — showing how to structure stores, systems, renderers, and plugins in a real-world 3D application.