Skip to content

viewer: render live scenes in any browser app, proven by a packed fixture - #1250

Merged
wass08 merged 5 commits into
mainfrom
viewer/live-portability
Nov 10, 2026
Merged

wass08 merged 5 commits into
mainfrom
viewer/live-portability

Conversation

@wass08

@wass08 wass08 commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Makes the render-only entry from #1246 usable from any browser app. An external Vite app that installs the packed @pascal-app/core, @pascal-app/viewer and @pascal-app/nodes, with no @pascal-app/editor and no next in its tree, can now hydrate a scene graph and render it live with renderPlugin and <Viewer>. Stacked on #1246.

  • configureViewer({ assetsBaseUrl, storageUrl, decoders }) replaces module-evaluation process.env reads. Defaults keep today's behaviour; apps/editor passes its environment explicitly.
  • Draco and Basis decoder directories are configurable through every loader. Basis is pinned instead of drei-assets@master.
  • Remaining render-path environment reads are guarded, so apps need no process polyfill.
  • The Viewer's canvas background, transition and GPU fallback use inline styles, so they render without Tailwind; the editor looks the same.
  • Viewer preferences tolerate denied storage.
  • The viewer README and wiki/architecture/viewer-isolation.md document the boot sequence and the one-active-scene-per-page limit.
  • fixtures/viewer-live and bun run check:viewer-live pack the three packages, install them outside the repo with npm, and assert neither the editor nor next is installed. They then build with Vite, and check vite dev and vite preview, with storage available and denied, reach scene-ready with geometry for every node (walls, door, window, roof, ceiling with a procedural downlight cut, zone, measurement, separator, a GLTF item), draw calls and no page errors. A separate CI job runs it.

How to test

  1. bun run check:viewer-live: about 45 s; prints the isolation check, the Vite build and four browser runs (dev and preview, storage available and denied), each with geometry for every node and its draw-call count.
  2. bun run check:render-bundle: still passes.
  3. Open the editor: canvas, loading transition and GPU fallback look unchanged; assets and textures load.

Screenshots / screen recording

N/A: no visual change in the editor. The fixture is verified headlessly (SwiftShader) in dev and production builds.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

🤖 Generated with Claude Code


Note

Medium Risk
Touches core rendering config (asset URLs, decoders, env detection) and viewer persistence; mitigated by new isolated fixture CI and existing render-bundle check.

Overview
Enables embedding the live Pascal viewer in ordinary React apps (e.g. Vite) without Next.js, Tailwind, or @pascal-app/editor. Hosts call configureViewer for asset CDN, storage, and Draco/Basis decoder paths; URL resolution and loaders read config at use time instead of baking in process.env, so browser bundles do not need a process polyfill.

isDevelopmentBuild / isDevelopmentOutsideTests in core replace fragile NODE_ENV guards in polygon clipping and derived-node warnings. The viewer canvas background and unsupported-GPU fallback move to inline styles; viewer preferences persist through storage-safe accessors that tolerate denied localStorage. The editor bootstrap explicitly passes its public CDN/Supabase URLs via configureViewer.

Adds fixtures/viewer-live, root script check:viewer-live, and a CI viewer-live job that packs @pascal-app/core, @pascal-app/viewer, and @pascal-app/nodes, installs them in an isolated npm tree, asserts no Next/editor dependency, and Playwright-smokes Vite dev/preview for scene-ready geometry and draw calls (with and without storage). README and wiki/architecture/viewer-isolation.md document the boot sequence and one-active-scene-per-page limit.

Reviewed by Cursor Bugbot for commit b4c04cd. Bugbot is set up for automated code reviews on this repo. Configure here.

@wass08
wass08 force-pushed the viewer/render-entry branch from 1bc8b3d to 5e7fd8e Compare November 10, 2026 12:47
@wass08
wass08 force-pushed the viewer/live-portability branch from affad35 to 14bacf8 Compare November 10, 2026 12:48

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread .github/workflows/ci.yml Resolved
Comment thread apps/editor/lib/bootstrap.ts Resolved
Base automatically changed from viewer/render-entry to main November 10, 2026 13:00
…ture

Slice 1b of the render-only entry: an external Vite app installing the
packed @pascal-app/core, viewer and nodes, with no editor and no Next in
its tree, hydrates a scene graph and renders it live with renderPlugin.

- configureViewer({ assetsBaseUrl, storageUrl, decoders }) replaces
  module-evaluation process.env reads; defaults keep today's behaviour
  and the standalone editor passes its environment explicitly
- Draco and Basis decoder directories are configurable through every
  loader; Basis is pinned instead of drei-assets@master
- remaining render-path environment reads are guarded, so no process
  polyfill is needed
- the Viewer's canvas background, transition and GPU fallback use inline
  styles, so they render without Tailwind
- viewer preferences tolerate denied storage
- the viewer README and viewer-isolation page document the boot sequence
  and the one-active-scene-per-page limit
- fixtures/viewer-live + scripts/check-viewer-live-fixture.ts pack the
  three packages, install them outside the repo, assert neither the
  editor nor next is installed, build with Vite, and check dev and
  preview (storage available and denied) reach scene-ready with geometry
  for every node, draw calls and no page errors; runs in CI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wass08
wass08 force-pushed the viewer/live-portability branch from 14bacf8 to 8a0b7e0 Compare November 10, 2026 13:01
CI forces colour output and Vite then wraps the port of its printed URL in
escape codes, so the fixture never found the server. Spawn servers with
colour off and strip escape codes before matching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

wass08 and others added 2 commits November 10, 2026 08:21
…ure time

From CI and Bugbot on the live-portability PR.

- a `typeof process` guard runs in the browser, where process is absent,
  so packed Vite production builds took the development branch (empty-draw
  warnings, ?stockEvents, system and clipping diagnostics). One core helper,
  isDevelopmentBuild, reads process.env.NODE_ENV directly, which bundlers
  replace with a constant, and treats an unbundled browser as production
- the fixture builds its colour-code regex from the escape character
  instead of a control character in a literal
- the packed fixture job gets 15 minutes instead of 5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On CI the fixture passed in 129 s and then hung until the job timeout:
killing `npm run` left its Vite and esbuild children running on Linux.
Servers now run in their own process group, which is stopped as a whole,
and the script exits once it has printed its verdict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit dc479a7. Configure here.

Comment thread scripts/check-viewer-live-fixture.ts Resolved
From Bugbot: the forced exit only ran after a pass, so a failing fixture
still waited out the job timeout on leftover handles. Failures now print
the error and exit 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wass08
wass08 merged commit 19a2fa1 into main Nov 10, 2026
6 checks passed
@wass08
wass08 deleted the viewer/live-portability branch November 10, 2026 14:00
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.

1 participant