Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b993f5e
Fix Dashboard App integration and rename from KPI Dashboard
Mar 17, 2026
328c0ec
Use relative path for dashboard-app widget action
Mar 17, 2026
4d3dd1d
Fix multiple memory leaks causing resource exhaustion when loading mo…
claude Mar 17, 2026
adbc506
Add documentation for memory leak fixes
claude Mar 17, 2026
7b05740
Fix asset paths for GitHub Pages subpath deployment
Mar 17, 2026
2222c9d
Fix GitHub Pages routing for lowercase repo name
Mar 20, 2026
21c0aa3
Fix SPA 404 redirect for GitHub Pages subpath
Mar 20, 2026
c720465
Fix Dashboard App iframe URL resolution for GitHub Pages
Mar 20, 2026
61f3c45
Use BrowserRouter basename for GitHub Pages subpath
Mar 20, 2026
b380c6f
Revert basename approach, restore installPrefix for GitHub Pages
Mar 20, 2026
bee25f7
Revert GitHub Pages workarounds for Netlify deployment
Mar 20, 2026
682c84a
Update dashboard-app widget with HQ design system styling
Mar 20, 2026
227fab4
Push selection changes to Dashboard App via MessageChannel
Mar 20, 2026
63f4e53
Add SPA fallback redirect to netlify.toml
Mar 20, 2026
a9f49c8
Fix selection subscription — use basic Zustand subscribe
Mar 20, 2026
6c639a0
Allow apps drawer to expand to full window width
Mar 20, 2026
614f223
Fix drawer resize sticking when cursor is over iframe
Mar 20, 2026
f83368d
Replace arrow gizmo with translucent plane for section cuts
Mar 20, 2026
20442e5
Revert section plane changes, keep drawer improvements
Mar 20, 2026
481ff08
Revert all drawer changes to upstream
Mar 20, 2026
cbd09bd
Remove testdata from tracking, add to gitignore
Mar 21, 2026
b7f2cdc
Clean section plane implementation: bypass IfcPlane, use context dire…
Mar 21, 2026
fd22315
Add NavCube, IFC Inspector app, compact apps listing
Mar 21, 2026
629b298
Revert UI theme changes, keep apps listing fixes
Mar 21, 2026
d5620bb
Fix memory leaks: viewer disposal, GPU cleanup, event handlers
Mar 21, 2026
d0e83fd
Add Test Models browser, Recent Models, local model serving
Mar 21, 2026
80fbe18
Add CLAUDE.md with build versioning log and project context
Mar 21, 2026
eab747b
Add Architect agent with IFC building knowledge base
Mar 21, 2026
fe5dd75
Add floor plan view feature (build 016)
Mar 21, 2026
41aafae
Switch all toolbar icons to Lucide React (build 020)
Mar 21, 2026
0d9b0fa
UI refresh builds 021-038: layout, icons, panels, light toggle
Mar 22, 2026
7947bbe
Revert to working overlay layout (build 045)
Mar 22, 2026
ebdcfaa
Dashboard App neutral style, apps drawer offset (build 051)
Mar 22, 2026
1b29e25
ViewerToolbar, NavSphere, Terrain, apps drawer resize (build 059)
Mar 22, 2026
313d9ca
Build 060: NavSphere, floor plan, project management, model versioning
Mar 22, 2026
8aea47d
Remove docs-internal from repo, add to .gitignore
Mar 22, 2026
d2f761f
Build 060: GH Pages fixes, seed export/import, view state, sun controls
Mar 22, 2026
e269457
Mobile UI, admin localhost-only, seed import fix
Mar 22, 2026
6a54a0a
Build 060: Theme system, section plane controls, style cleanup
Mar 22, 2026
0648675
UI polish: fast menu, hover animations, layout restructure
Mar 23, 2026
654a425
Element filter, search in toolbar, UI fixes
Mar 23, 2026
172313b
Google Drive integration, .env auto-loader, COOP/COEP fixes
Mar 24, 2026
4df3943
Add codebase improvement areas document
claude Mar 24, 2026
b4e42af
Add floor plan comparison spec: bldrs-share vs ThatOpen v2
claude Mar 25, 2026
8de5dc2
Add portable per-feature specs for cross-repo comparison
claude Mar 25, 2026
0c65648
Merge origin/main, resolve conflicts in viewer, AppIFrame, CadView
claude Mar 25, 2026
731b8ba
Merge pull request #23 from MarkusSteinbrecher/claude/fix-memory-leak…
MarkusSteinbrecher Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ test-results
# symlink for test-models repo
public/test-models

# internal docs (not for public deployment)
/docs-internal

