{"repo":"pascalorg/editor","free":true,"listed":false,"github":"https://github.com/pascalorg/editor","clone":"git clone https://github.com/pascalorg/editor.git","description":"Create and share 3D architectural projects.","language":"TypeScript","stars":21426,"topics":["3d","architecture","bim","cad","editor","floorplan","mcp","nextjs","parametric-design","react-three-fiber","threejs","typescript"],"license":"MIT","category":"bim_cad_editor","readme_excerpt":"# Pascal Editor\n\nA 3D building editor built with React Three Fiber and WebGPU.\n\n[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![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)\n[![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)\n[![npm @pascal-app/cli](https://img.shields.io/npm/v/@pascal-app/cli?label=%40pascal-app%2Fcli)](https://www.npmjs.com/package/@pascal-app/cli)\n[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/XRKsDcpqgS)\n[![X (Twitter)](https://img.shields.io/badge/follow-%40pascal__app-black?logo=x&logoColor=white)](https://x.com/pascal_app)\n\nhttps://github.com/user-attachments/assets/8b50e7cf-cebe-4579-9cf3-8786b35f7b6b\n\n## Run the Editor Locally\n\nNode.js 22.13 or newer can create a persistent local Pascal installation without\ncloning this repository:\n\n```bash\nnpx @pascal-app/cli editor\n```\n\nThe CLI starts the editor and an authenticated MCP service in the background, selects\ncollision-free loopback ports, and keeps projects in `~/.pascal/data/pascal.db`. Configure\nan agent to launch `pascal mcp connect`. See [Run Pascal locally](https://editor.pascal.app/docs/developers/local-editor)\nfor pnpm/Bun commands, project management, MCP setup, updates, storage paths, and\ntroubleshooting.\n\n## Using Published Packages\n\nThe viewer runtime and built-in node definitions are separate packages. Install the full built-in\nviewer set, then load the built-in plugin once before mounting `<Viewer>`:\n\n```bash\nnpm install @pascal-app/core @pascal-app/viewer @pascal-app/editor @pascal-app/nodes\n```\n\n```typescript\nimport { loadPlugin } from '@pascal-app/core'\nimport { builtinPlugin } from '@pascal-app/nodes'\n\nawait loadPlugin(builtinPlugin)\n```\n\nSee the [`@pascal-app/viewer` quick start](packages/viewer/README.md#usage) for a React example.\n\n\n## Repository Architecture\n\nThis is a Turborepo monorepo with the reusable editor packages, the standalone app,\nand the CLI that distributes it:\n\n```\neditor/\n├── apps/\n│   └── editor/          # Next.js application\n├── packages/\n│   ├── core/            # Schemas, scene state, and registry contracts\n│   ├── viewer/          # 3D rendering runtime and shared systems\n│   ├── editor/          # Editing tools and UI components\n│   ├── nodes/           # Built-in node definitions, renderers, and systems\n│   ├── cli/             # Persistent local editor installer and process manager\n│   ├── mcp/             # Model Context Protocol server and scene storage\n│   └── ui/              # Shared UI components\n```\n\n### Separation of Concerns\n\n| Package | Responsibility |\n|---------|---------------|\n| **@pascal-app/core** | Node schemas, scene state (Zustand), registry contracts, spatial queries, and event bus |\n| **@pascal-app/viewer** | 3D rendering via React Three Fiber, shared render systems, default camera/controls, and post-processing |\n| **@pascal-app/editor** | Editing tools, panels, selection, and direct-manipulation UI |\n| **@pascal-app/nodes** | Built-in registry plugin with node definitions, renderers, geometry, and systems |\n| **@pascal-app/cli** | Installs and manages a versioned standalone editor runtime and persistent local data |\n| **@pascal-app/mcp** | Exposes scene tools, resources, prompts, and local storage to MCP-compatible AI hosts |\n| **apps/editor** | Standalone Next.js host for the editor packages |\n\nThe **viewer** renders the scene with sensible defaults. The **editor** extends it with interactive tools, selection management, and editing capabilities.\n\n### Stores\n\nEach package has its own Zustand store for managing state:\n\n| Store | Package | Responsibility |\n|-------|---------|----------------|\n| `useScene` | `@pascal-app/core` | Scene data: nodes, root IDs, dirty nodes, CRUD operations. Persisted to IndexedDB with undo/redo via Zundo. |\n| `useViewer` | `@pascal-app/viewer` | Viewer state: current selection (building/level/zone IDs), level display mode (stacked/exploded/solo), camera mode. |\n| `useEditor` | `apps/editor` | Editor state: active tool, structure layer visibility, panel states, editor-specific preferences. |\n\n**Access patterns:**\n\n```typescript\n// Subscribe to state changes (React component)\nconst nodes = useScene((state) => state.nodes)\nconst levelId = useViewer((state) => state.selection.levelId)\nconst activeTool = useEditor((state) => state.tool)\n\n// Access state outside React (callbacks, systems)\nconst node = useScene.getState().nodes[id]\nuseViewer.getState().setSelection({ levelId: 'level_123' })\n```\n\n---\n\n## Core Concepts\n\n### Nodes\n\nNodes are the data primitives that describe the 3D scene. All nodes extend `BaseNode`:\n\n```typescript\nBaseNode {\n  id: string              // Auto-generated with type prefix (e.g., \"wall_abc123\")\n  type: string            // Discriminator for type-safe handling\n  parentId: string | null // Parent node reference\n  visible: boolean\n  camera?: Camera         // Optional saved camera position\n  metadata?: JSON         // Arbitrary metadata (e.g., { isTransient: true })\n}\n```\n\n**Node Hierarchy:**\n\n```\nSite\n└── Building\n    └── Level\n        ├── Wall → Item (doors, windows)\n        ├── Slab\n        ├── Ceiling → Item (lights)\n        ├── Roof\n        ├── Zone\n        ├── Scan (3D reference)\n        └── Guide (2D reference)\n```\n\nNodes are stored in a **flat dictionary** (`Record<id, Node>`), not a nested tree. Parent-child relationships are defined via `parentId` and `children` arrays.\n\n---\n\n### Scene State (Zustand Store)\n\nThe scene is managed by a Zustand store in `@pascal-app/core`:\n\n```typescript\nuseScene.getState() = {\n  nodes: Record<id, AnyNode>,  // All nodes\n  rootNodeIds: string[],       // Top-level nodes (sites)\n  dirtyNodes: Set<string>,     // Nodes pending system updates\n\n  createNode(node, parentId),\n  updateNode(id, updates),\n  deleteNode(id),\n}\n```\n\n**Middleware:**\n- **Persist** - Saves to IndexedDB (excludes transient nodes)\n- **Temporal** (Zundo) - Undo/redo with 50-step history\n\n---\n\n### Scene Registry\n\nThe registry maps node IDs to their Three.js objects for fast lookup:\n\n```typescript\nsceneRegistry = {\n  nodes: Map<id, Object3D>,    // ID → 3D object\n  byType: {\n    wall: Set<id>,\n    item: Set<id>,\n    zone: Set<id>,\n    // ...\n  }\n}\n```\n\nRenderers register their refs using the `useRegistry` hook:\n\n```tsx\nconst ref = useRef<Mesh>(null!)\nuseRegistry(node.id, 'wall', ref)\n```\n\nThis allows systems to access 3D objects directly without traversing the scene graph.\n\n---\n\n### Node Renderers\n\nRenderers are React components that create Three.js objects for each node type:\n\n```\nSceneRenderer\n└── NodeRenderer (dispatches by type)\n    ├── BuildingRenderer\n    ├── LevelRenderer\n    ├── WallRenderer\n    ├── SlabRenderer\n    ├── ZoneRenderer\n    ├── ItemRenderer\n    └── ...\n```\n\n**Pattern:**\n1. Renderer creates a placeholder mesh/group\n2. Registers it with `useRegistry`\n3. Systems update geometry based on node data\n\nExample (simplified):\n```tsx\nconst WallRenderer = ({ node }) => {\n  const ref = useRef<Mesh>(null!)\n  useRegistry(node.id, 'wall', ref)\n\n  return (\n    <mesh ref={ref}>\n      <boxGeometry args={[0, 0, 0]} />  {/* Replaced by WallSystem */}\n      <meshStandardMaterial />\n      {node.children.map(id => <NodeRenderer key={id} nodeId={id} />)}\n    </mesh>\n  )\n}\n```\n\n---\n\n### Systems\n\nSystems are React components that run in the render loop (`useFrame`) to update geometry and transforms. They process **dirty nodes** marked by the store.\n\n**Core Systems (in `@pascal-app/core`):**\n\n| System | Responsibility |\n|--------|---------------|\n| `WallSystem` | Generates wall geometry with mitering and CSG cutouts for doors/windows |\n| `SlabSystem` | Generates floor geometry from polygons |\n| `CeilingSystem` | Generates ceiling geometry |\n| `RoofSystem` | Generates roof geometry |\n| `ItemSystem` | Positions items on walls, ceilings, or floors (slab elevation) |\n\n**Viewer Systems (in `@pascal-app/viewer`):**\n\n| System | Responsibility |\n|--------|---------------|\n| `LevelSystem` | Handles level visibility and vertical positioning (stacked/exploded/solo modes) |\n| `ScanSystem` | Controls 3D scan visibility |\n| `GuideSystem` | Controls guide image visibility |\n\n**Processing Pattern:**\n```typescript\nuseFrame(() => {\n  for (const id of dirtyNodes) {\n    const obj = sceneRegistry.nodes.get(id)\n    const node = useScene.getState().nodes[id]\n\n    // Update geometry, transforms, etc.\n    updateGeometry(obj, node)\n\n    dirtyNodes.delete(id)\n  }\n})\n```\n\n---\n\n### Dirty Nodes\n\nWhen 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.\n\n```typescript\n// Automatic: createNode, updateNode, deleteNode mark nodes dirty\nuseScene.getState().updateNode(wallId, { thickness: 0.2 })\n// → wallId added to dirtyNodes\n// → WallSystem regenerates geometry next frame\n// → wallId removed from dirtyNodes\n```\n\n**Manual marking:**\n```typescript\nuseScene.getState().dirtyNodes.add(wallId)\n```\n\n---\n\n### Event Bus\n\nInter-component communication uses a typed event emitter (mitt):\n\n```typescript\n// Node events\nemitter.on('wall:click', (event) => { ... })\nemitter.on('item:enter', (event) => { ... })\nemitter.on('zone:context-menu', (event) => { ... })\n\n// Grid events (background)\nemitter.on('grid:click', (event) => { ... })\n\n// Event payload\nNodeEvent {\n  node: AnyNode\n  position: [x, y, z]\n  localPosition: [x, y, z]\n  normal?: [x, y, z]\n  stopPropagation: () => void\n}\n```\n\n---\n\n### Spatial Grid Manager\n\nHandles collision detection and placement validation:\n\n```typescript\nspatialGridManager.canPlaceOnFloor(levelId, position, dimensions, rotation)\nspatialGridManager.canPlaceOnWall(wallId, t, height, dimensions)\nspatialGridManager.getSlabElevationAt(levelId, x, z)\n``","default_branch":"main","files":2547,"tree":[".agents/skills/open-pr/SKILL.md",".agents/skills/review-architecture/SKILL.md",".claude/settings.json",".claude/skills",".codex/skills",".cursor/skills",".devcontainer/devcontainer-lock.json",".devcontainer/devcontainer.json",".dockerignore",".env.defaults",".env.example",".github/FUNDING.yml",".github/ISSUE_TEMPLATE/bug_report.yml",".github/ISSUE_TEMPLATE/config.yml",".github/ISSUE_TEMPLATE/feature_request.yml",".github/copilot-instructions.md",".github/pull_request_template.md",".github/workflows/ci.yml",".github/workflows/mcp-ci.yml",".github/workflows/release.yml",".gitignore",".npmrc",".vscode/settings.json","AGENTS.md","CHANGELOG.md","CLAUDE.md","CODE_OF_CONDUCT.md","CONTRIBUTING.md","Dockerfile","GEMINI.md","LICENSE","README.md","SECURITY.md","SETUP.md","apps/editor/.gitignore","apps/editor/AGENTS.md","apps/editor/CLAUDE.md","apps/editor/README.md","apps/editor/app/api/health/route.ts","apps/editor/app/api/plugins/mint/[...path]/route.ts","apps/editor/app/api/scenes/[id]/events/route.ts","apps/editor/app/api/scenes/[id]/route.ts","apps/editor/app/api/scenes/route.ts","apps/editor/app/client-bootstrap.tsx","apps/editor/app/favicon.ico","apps/editor/app/fonts/GeistMonoVF.woff","apps/editor/app/fonts/GeistVF.woff","apps/editor/app/globals.css","apps/editor/app/layout.tsx","apps/editor/app/page.tsx","apps/editor/app/privacy/page.tsx","apps/editor/app/scene/[id]/page.tsx","apps/editor/app/scenes/page.tsx","apps/editor/app/terms/page.tsx","apps/editor/components/build-tab.tsx","apps/editor/components/save-button.tsx","apps/editor/components/scene-loader.tsx","apps/editor/components/toolbar-tooltip.tsx","apps/editor/components/viewer-toolbar.tsx","apps/editor/env.mjs","apps/editor/lib/bootstrap.ts","apps/editor/lib/graph-schema.test.ts","apps/editor/lib/graph-schema.ts","apps/editor/lib/scene-api-security.test.ts","apps/editor/lib/scene-api-security.ts","apps/editor/lib/scene-signature.test.ts","apps/editor/lib/scene-signature.ts","apps/editor/lib/scene-store-server.test.ts","apps/editor/lib/scene-store-server.ts","apps/editor/lib/utils.ts","apps/editor/next.config.ts","apps/editor/package.json","apps/editor/postcss.config.mjs","apps/editor/public/audios/radios/classic/Ballroom in Miniature.mp3","apps/editor/public/audios/radios/classic/Blueprints in Springtime.mp3","apps/editor/public/audios/radios/classic/Clockwork Tea Party (Alternate).mp3","apps/editor/public/audios/radios/classic/Clockwork Tea Party.mp3","apps/editor/public/audios/radios/classic/Clockwork Teacups.mp3","apps/editor/public/audios/radios/classic/Evening in the Parlor.mp3","apps/editor/public/audios/radios/classic/Glass Atrium.mp3","apps/editor/public/audios/radios/classic/Moonlight On The Drafting Table.mp3","apps/editor/public/audios/radios/classic/Sunlit Garden Reverie.mp3","apps/editor/public/audios/radios/classic/Sunlit Waltz in Pastel Hues.mp3","apps/editor/public/audios/sfx/grid_snap.mamd","apps/editor/public/audios/sfx/grid_snap.mp3","apps/editor/public/audios/sfx/grid_snap_0.mp3","apps/editor/public/audios/sfx/grid_snap_1.mp3","apps/editor/public/audios/sfx/grid_snap_2.mp3","apps/editor/public/audios/sfx/item_delete.mp3","apps/editor/public/audios/sfx/item_pick.mp3","apps/editor/public/audios/sfx/item_place.mp3","apps/editor/public/audios/sfx/item_rotate.mp3","apps/editor/public/audios/sfx/menu_click.mp3","apps/editor/public/audios/sfx/menu_hover.mp3","apps/editor/public/audios/sfx/paint_apply.mp3","apps/editor/public/audios/sfx/resize_0.mp3","apps/editor/public/audios/sfx/resize_1.mp3","apps/editor/public/audios/sfx/resize_2.mp3","apps/editor/public/audios/sfx/snapshot_capture.mp3","apps/editor/public/audios/sfx/structure_build.mp3","apps/editor/public/audios/sfx/structure_build_end.mp3","apps/editor/public/audios/sfx/structure_build_start.mp3","apps/editor/public/audios/sfx/structure_delete.mp3","apps/editor/public/audios/sfx/terrain_flatten.mp3","apps/editor/public/audios/sfx/terrain_lower.mp3","apps/editor/public/audios/sfx/terrain_raise.mp3","apps/editor/public/audios/sfx/terrain_smooth.mp3","apps/editor/public/cursor.svg","apps/editor/public/demos/demo_1.json","apps/editor/public/file-text.svg","apps/editor/public/fonts/PlusJakartaSans-SemiBold.ttf","apps/editor/public/fonts/geist-regular.ttf","apps/editor/public/globe.svg","apps/editor/public/hdri/venice_sunset_1k.hdr","apps/editor/public/icons/HVAC.webp","apps/editor/public/icons/appliance.webp","apps/editor/public/icons/bathroom.webp","apps/editor/public/icons/blueprint.webp","apps/editor/public/icons/build.webp","apps/editor/public/icons/building.webp","apps/editor/public/icons/ceiling.webp","apps/editor/public/icons/collection.webp","apps/editor/public/icons/column.webp","apps/editor/public/icons/column1.webp","apps/editor/public/icons/couch.webp","apps/editor/public/icons/cube.webp","apps/editor/public/icons/custom-room.webp","apps/editor/public/icons/door.webp","apps/editor/public/icons/duct-fitting.webp","apps/editor/public/icons/duct.webp","apps/editor/public/icons/dwv-pipes.webp","apps/editor/public/icons/elevator.webp","apps/editor/public/icons/environment.webp","apps/editor/public/icons/fence.webp","apps/editor/public/icons/floor.webp","apps/editor/public/icons/floorplan.webp","apps/editor/public/icons/item.webp","apps/editor/public/icons/kitchen.webp","apps/editor/public/icons/level.webp","apps/editor/public/icons/lineset.webp","apps/editor/public/icons/mesh.webp","apps/editor/public/icons/orbit.webp","apps/editor/public/icons/paint.webp","apps/editor/public/icons/pan.webp","apps/editor/public/icons/registers.webp","apps/editor/public/icons/roof.webp","apps/editor/public/icons/room.webp","apps/editor/public/icons/rotate.webp","apps/editor/public/icons/scene.webp","apps/editor/public/icons/select.webp","apps/editor/public/icons/settings.webp","apps/editor/public/icons/shelf.webp","apps/editor/public/icons/site-flag.webp","apps/editor/public/icons/site.webp","apps/editor/public/icons/spawn-point.svg","apps/editor/public/icons/spawn-point.webp","apps/editor/public/icons/stairs.webp","apps/editor/public/icons/structural-grid.webp","apps/editor/public/icons/terrain-flatten.webp","apps/editor/public/icons/terrain-lower.webp","apps/editor/public/icons/terrain-raise.webp","apps/editor/public/icons/terrain-smooth.webp","apps/editor/public/icons/topview.webp","apps/editor/public/icons/tree.webp","apps/editor/public/icons/wall.webp","apps/editor/public/icons/wallcut.webp","apps/editor/public/icons/walllow.webp","apps/editor/public/icons/window.webp","apps/editor/public/icons/zone.webp","apps/editor/public/items/ac-block/model.glb","apps/editor/public/items/ac-block/thumbnail.webp","apps/editor/public/items/air-conditioner-block/model.glb","apps/editor/public/items/air-conditioner-block/thumbnail.webp","apps/editor/public/items/air-conditioner/model.glb","apps/editor/public/items/air-conditioner/thumbnail.webp","apps/editor/public/items/air-conditioning/model.glb","apps/editor/public/items/air-conditioning/thumbnail.webp","apps/editor/public/items/alarm-keypad/model.glb","apps/editor/public/items/alarm-keypad/thumbnail.webp","apps/editor/public/items/ball/model.glb","apps/editor/public/items/ball/thumbnail.webp","apps/editor/public/items/barbell-stand/model.glb","apps/editor/public/items/barbell-stand/thumbnail.webp","apps/editor/public/items/barbell/model.glb","apps/editor/public/items/barbell/thumbnail.webp","apps/editor/public/items/basket-hoop/model.glb","apps/editor/public/items/basket-hoop/thumbnail.webp","apps/editor/public/items/bathroom-sink/model.glb","apps/editor/public/items/bathroom-sink/thumbnail.webp","apps/editor/public/items/bathtub/model.glb","apps/editor/public/items/bathtub/thumbnail.webp","apps/editor/public/items/bean-bag/model.glb","apps/editor/public/items/bean-bag/thumbnail.webp","apps/editor/public/items/bedside-table/model.glb","apps/editor/public/items/bedside-table/thumbnail.webp","apps/editor/public/items/books/model.glb","apps/editor/public/items/books/thumbnail.webp","apps/editor/public/items/bookshelf/model.glb","apps/editor/public/items/bookshelf/thumbnail.webp","apps/editor/public/items/bunkbed/model.glb","apps/editor/public/items/bunkbed/thumbnail.webp","apps/editor/public/items/bush/model.glb","apps/editor/public/items/bush/thumbnail.webp","apps/editor/public/items/cactus/model.glb","apps/editor/public/items/cactus/thumbnail.webp","apps/editor/public/items/car-toy/model.glb","apps/editor/public/items/car-toy/thumbnail.webp","apps/editor/public/items/ceiling-fan/model.glb","apps/editor/public/items/ceiling-fan/thumbnail.webp","apps/editor/public/items/ceiling-lamp/model.glb","apps/editor/public/items/ceiling-lamp/thumbnail.webp","apps/editor/public/items/ceiling-light/model.glb","apps/editor/public/items/ceiling-light/thumbnail.webp","apps/editor/public/items/circular-ceiling-light/model.glb","apps/editor/public/items/circular-ceiling-light/thumbnail.webp","apps/editor/public/items/closet/model.glb","apps/editor/public/items/closet/thumbnail.webp","apps/editor/public/items/coat-rack/model.glb","apps/editor/public/items/coat-rack/thumbnail.webp","apps/editor/public/items/coffee-machine/model.glb","apps/editor/public/items/coffee-machine/thumbnail.webp","apps/editor/public/items/coffee-table/model.glb","apps/editor/public/items/coffee-table/thumbnail.webp","apps/editor/public/items/column/model.glb","apps/editor/public/items/column/thumbnail.webp","apps/editor/public/items/computer/model.glb","apps/editor/public/items/computer/thumbnail.webp","apps/editor/public/items/couch-medium/model.glb","apps/editor/public/items/couch-medium/thumbnail.webp","apps/editor/public/items/couch-small/model.glb","apps/editor/public/items/couch-small/thumbnail.webp","apps/editor/public/items/cutting-board/model.glb","apps/editor/public/items/cutting-board/thumbnail.webp","apps/editor/public/items/desk/model.glb","apps/editor/public/items/desk/thumbnail.webp","apps/editor/public/items/dining-chair/model.glb","apps/editor/public/items/dining-chair/thumbnail.webp","apps/editor/public/items/dining-table/model.glb","apps/editor/public/items/dining-table/thumbnail.webp","apps/editor/public/items/door-bar/model.glb","apps/editor/public/items/door-bar/thumbnail.webp","apps/editor/public/items/door-with-bar/model.glb","apps/editor/public/items/door-with-bar/thumbnail.webp","apps/editor/public/items/door/model.glb","apps/editor/public/items/door/thumbnail.webp","apps/editor/public/items/doorway-front/model.glb","apps/editor/public/items/doorway-front/thumbnail.webp","apps/editor/public/items/double-bed/model.glb","apps/editor/public/items/double-bed/thumbnail.webp","apps/editor/public/items/dresser/model.glb","apps/editor/public/items/dresser/thumbnail.webp","apps/editor/public/items/drying-rack/model.glb","apps/editor/public/items/drying-rack/thumbnail.webp","apps/editor/public/items/easel/model.glb","apps/editor/public/items/easel/thumbnail.webp","apps/editor/public/items/electric-panel/model.glb","apps/editor/public/items/electric-panel/thumbnail.webp","apps/editor/public/items/ev-wall-charger/model.glb","apps/editor/public/items/ev-wall-charger/thumbnail.webp","apps/editor/public/items/exercise-bike/model.glb","apps/editor/public/items/exercise-bike/thumbnail.webp","apps/editor/public/items/exit-sign/model.glb","apps/editor/public/items/exit-sign/thumbnail.webp","apps/editor/public/items/fence/model.glb","apps/editor/public/items/fence/thumbnail.webp","apps/editor/public/items/fir-tree/model.glb","apps/editor/public/items/fir-tree/thumbnail.webp","apps/editor/public/items/fire-alarm/model.glb","apps/editor/public/items/fire-alarm/thumbnail.webp","apps/editor/public/items/fire-detector/model.glb","apps/editor/public/items/fire-detector/thumbnail.webp","apps/editor/public/items/fire-extinguisher/model.glb","apps/editor/public/items/fire-extinguisher/thumbnail.webp","apps/editor/public/items/flat-screen-tv/model.glb","apps/editor/public/items/flat-screen-tv/thumbnail.webp","apps/editor/public/items/floor-lamp/model.glb","apps/editor/public/items/floor-lamp/thumbnail.webp","apps/editor/public/items/freezer/model.glb","apps/editor/public/items/freezer/thumbnail.webp","apps/editor/public/items/fridge/model.glb","apps/editor/public/items/fridge/thumbnail.webp","apps/editor/public/items/fruits/model.glb","apps/editor/public/items/fruits/thumbnail.webp","apps/editor/public/items/frying-pan/model.glb","apps/editor/public/items/frying-pan/thumbnail.webp","apps/editor/public/items/glass-door/model.glb","apps/editor/public/items/glass-door/thumbnail.webp","apps/editor/public/items/guitar/model.glb","apps/editor/public/items/guitar/thumbnail.webp","apps/editor/public/items/hedge/model.glb","apps/editor/public/items/hedge/thumbnail.webp","apps/editor/public/items/high-fence/model.glb","apps/editor/public/items/high-fence/thumbnail.webp","apps/editor/public/items/hood/model.glb","apps/editor/public/items/hood/thumbnail.webp","apps/editor/public/items/hydrant/model.glb","apps/editor/public/items/hydrant/thumbnail.webp","apps/editor/public/items/indoor-plant/model.glb","apps/editor/public/items/indoor-plant/thumbnail.webp","apps/editor/public/items/iron/model.glb","apps/editor/public/items/iron/thumbnail.webp","apps/editor/public/items/ironing-board/model.glb","apps/editor/public/items/ironing-board/thumbnail.webp","apps/editor/public/items/kettle/model.glb","apps/editor/public/items/kettle/thumbnail.webp","apps/editor/public/items/kitchen-cabinet/model.glb","apps/editor/public/items/kitchen-cabinet/thumbnail.webp","apps/editor/public/items/kitchen-counter/model.glb","apps/editor/public/items/kitchen-counter/thumbnail.webp","apps/editor/public/items/kitchen-fridge/model.glb","apps/editor/public/items/kitchen-fridge/thumbnail.webp","apps/editor/public/items/kitchen-shelf/model.glb","apps/editor/public/items/kitchen-shelf/thumbnail.webp","apps/editor/public/items/kitchen-utensils/model.glb","apps/editor/public/items/kitchen-utensils/thumbnail.webp","apps/editor/public/items/kitchen/model.glb","apps/editor/public/items/kitchen/thumbnail.webp","apps/editor/public/items/laundry-bag/model.glb","apps/editor/public/items/laundry-bag/thumbnail.webp","apps/editor/public/items/livingroom-chair/model.glb","apps/editor/public/items/livingroom-chair/thumbnail.webp","apps/editor/public/items/lounge-chair/model.glb","apps/editor/public/items/lounge-chair/thumbnail.webp","apps/editor/public/items/low-fence/model.glb","apps/editor/public/items/low-fence/thumbnail.webp","apps/editor/public/items/medium-fence/model.glb","apps/editor/public/items/medium-fence/thumbnail.webp","apps/editor/public/items/microwave/model.glb","apps/editor/public/items/microwave/thumbnail.webp","apps/editor/public/items/office-chair/floor-plan.svg","apps/editor/public/items/office-chair/model.glb","apps/editor/public/items/office-chair/thumbnail.webp","apps/editor/public/items/office-table/model.glb","apps/editor/public/items/office-table/thumbnail.webp","apps/editor/public/items/outdoor-playhouse/model.glb","apps/editor/public/items/outdoor-playhouse/thumbnail.webp","apps/editor/public/items/palm/model.glb","apps/editor/public/items/palm/thumbnail.webp","apps/editor/public/items/parking-spot/model.glb","apps/editor/public/items/parking-spot/thumbnail.webp","apps/editor/public/items/patio-umbrella/model.glb","apps/editor/public/items/patio-umbrella/thumbnail.webp","apps/editor/public/items/piano/Fireplace_13.glb","apps/editor/public/items/piano/model.glb","apps/editor/public/items/piano/thumbnail.webp","apps/editor/public/items/picture/model.glb","apps/editor/public/items/picture/thumbnail.webp","apps/editor/public/items/pillar/model.glb","apps/editor/public/items/pillar/thumbnail.webp","apps/editor/public/items/pool-table/model.glb","apps/editor/public/items/pool-table/thumbnail.webp","apps/editor/public/items/recessed-light/model.glb","apps/editor/public/items/recessed-light/thumbnail.webp","apps/editor/public/items/rectangular-carpet/model.glb","apps/editor/public/items/rectangular-carpet/thumbnail.webp","apps/editor/public/items/rectangular-ceiling-light/Screenshot 2026-01-23 at 12.15.00.png","apps/editor/public/items/rectangular-ceiling-light/model.glb","apps/editor/public/items/rectangular-ceiling-light/thumbnail.webp","apps/editor/public/items/rectangular-mirror/model.glb","apps/editor/public/items/rectangular-mirror/thumbnail.webp","apps/editor/public/items/round-carpet/model.glb","apps/editor/public/items/round-carpet/thumbnail.webp","apps/editor/public/items/round-mirror/model.glb","apps/editor/public/items/round-mirror/thumbnail.webp","apps/editor/public/items/scooter/model.glb","apps/editor/public/items/scooter/thumbnail.webp","apps/editor/public/items/sewing-machine/model.glb","apps/editor/public/items/sewing-machine/thumbnail.webp","apps/editor/public/items/shelf/model.glb","apps/editor/public/items/shelf/thumbnail.webp","apps/editor/public/items/shower-angle/model.glb","apps/editor/public/items/shower-angle/thumbnail.webp","apps/editor/public/items/shower-rug/model.glb","apps/editor/public/items/shower-rug/thumbnail.webp","apps/editor/public/items/shower-square/model.glb","apps/editor/public/items/shower-square/thumbnail.webp","apps/editor/public/items/shower/model.glb","apps/editor/public/items/single-bed/model.glb","apps/editor/public/items/single-bed/thumbnail.webp","apps/editor/public/items/sink-cabinet/model.glb","apps/editor/public/items/sink-cabinet/thumbnail.webp","apps/editor/public/items/skate/model.glb","apps/editor/public/items/skate/thumbnail.webp","apps/editor/public/items/small-indoor-plant/model.glb","apps/editor/public/items/small-indoor-plant/thumbnail.webp","apps/editor/public/items/small-kitchen-cabinet/model.glb","apps/editor/public/items/small-kitchen-cabinet/thumbnail.webp","apps/editor/public/items/smoke-detector/model.glb","apps/editor/public/items/smoke-detector/thumbnail.webp","apps/editor/public/items/sofa/floor-plan.svg","apps/editor/public/items/sofa/model.glb","apps/editor/public/items/sofa/thumbnail.webp","apps/editor/public/items/sprinkler/model.glb","apps/editor/public/items/sprinkler/thumbnail.webp","apps/editor/public/items/stairs/model.glb","apps/editor/public/items/stairs/thumbnail.webp","apps/editor/public/items/stereo-speaker/model.glb","apps/editor/public/items/stereo-speaker/thumbnail.webp","apps/editor/public/items/stool/model.glb","apps/editor/public/items/stool/thumbnail.webp"],"storefront":"/r/pascalorg","claimed":false,"request_supported":{"post":"https://gitbuyer.com/r/pascalorg/editor/request-supported","requests":0},"note":"indexed from public GitHub; nothing is for sale on this page. Clone it from GitHub. Paid listings live at /search."}