Skip to main content
ClaudeWave

Create and share 3D architectural projects.

MCP Servers21.1k estrellas2.7k forksTypeScriptMITActualizado today
Install in Claude Code / Claude Desktop
Method: Manual
Claude Code CLI
git clone https://github.com/pascalorg/editor
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "editor": {
      "command": "node",
      "args": ["/path/to/editor/dist/index.js"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Clone https://github.com/pascalorg/editor and follow its README for install instructions.
Casos de uso

Resumen de MCP Servers

# Pascal Editor

A 3D building editor built with React Three Fiber and WebGPU.

[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![npm @pascal-app/core](https://img.shields.io/npm/v/@pascal-app/core?label=%40pascal-app%2Fcore)](https://www.npmjs.com/package/@pascal-app/core)
[![npm @pascal-app/viewer](https://img.shields.io/npm/v/@pascal-app/viewer?label=%40pascal-app%2Fviewer)](https://www.npmjs.com/package/@pascal-app/viewer)
[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/XRKsDcpqgS)
[![X (Twitter)](https://img.shields.io/badge/follow-%40pascal__app-black?logo=x&logoColor=white)](https://x.com/pascal_app)

https://github.com/user-attachments/assets/8b50e7cf-cebe-4579-9cf3-8786b35f7b6b

## Using Published Packages

The viewer runtime and built-in node definitions are separate packages. Install the full built-in
viewer set, then load the built-in plugin once before mounting `<Viewer>`:

```bash
npm install @pascal-app/core @pascal-app/viewer @pascal-app/editor @pascal-app/nodes
```

```typescript
import { loadPlugin } from '@pascal-app/core'
import { builtinPlugin } from '@pascal-app/nodes'

await loadPlugin(builtinPlugin)
```

See the [`@pascal-app/viewer` quick start](packages/viewer/README.md#usage) for a React example.


## Repository Architecture

This is a Turborepo monorepo with four main runtime packages:

```
editor/
├── apps/
│   └── editor/          # Next.js application
├── packages/
│   ├── core/            # Schemas, scene state, and registry contracts
│   ├── viewer/          # 3D rendering runtime and shared systems
│   ├── editor/          # Editing tools and UI components
│   ├── nodes/           # Built-in node definitions, renderers, and systems
│   └── ui/              # Shared UI components
```

### Separation of Concerns

| Package | Responsibility |
|---------|---------------|
| **@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, default 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 |
| **apps/editor** | Standalone Next.js host for the editor packages |

The **viewer** renders the scene with sensible defaults. The **editor** extends it with interactive tools, selection management, and editing capabilities.

### Stores

Each package has its own Zustand store for managing state:

| Store | Package | Responsibility |
|-------|---------|----------------|
| `useScene` | `@pascal-app/core` | Scene data: nodes, root IDs, dirty nodes, CRUD operations. Persisted to IndexedDB with undo/redo via Zundo. |
| `useViewer` | `@pascal-app/viewer` | Viewer state: current selection (building/level/zone IDs), level display mode (stacked/exploded/solo), camera mode. |
| `useEditor` | `apps/editor` | Editor state: active tool, structure layer visibility, panel states, editor-specific preferences. |

**Access patterns:**

```typescript
// Subscribe to state changes (React component)
const nodes = useScene((state) => state.nodes)
const levelId = useViewer((state) => state.selection.levelId)
const activeTool = useEditor((state) => state.tool)

// Access state outside React (callbacks, systems)
const node = useScene.getState().nodes[id]
useViewer.getState().setSelection({ levelId: 'level_123' })
```

---

## Core Concepts

### Nodes

Nodes are the data primitives that describe the 3D scene. All nodes extend `BaseNode`:

```typescript
BaseNode {
  id: string              // Auto-generated with type prefix (e.g., "wall_abc123")
  type: string            // Discriminator for type-safe handling
  parentId: string | null // Parent node reference
  visible: boolean
  camera?: Camera         // Optional saved camera position
  metadata?: JSON         // Arbitrary metadata (e.g., { isTransient: true })
}
```

**Node Hierarchy:**

```
Site
└── Building
    └── Level
        ├── Wall → Item (doors, windows)
        ├── Slab
        ├── Ceiling → Item (lights)
        ├── Roof
        ├── Zone
        ├── Scan (3D reference)
        └── Guide (2D reference)
```

Nodes are stored in a **flat dictionary** (`Record<id, Node>`), not a nested tree. Parent-child relationships are defined via `parentId` and `children` arrays.

---

### Scene State (Zustand Store)

The scene is managed by a Zustand store in `@pascal-app/core`:

```typescript
useScene.getState() = {
  nodes: Record<id, AnyNode>,  // All nodes
  rootNodeIds: string[],       // Top-level nodes (sites)
  dirtyNodes: Set<string>,     // Nodes pending system updates

  createNode(node, parentId),
  updateNode(id, updates),
  deleteNode(id),
}
```

**Middleware:**
- **Persist** - Saves to IndexedDB (excludes transient nodes)
- **Temporal** (Zundo) - Undo/redo with 50-step history

---

### Scene Registry

The registry maps node IDs to their Three.js objects for fast lookup:

```typescript
sceneRegistry = {
  nodes: Map<id, Object3D>,    // ID → 3D object
  byType: {
    wall: Set<id>,
    item: Set<id>,
    zone: Set<id>,
    // ...
  }
}
```

Renderers register their refs using the `useRegistry` hook:

```tsx
const ref = useRef<Mesh>(null!)
useRegistry(node.id, 'wall', ref)
```

This allows systems to access 3D objects directly without traversing the scene graph.

---

### Node Renderers

Renderers are React components that create Three.js objects for each node type:

```
SceneRenderer
└── NodeRenderer (dispatches by type)
    ├── BuildingRenderer
    ├── LevelRenderer
    ├── WallRenderer
    ├── SlabRenderer
    ├── ZoneRenderer
    ├── ItemRenderer
    └── ...
```

**Pattern:**
1. Renderer creates a placeholder mesh/group
2. Registers it with `useRegistry`
3. Systems update geometry based on node data

Example (simplified):
```tsx
const WallRenderer = ({ node }) => {
  const ref = useRef<Mesh>(null!)
  useRegistry(node.id, 'wall', ref)

  return (
    <mesh ref={ref}>
      <boxGeometry args={[0, 0, 0]} />  {/* Replaced by WallSystem */}
      <meshStandardMaterial />
      {node.children.map(id => <NodeRenderer key={id} nodeId={id} />)}
    </mesh>
  )
}
```

---

### Systems

Systems are React components that run in the render loop (`useFrame`) to update geometry and transforms. They process **dirty nodes** marked by the store.

**Core Systems (in `@pascal-app/core`):**

| 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 (slab elevation) |

**Viewer Systems (in `@pascal-app/viewer`):**

| System | Responsibility |
|--------|---------------|
| `LevelSystem` | Handles level visibility and vertical positioning (stacked/exploded/solo modes) |
| `ScanSystem` | Controls 3D scan visibility |
| `GuideSystem` | Controls guide image visibility |

**Processing Pattern:**
```typescript
useFrame(() => {
  for (const id of dirtyNodes) {
    const obj = sceneRegistry.nodes.get(id)
    const node = useScene.getState().nodes[id]

    // Update geometry, transforms, etc.
    updateGeometry(obj, node)

    dirtyNodes.delete(id)
  }
})
```

---

### Dirty Nodes

When a node changes, it's marked as **dirty** in `useScene.getState().dirtyNodes`. Systems check this set each frame and only recompute geometry for dirty nodes.

```typescript
// Automatic: createNode, updateNode, deleteNode mark nodes dirty
useScene.getState().updateNode(wallId, { thickness: 0.2 })
// → wallId added to dirtyNodes
// → WallSystem regenerates geometry next frame
// → wallId removed from dirtyNodes
```

**Manual marking:**
```typescript
useScene.getState().dirtyNodes.add(wallId)
```

---

### Event Bus

Inter-component communication uses a typed event emitter (mitt):

```typescript
// Node events
emitter.on('wall:click', (event) => { ... })
emitter.on('item:enter', (event) => { ... })
emitter.on('zone:context-menu', (event) => { ... })

// Grid events (background)
emitter.on('grid:click', (event) => { ... })

// Event payload
NodeEvent {
  node: AnyNode
  position: [x, y, z]
  localPosition: [x, y, z]
  normal?: [x, y, z]
  stopPropagation: () => void
}
```

---

### Spatial Grid Manager

Handles collision detection and placement validation:

```typescript
spatialGridManager.canPlaceOnFloor(levelId, position, dimensions, rotation)
spatialGridManager.canPlaceOnWall(wallId, t, height, dimensions)
spatialGridManager.getSlabElevationAt(levelId, x, z)
```

Used by item placement tools to validate positions and calculate slab elevations.

---

## Editor Architecture

The editor extends the viewer with:

### Tools

Tools are activated via the toolbar and handle user input for specific operations:

- **SelectTool** - Selection and manipulation
- **WallTool** - Draw walls
- **ZoneTool** - Create zones
- **ItemTool** - Place furniture/fixtures
- **SlabTool** - Create floor slabs

### Selection Manager

The editor uses a custom selection manager with hierarchical navigation:

```
Site → Building → Level → Zone → Items
```

Each depth level has its own selection strategy for hover/click behavior.

### Editor-Specific Systems

- `ZoneSystem` - Controls zone visibility based on level mode
- Custom camera controls with node focusing

---

## Data Flow

```
User Action (click, drag)
       ↓
Tool Handler
       ↓
useScene.createNode() / updateNode()
       ↓
Node added/updated in store
Node marked dirty
       ↓
React re-renders NodeRenderer
useRegistry() registers 3D object
       ↓
System detects dirty node (useFrame)
Updates geometry via sceneRegistry
Clears dirty flag
```

---

## Building
3darchitecturebimcadeditorfloorplanmcpnextjsparametric-designreact-three-fiberthreejstypescript

Lo que la gente pregunta sobre editor

¿Qué es pascalorg/editor?

+

pascalorg/editor es mcp servers para el ecosistema de Claude AI. Create and share 3D architectural projects. Tiene 21.1k estrellas en GitHub y se actualizó por última vez today.

¿Cómo se instala editor?

+

Puedes instalar editor clonando el repositorio (https://github.com/pascalorg/editor) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.

¿Es seguro usar pascalorg/editor?

+

pascalorg/editor aún no ha sido auditado por nuestro agente de seguridad. Revisa el repositorio original en GitHub antes de usarlo en producción.

¿Quién mantiene pascalorg/editor?

+

pascalorg/editor es mantenido por pascalorg. La última actividad registrada en GitHub es de today, con 22 issues abiertos.

¿Hay alternativas a editor?

+

Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.

Despliega editor en tu cloud

Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.

¿Mantienes este repo? Añade un badge a tu README

Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.

Featured on ClaudeWave: pascalorg/editor
[![Featured on ClaudeWave](https://claudewave.com/api/badge/pascalorg-editor)](https://claudewave.com/repo/pascalorg-editor)
<a href="https://claudewave.com/repo/pascalorg-editor"><img src="https://claudewave.com/api/badge/pascalorg-editor" alt="Featured on ClaudeWave: pascalorg/editor" width="320" height="64" /></a>

Más MCP Servers

Alternativas a editor