# environment secrets
.env
.env.local

# misc
.DS_Store
.vscode
Expand All @@ -32,3 +39,4 @@ public/test-models

# Local Netlify folder
.netlify
testdata/
134 changes: 134 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Bldrs Share — Fork

Fork of [bldrs-ai/Share](https://github.com/bldrs-ai/Share) with custom extensions.

## Dev Server

```bash
# Production config with real proxy URLs, no MSW mocking
MSW_IS_ENABLED=false SHARE_CONFIG=prod serveHttps=false yarn serve-share-conway
```

After restart, clear site data in Chrome DevTools → Application → Storage.
Enable "Disable cache" in DevTools → Network tab.

Port 8080 (frontend) + 8079 (esbuild backend).

## Build Versioning

Build number shown top-center of the viewport. Increment in `src/Containers/TopBar.jsx` on each deploy.

Current build: **060**

| Build | Changes |
|-------|---------|
| 001 | Build version indicator added |
| 002 | Icon size 40px → 24px, button size 3em → 2.25em |
| 003 | Onboarding popup disabled |
| 004 | Help moved to top-right |
| 005 | Cache-busting headers, service worker auto-unregister |
| 006 | All icons in left toolbar, service worker cleanup |
| 007 | Left toolbar with all tools, OperationsGroup removed from center |
| 008 | All controls consolidated in left toolbar |
| 009 | Expand/collapse with section labels |
| 010 | Expand shows inline icon + text labels |
| 011 | Full-height left nav, Bldrs logo at bottom, outlined MUI icons |
| 012 | Marker control removed from left nav |
| 013 | Memory leak fixes: viewer disposal, GPU cleanup, event handler cleanup |
| 014 | Recent Models tab in Open dialog |
| 015 | Test Models tab: browseable local IFC test models from testdata/ |
| 016 | Floor plan view feature |
| 017 | Icons 20px, buttons 2em, stroke-width experiment |
| 018 | All toolbar icons replaced with Lucide React (thin strokes) |
| 019 | Profile + FloorPlan icons switched to Lucide |
| 020 | Fixed Bldrs logo (use img instead of SvgIcon) |
| 021-024 | TopBar, left nav full-height, drawer offsets, resizer thin line |
| 025 | Nav tree: Lucide eye/chevron icons, hover-to-show hide, 13px font |
| 026-028 | z-index fixes, SideDrawer offsets, transparent panel backgrounds |
| 029-030 | Build version in TopBar, nav drawer margin fixes |
| 031 | NavTree spatial/types icons switched to Lucide |
| 032-033 | Selected icon turns bldrs green, transparent background |
| 034 | Open dialog: consistent compact list style across all tabs |
| 035 | Light/shadow toggle, BLDRS skyline model |
| 036 | Individual app icons replace app store, Divider separator |
| 037-038 | PanelLeft toggle icon (Insight style), CSS width transition |
| 039-058 | TopBar, ViewerToolbar, apps drawer, section plane grid, LightManager, NavCube |
| 059 | NavSphere: brighter wireframe, background disc, drag-to-orbit, clickable axis dots |
| 060 | NavSphere arrows (Lucide chevrons), ViewerToolbar/NavCube floor plan offset, floor plan toggle + title bar, app icon toggle + green highlight, Company/Project/Model data layer (IndexedDB + OPFS), ProjectAdmin dialog (Companies/Projects/Models tabs with version control), ProjectSelector breadcrumb + reload, MessageChannel extensions (getProjectContext/loadAppData/saveAppData) |

## UI Architecture (Overlay-based)

The UI uses absolute-positioned overlays on top of the Three.js canvas. A VS Code-style flex layout was attempted (builds 039-048) but caused blank pages because Three.js needs real pixel dimensions at canvas creation time. The flex approach (AppShell.jsx) was abandoned.

**Layout stack (z-index order):**
- `ViewerContainer` — Three.js canvas, absolute top:0 left:0, adjusts width for apps drawer
- `LeftToolbar` — absolute left strip (40px collapsed, 160px expanded), top:40px
- `TopBar` — absolute top bar (40px tall), contains build version + app icons + profile/help
- `ViewerToolbar` — floating pill bar centered below top bar (camera/light/wireframe/projection controls)
- `NavCube` — bottom center, shifts left when apps drawer opens
- `SideDrawer` — right-side panels (NavTree, Properties, Apps, etc.)

**Key state:**
- `isAppsVisible` / `appsDrawerWidth` — controls viewer canvas width + NavCube position
- `selectedElement` — drives Properties panel + selection sync to iframe apps
- `isModelReady` — gates terrain, floor plan, app icons in TopBar

## Our Changes vs Upstream

Key files changed from upstream `bldrs-ai/Share`:

**Layout & containers:**
- `src/Containers/CadView.jsx` — fixed updateLoadedFileInfo, added recent model tracking
- `src/Containers/viewer.js` — disposeViewer() for proper cleanup, ResizeObserver
- `src/Containers/LeftToolbar.jsx` — new: consolidated vertical toolbar (expandable)
- `src/Containers/TopBar.jsx` — new: top bar with build version, app icons, profile/help
- `src/Containers/ViewerToolbar.jsx` — new: floating viewer controls (fit, reset, light, wireframe, projection)
- `src/Containers/ViewerContainer.jsx` — width adjusts for apps drawer, ResizeObserver for resize
- `src/Containers/RootLandscape.jsx` — new layout with all overlay components

**Components:**
- `src/Components/NavCube/NavCube.jsx` — Three.js NavSphere with drag-to-orbit, axis dots, background disc
- `src/Components/Apps/AppsMessagesHandler.js` — getFileData via OPFS, selection sync, dispose()
- `src/Components/Apps/AppsRegistry.json` — 3 apps: Dashboard, IFC Inspector, IFC Quantities
- `src/Components/Apps/AppIFrame.jsx` — appPrefix URL resolution, channel cleanup
- `src/Components/Open/LocalModels.jsx` — browseable test models from testdata/
- `src/Components/Open/RecentModels.jsx` — recent models in localStorage
- `src/Components/Open/OpenModelDialog.jsx` — 5 tabs: Local, Recent, Test, GitHub, Samples
- `src/Components/Terrain/TerrainControl.jsx` — terrain overlay toggle
- `src/Components/FloorPlan/SVGFloorPlan/SVGFloorPlanView.jsx` — floor plan rendering

**Infrastructure:**
- `src/Infrastructure/CutPlaneGizmo.ts` — grid-pattern section plane visual
- `src/Infrastructure/GlbClipper.js` — unified clipper for IFC + GLB
- `src/Infrastructure/LightManager.js` — directional light + shadow toggle

**Store:**
- `src/store/useStore.js` — added TerrainSlice
- `src/store/SideDrawerSlice.jsx` — apps drawer default = 50% screen width
- `src/store/TerrainSlice.js` — terrain state

**Theme & styles:**
- `src/Styles.jsx` — 18px icons, hover-to-show nav tree hide buttons
- `src/theme/Components.js` — 2em buttons, 6px radius, bldrs green (#00ff00) for selected
- `src/privacy/firstTime.js` — onboarding disabled

**Build & deploy:**
- `public/index.html` — cache-busting headers, SW unregister
- `tools/esbuild/proxy.js` — serves /testdata/ from disk
- `netlify.toml` — SPA fallback redirect
- `package.json` — added lucide-react dependency

## Known Issues & Deferred Work

- **VS Code flex layout**: AppShell.jsx exists but is NOT wired in. Three.js needs pixel dimensions at init.
- **Section planes**: Work but could be improved (stencil caps, TransformControls for positioning).
- **Netlify free tier**: Bandwidth can be exhausted by frequent deploys.
- **Style/theme page**: User wants a theme selector (like Insight's Warm/Cool/Yello) — not yet built.
- **Architect agent**: Can generate IFC files via direct STEP text. More building models wanted.

## IFC File Creation

Conway is read-only. For creating IFC files:
- **web-ifc**: `CreateModel()` + `WriteLine()` + `SaveModel()` — WASM-based, entity-level
- **Direct STEP text**: template-based string generation with entity counter + GUID generator
- **IfcOpenShell (Python)**: highest-level API via `ifcopenshell.api`, can be called as subprocess
98 changes: 98 additions & 0 deletions CODEBASE_IMPROVEMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Codebase Improvement Areas

Audit performed on 2026-03-17. These are pre-existing issues unrelated to the memory leak fixes.

---

## Critical: Security

### 1. `document.write()` XSS Risk
- **File:** `src/Components/Profile/ProfileControl.jsx:153`
- **Problem:** Response HTML from a fetch call is written directly to the DOM using `document.write()`. If the response contains malicious scripts, they will execute in the user's browser context.
- **Fix:** Navigate to the URL directly or use `innerHTML` with a sanitization library (e.g. DOMPurify).

### 2. API Key Stored in Plain Text in localStorage
- **File:** `src/Components/Bot/BotChat.jsx:34, 74`
- **Problem:** The user's OpenRouter API key is stored unencrypted in `localStorage` under the key `openrouter_api_key`. Any XSS vulnerability in the app (including the `document.write` issue above) could exfiltrate this key.
- **Fix:** Use a more secure storage mechanism, or at minimum warn users about the risk. Consider using session-only storage or encrypting the value.

---

## High: Memory Leaks

### 3. Event Listener Not Cleaned Up on Unmount
- **File:** `src/Components/Apps/AppIFrame.jsx:28`
- **Problem:** A `load` event listener is added to the iframe element but never removed when the component unmounts.
- **Fix:** Return a cleanup function from the `useEffect` that calls `removeEventListener`.

### 4. Timer Not Cleared on Unmount
- **File:** `src/Components/Open/SaveModelControl.jsx:372-383`
- **Problem:** A module-level `snackTimeout` variable holds a `setTimeout` reference. If the component unmounts before the timeout fires, it will attempt to update state on an unmounted component.
- **Fix:** Use a ref for the timeout and clear it in a useEffect cleanup.

### 5. Module-Level Shared State
- **File:** `src/Containers/CadView.jsx:32-33`
- **Problem:** `count` and `previousThemeChangeCb` are declared at module scope. They persist across component instances and can cause stale references and accumulated theme listeners.
- **Fix:** Move these into component scope using refs.

### 6. File Input Listener Leak
- **File:** `src/utils/loader.js:85-87`
- **Problem:** A `change` event listener is added to a dynamically created file input, which is then immediately removed from the DOM. The listener may fire after removal or never be garbage collected cleanly.
- **Fix:** Remove the event listener explicitly after handling or before removing the element.

---

## High: React Anti-Patterns

### 7. Missing useEffect Dependencies (CadView)
- **File:** `src/Containers/CadView.jsx:614-629`
- **Problem:** ESLint exhaustive-deps rule is disabled. `hasGitHubIdentity` and `isViewerLoaded` are used inside the effect but missing from the dependency array, creating stale closures.
- **Fix:** Add missing dependencies or restructure to avoid the stale closure.

### 8. Missing useEffect Dependencies (NotesControl)
- **File:** `src/Components/Notes/NotesControl.jsx:96-97, 232-233, 240-241`
- **Problem:** Multiple `useEffect` hooks have suppressed exhaustive-deps warnings with significant missing dependencies including `accessToken`, `setNotes`, `toggleSynchSidebar`, and others.
- **Fix:** Audit each effect and add the correct dependencies.

### 9. Unhandled Async in useEffect
- **File:** `src/Components/Open/SaveModelControl.jsx:36-49`
- **Problem:** `fetchOrganizations()` is called inside a useEffect with no `.catch()` or try/catch. Network failures will result in unhandled promise rejections.
- **Fix:** Wrap in try/catch with appropriate error handling/user feedback.

---

## Medium: Code Quality

### 10. Non-Standard Document Property Mutation
- **File:** `src/Components/Camera/CameraControl.jsx:69-73`
- **Problem:** `document.wheeling` is used as a debounce timer store. This is not a standard DOM property and could conflict with other code or libraries.
- **Fix:** Use a React ref instead.

### 11. Duplicate Viewport Meta Tags
- **File:** `public/index.html:7, 9-10`
- **Problem:** Two `<meta name="viewport">` tags exist. This can cause unpredictable viewport behavior, especially on mobile browsers, and may contribute to the blank-page-on-mobile issue.
- **Fix:** Remove the duplicate and keep only one comprehensive viewport tag.

### 12. No Callback Memoization in BotChat
- **File:** `src/Components/Bot/BotChat.jsx:77-96`
- **Problem:** `handleSend` accesses store state and is recreated on every render without proper memoization of dependencies. Large message arrays will cause frequent re-renders.
- **Fix:** Ensure all dependencies are stable or memoized.

### 13. Inefficient Array Operations in NotesControl
- **File:** `src/Components/Notes/NotesControl.jsx:68-84`
- **Problem:** `.reverse().flatMap()` with side effects (push inside flatMap). This is both inefficient for large arrays and violates functional programming expectations.
- **Fix:** Use a simple loop instead of flatMap with side effects.

---

## Low: Deprecated Patterns

### 14. Deprecated Auth0 Logout Pattern
- **File:** `src/Components/Profile/ProfileControl.jsx:112-119`
- **Problem:** Uses the older Auth0 logout callback pattern with `openUrl`.
- **Fix:** Migrate to Auth0's current redirect-based logout API.

### 15. Unused Variables
- **Files:** `src/Components/Notes/NoteContent.jsx:19`, `src/Components/Notes/NoteCard.jsx:300`
- **Problem:** ESLint `no-unused-vars` rule is suppressed for variables that should be cleaned up.
- **Fix:** Remove unused variables.
Loading
Loading