Skip to content

feat(site): landing page + playground with spiral staircase hero#110

Merged
andymai merged 9 commits into
mainfrom
feat/site-visual-upgrade
Feb 6, 2026
Merged

feat(site): landing page + playground with spiral staircase hero#110
andymai merged 9 commits into
mainfrom
feat/site-visual-upgrade

Conversation

@andymai
Copy link
Copy Markdown
Owner

@andymai andymai commented Feb 6, 2026

Summary

  • Add brepjs website: landing page with hero 3D viewer + interactive playground with Monaco editor
  • Spiral staircase hero model showcasing parametric CAD (for-loops, transforms, helix sweep, ball endcaps)
  • Pre-computed hero mesh (252KB) seeds both landing page and playground for instant display while WASM loads
  • CAD studio visual style: warm clay material, studio HDRI reflections, contact shadows, dark charcoal edges
  • Landing page copy rewrite: "Parametric CAD in TypeScript", responsive layout, side-profile camera angle
  • Monaco editor StrictMode fix: uncontrolled mode (defaultValue + keepCurrentModel), idempotent setup
  • Shared SceneSetup with Environment, ContactShadows, infinite grid
  • Scoped COEP headers to playground/WASM routes only

Changes

  • site/src/lib/constants.ts — HERO_CODE: parametric spiral staircase with handrail helix sweep + ball endcaps
  • site/scripts/precompute-hero-mesh.ts — Generates hero-mesh.json matching HERO_CODE
  • site/src/components/landing/ — Hero section, code display, features, install, responsive layout
  • site/src/components/playground/EditorPanel.tsx — Uncontrolled Monaco to fix React 19 StrictMode disposal crash
  • site/src/components/playground/PlaygroundPage.tsx — Seeds viewer with pre-computed mesh on load
  • site/src/lib/monacoSetup.ts — Idempotent setup guard for StrictMode double-invoke
  • site/src/types/brepjs-ambient.d.ts — Ambient types for playground autocomplete (~80 functions)

Test plan

  • npm run typecheck passes
  • All 78 test files pass (1301 tests)
  • Manual QA: landing page hero renders staircase with ball endcaps, side-profile camera, auto-rotate
  • Manual QA: playground shows pre-computed mesh immediately, then live result after WASM init
  • Manual QA: Monaco editor loads without console errors (no InstantiationService disposed)
  • Manual QA: example picker updates editor and viewer correctly
  • Verify responsive layout on mobile (viewer-first, no horizontal scroll)
  • Verify OrbitControls (drag, zoom, pan) work on both viewers

Comment thread site/src/workers/cad.worker.ts Fixed
Comment thread site/src/workers/cad.worker.ts Fixed
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Feb 6, 2026

Greptile Overview

Greptile Summary

This PR adds a complete brepjs website with a landing page and interactive playground. The implementation includes:

Architecture:

  • Landing page with 3D hero viewer using precomputed mesh for instant load
  • Interactive playground with Monaco editor and live 3D preview
  • Web Worker isolation for WASM/code execution with proper COOP/COEP headers
  • Shared CAD studio visual style: warm clay material, HDRI reflections, contact shadows, dark edges

Key Technical Decisions:

  • User code runs in Web Worker via new Function() for isolation (intentional for playground functionality)
  • WASM loader dynamically imported via blob URL to avoid bundling issues
  • All brepjs exports injected onto globalThis in worker for import-free code
  • Code/URL sync with LZ-string compression
  • Examples array intentionally cleared for quality rebuild in follow-ups
  • Excluded site/** from root Vitest config to prevent symlinked dependency test discovery

Code Quality:

  • Well-structured React components with proper TypeScript types
  • Zustand stores for state management
  • Custom hooks for worker communication and code execution
  • Proper cleanup of globalThis keys after execution
  • Error handling with line number extraction from stack traces

Confidence Score: 4/5

  • This PR is safe to merge with standard testing recommended
  • Score reflects a well-architected website implementation with proper security headers (COOP/COEP), worker isolation, and clean component structure. The intentional use of new Function() for code evaluation is properly sandboxed. Minor point deduction because: (1) the PR adds 6700+ lines that would benefit from manual QA testing as outlined in the test plan, and (2) the examples array is cleared, so some features like ExamplesPreview won't be fully functional until follow-up PRs
  • Pay close attention to site/src/workers/cad.worker.ts (code execution logic) and verify the manual QA checklist in the PR description, particularly the visual rendering and WASM loading

Important Files Changed

Filename Overview
vitest.config.ts Added site/** to test exclusions to prevent symlinked dependency test discovery
site/vite.config.ts Vite config with COOP/COEP headers for SharedArrayBuffer, code splitting for Monaco/Three.js, excludes brepjs-opencascade from optimization
site/vercel.json Vercel deployment config with COOP/COEP headers, aggressive WASM caching, SPA rewrites
site/src/workers/cad.worker.ts Web worker loads WASM, injects brepjs onto globalThis, evaluates user code with new Function(), meshes shapes, exports STL
site/src/hooks/useWorker.ts Hook initializes CAD worker, manages message passing, updates engine store with init progress
site/src/hooks/useCodeExecution.ts Hook manages code execution with debounce, auto-runs on engine ready, handles eval results/errors, triggers STL export
site/src/lib/monacoSetup.ts Monaco editor theme and TypeScript config, loads brepjs ambient types for autocomplete
site/src/components/landing/HeroViewer.tsx Hero 3D viewer with precomputed mesh, auto-rotation, auto-fit camera, clay material, CSS vignette overlay
site/src/components/playground/PlaygroundPage.tsx Main playground page layout with editor/viewer split, toolbar, status bar, loading overlay

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread site/src/workers/cad.worker.ts Outdated

try {
// Wrap user code in a function and execute it
const fn = new Function(code);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using new Function() executes arbitrary user code in the worker, which is the intended playground behavior. Properly isolated with Web Worker sandbox and COOP/COEP headers.

Prompt To Fix With AI
This is a comment left during a code review.
Path: site/src/workers/cad.worker.ts
Line: 93:93

Comment:
Using `new Function()` executes arbitrary user code in the worker, which is the intended playground behavior. Properly isolated with Web Worker sandbox and COOP/COEP headers.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +36 to +42
// We fetch + blob URL to avoid Vite/Rollup trying to resolve it at build time
const resp = await fetch('/wasm/brepjs_single.js');
const jsText = await resp.text();
const blob = new Blob([jsText], { type: 'application/javascript' });
const blobUrl = URL.createObjectURL(blob);
const ocModule = await import(/* @vite-ignore */ blobUrl);
URL.revokeObjectURL(blobUrl);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the /wasm/ directory is only writable during build/deployment, not at runtime, since this code dynamically imports JS from that location.

Prompt To Fix With AI
This is a comment left during a code review.
Path: site/src/workers/cad.worker.ts
Line: 36:42

Comment:
Ensure the `/wasm/` directory is only writable during build/deployment, not at runtime, since this code dynamically imports JS from that location.

How can I resolve this? If you propose a fix, please make it concise.

@andymai andymai changed the title feat(site): landing page + playground with CAD studio visuals feat(site): landing page + playground with spiral staircase hero Feb 6, 2026
Add the brepjs website with landing page + interactive playground:

- Landing page with hero 3D viewer, code display, features section
- Playground with Monaco editor, 3D viewer, WASM-powered CAD engine
- CAD studio visual style: warm clay material (#c8c0b8), studio HDRI
  reflections, contact shadows, dark charcoal edges, CSS vignette
- Shared SceneSetup with Environment, ContactShadows, infinite grid
- Examples cleared for quality rebuild
- Exclude site/ from root Vitest to avoid symlinked dependency tests
Landing page no longer sends Cross-Origin-Embedder-Policy: require-corp,
which could interfere with Googlebot crawling. The COEP/COOP headers
(needed for SharedArrayBuffer) are now only set on /playground and /wasm/.
…ive layout

- Headline: "Parametric CAD / in TypeScript"
- Features section: "Built on OpenCascade" with shorter, scannable cards
- Hero shape: parametric spiral staircase with column, treads, railing
  posts, and swept handrail (replaces box-with-hole)
- Hero code: full staircase example showing for-loop, sweep, helix
- Default playground code loads the staircase example
- Hide empty examples section until examples exist
- Remove redundant GitHub button from install section
- Footer: inline Apache-2.0 + GitHub link
- Responsive: mobile-first padding, flex-wrap CTAs, viewer-first order
  on mobile, scrollable code panel, min-w-0 grid children, overflow-x
  hidden on root
- Custom thin dark scrollbars for code panels
- Camera near/far adjusted for larger model
…layground mesh

- Add sphere ball endcaps on first and last handrail ends
- Increase hero code/viewer height to 560px from 400px
- Set landing page camera to side profile (15° elevation)
- Rename code preview tab to staircase.ts
- Seed playground viewer with pre-computed hero mesh while WASM loads
- Fix Monaco editor StrictMode crash: switch to uncontrolled mode
  (defaultValue + keepCurrentModel), make setupMonaco idempotent,
  guard marker effects against disposed editor
- Remove fillet from hero code (OCCT fails on complex boolean result)
- Add missing ambient types (makeCircle, makeLine, genericSweep)
- Clean up unused filletShape import from precompute script
…ion scan

The playground intentionally evaluates user-authored code via new Function()
in a sandboxed Web Worker with no DOM, cookies, or storage access.
@andymai andymai force-pushed the feat/site-visual-upgrade branch from ce2d981 to 0256edc Compare February 6, 2026 22:02
Comment thread site/src/workers/cad.worker.ts Dismissed
Comment thread site/src/workers/cad.worker.ts Dismissed
Security hardening from audit:
- Add Content-Security-Policy with connect-src 'self' to restrict Worker
  fetch() to same-origin, blocking SSRF/exfiltration via shared links
- Allow cdn.jsdelivr.net for Monaco editor CDN loading
- Add pendingReview flag: shared-link code is NOT auto-executed
- Show amber warning banner with Run/Dismiss for URL-loaded code
- Toolbar Run button also clears pendingReview state
The default CodeQL setup is enabled in repo settings and can't coexist
with an advanced workflow. The playground's new Function() alerts will
be dismissed as intentional in the PR security tab. The CSP headers
(connect-src 'self') are the real mitigation for the network vector.
@andymai andymai merged commit 55cacd3 into main Feb 6, 2026
3 of 4 checks passed
@andymai andymai deleted the feat/site-visual-upgrade branch February 6, 2026 22:17
brepjs Bot added a commit that referenced this pull request Feb 6, 2026
🤖 I have created a release *beep* *boop*
---


##
[4.17.0](brepjs-v4.16.0...brepjs-v4.17.0)
(2026-02-06)


### Features

* **site:** landing page + playground with spiral staircase hero
([#110](#110))
([55cacd3](55cacd3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: brepjs-bot[bot] <258782221+brepjs-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants