You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document is now the working roadmap for the released @compas-dev/compas-threejs-ts package.
Current status
Last reviewed: 2026-08-14
v1.0.0 was published on 2026-08-13.
v1.0.1 is the current release on main; it made npm publication retryable.
The repository is owned by compas-dev and the package is published as @compas-dev/compas-threejs-ts.
Release Please creates release pull requests and GitHub releases. GitHub
Actions publishes to npm with Trusted Publishing and provenance.
The sibling Python package remains a first-class consumer of the standalone
build and must continue to work without Node.js at installation or runtime.
Remote follow-up work exists on these branches and should be reviewed before
reimplementing the same features:
origin/feature/spinner
origin/feature/object-visibility
origin/feature/object-actions-panel
Their status relative to main is a dated observation, not a guarantee that a
pull request is still open.
What shipped in 1.0
The completed release work can be summarized as follows:
A side-effect-free, instance-based createViewer API with embedded and
WebSocket modes, explicit dispatch, reset, resize, and dispose
lifecycle methods, typed errors, host callbacks, and multi-instance support.
Separate ESM library and standalone application builds, curated TypeScript
declarations and exports, explicit CSS, restrictive package contents, clean
consumer installation tests, and self-hosted UI fonts.
Binary Python-to-browser COMPAS Protobuf dispatch and JSON browser-to-Python
callbacks, with Python-generated compatibility fixtures and deliberate errors
for unsupported or invalid messages.
The documented 1.0 rendering set: Box, Capsule, Circle, Cone, Cylinder,
Frame, Line, Mesh, Plane, Point, Pointcloud, Polyhedron, Polyline, Sphere,
Torus, and Vector. Python Breps use the view-mesh path.
Materials, lights, scene controls, themes, UI controls, text tags, metadata,
object actions, visibility commands, picking, and the embedded kitchen-sink
example, subject to the limits recorded in docs/support-matrix.md.
Effective strict TypeScript, ESLint, Prettier, unit, compatibility, build,
packed-package, production-audit, and Chromium browser gates in CI.
Public metadata, MIT licensing, compatibility and dependency policies,
changelog, release instructions, automated GitHub releases, and npm
publication through a protected environment.
Cross-repository fixes for the Python compas_pb >=1,<2 constraint, its test
task, and the default PhysicalMaterial.attenuation_distance wire value.
The old stacked-PR instructions, rewritten commit SHAs, pre-release gates, and
completed audit narratives have been removed. Consult git log, the tagged
releases, and CHANGELOG.md when historical detail is needed.
What's left: quick outline
Integrate the existing spinner, object-visibility, and object-actions UI
follow-ups and release them through the normal 1.x workflow.
Finish or explicitly narrow the limited command surface: text geometry,
Sky, sunlight, RectAreaLight, advanced physical materials, and exact Python
command parity.
Harden the shipped geometry, lifecycle, resource ownership, and UI behavior
with focused correctness and regression tests.
Harden WebSocket and untrusted-input handling, then expand browser and
security coverage.
Build the public documentation site and add the missing contributor and
security policies.
Add deferred geometry and Graph support incrementally after their contracts
are designed and tested.
Maintain compatibility, dependencies, release automation, and the sibling
Python/VS Code integrations across future 1.x releases.
Detailed plan
1. Integrate the active UI follow-ups
Treat the existing remote branches as review inputs. Rebase or update them from
current main; do not reproduce their changes from memory.
Review feature/spinner for command validation, accessibility, repeated
show/update/hide behavior, disposal, and Python-generated payload tests.
Review feature/object-visibility for hidden-object picking, reset,
replacement, removal, show-all behavior, and keyboard accessibility.
Review feature/object-actions-panel for selection changes, empty state,
callback values, narrow layouts, and interaction with ObjectInfo.
Resolve overlapping layout/store changes deliberately if the branches are
combined or merged in sequence.
Update the support matrix and changelog to describe the release in which
each feature actually ships. Do not retroactively imply that a post-1.0.0
feature was present in the original tarball.
Rebuild and review the sibling Python frontend assets in a separate,
explicit cross-repository change when a standalone feature is merged.
Acceptance criteria:
Each command has positive, malformed-input, replacement, reset, and disposal
coverage appropriate to its state.
Embedded mode and the Python WebSocket application behave consistently.
npm run check, npm run test:package, and npm run test:browser pass.
The resulting version is released only through Release Please and CI.
2. Complete the limited command and protocol surface
Python command parity
Generate deterministic Python fixtures for every material, light, scene,
UI, text, tag, metadata, object-action, visibility, and spinner variant.
Decode and validate those fixtures in TypeScript. Keep the Python
producer, TypeScript discriminated union, validator, handler, tests, and
protocol documentation synchronized.
Constrain Python Selection.options and default_value to the contract
expected by the TypeScript select command, or widen the browser contract
deliberately and test the chosen behavior.
Correct the live Python public parameter spellings clearcot_roughness and iridescenceior through a documented deprecation
path rather than an abrupt breaking change.
Add TypeScript-to-Python callback fixtures for UI, picking, object actions,
loaded JSON, and custom host messages.
The earlier default-PhysicalMaterial blocker is resolved: Python now omits an
unspecified attenuation distance and rejects non-finite explicit values. Keep
that behavior covered on both sides.
Text geometry
Decide whether typeface JSON files are bundled, resolved from Three.js,
or supplied through a configurable public asset base URL.
Ensure both the npm library and Python standalone build resolve assets
without assuming the host root is /.
Validate font name, weight, text length, direction/up vectors, and
degenerate bases.
Test successful loading, caching, failure reporting, replacement, reset,
and disposal. Only then move text geometry out of “limited”.
The bundled Inter WOFF2 file solves the viewer UI font and offline-privacy
problem; it does not supply the Three.js typeface JSON needed by text geometry.
Materials and lights
Replace the duplicated parseColor/parseInt helpers with a single
validated Three.js color conversion and cover valid and invalid forms.
Verify all physical-material fields against current Three.js semantics,
including ranges and optional values.
Make Sky elevation and azimuth drive its companion lights instead of
creating hard-coded white lights at the world origin.
Add directional-light targets to the scene graph so sunlight direction is
honored.
Verify the current Three.js setup requirements and rendering behavior for
RectAreaLight, then initialize or defer it explicitly.
Add conversion, replacement, and cleanup tests for every advertised
material and light variant.
Acceptance criteria:
Every public Python command has an exact wire fixture and one explicit status:
supported, limited with documented constraints, or unsupported.
Invalid payloads report stable errors without partially mutating viewer state.
The support matrix no longer groups unverified variants under broad claims
such as “basic materials and lights”.
3. Certify and harden the shipped rendering set
Keep the 1.0 geometry boundary stable while improving confidence. Do not mix new
geometry types into these hardening slices.
Add table-driven converter tests for every shipped geometry and helper,
including non-axis-aligned frames and non-origin positions.
Confirm the matrix element ordering in matrixFromElements against a
Python-generated, non-symmetric transform fixture.
Validate missing frame members, empty point sets, zero-length vectors,
parallel frame axes, non-finite coordinates, and malformed dimensions.
Test mesh/polyhedron index bounds, degenerate faces, fan-triangulation
limitations, normals, and upstream-triangulation guidance.
Test the documented display semantics: Circle as a filled disc, Plane as
a finite surface, and Frame/Vector as helpers.
Exercise replacement, assigned-material reuse, edge helpers, visibility,
picking, removal, reset, and disposal for every object category.
Add small visual-regression scenes for representative solids, curves,
helpers, points, and datastructures.
Acceptance criteria:
Every type listed as included has positive, invalid-input, orientation,
replacement, and cleanup coverage where applicable.
Renderer failures are deterministic CompasViewerErrors and do not corrupt
existing scene state.
The support matrix states known approximations and triangulation limits.
4. Finish lifecycle, ownership, and UI correctness
Separate CSS2D text-tag ownership from the geometry registry so GUID
collisions cannot silently replace unrelated objects; remove their DOM
elements on replacement and reset.
Dispose TransformControls, its helper resources, axes helpers, default
lights, and every viewer-owned material exactly once.
Define shared-versus-owned material rules so replacing or removing one
object never disposes a material still used by another.
Repair transform-button activation events and active styling; cover mouse
and keyboard mode changes.
Reuse the text-input shortcut guard in the runtime-level p, i, and
Escape handler.
Replace timestamp-only saved-view identifiers or otherwise prevent rapid
collisions.
Remove the remaining obsolete aliases, comments, duplicated helpers, and
release-number TODO labels after their behavior is covered.
Acceptance criteria:
Repeated create/reset/dispose and replacement loops leave no listeners,
render loops, DOM labels, scene objects, or owned GPU resources behind.
Two viewers remain independent under all tested UI and lifecycle actions.
Keyboard shortcuts never fire while editing an input, select, textarea, or
content-editable element.
5. Harden transport and untrusted input
Validate WebSocket host, port, workspace, and secure-mode inputs before
constructing the URL.
Catch synchronous constructor failures on initial and retry attempts.
Replace fixed unbounded retries with documented backoff/cancellation and
controlled-timer tests.
Decide whether embedded library consumers may inherit WebSocket settings
from the host page query string; make the precedence explicit.
Test binary receive, ignored text receive, JSON callback send, clean
shutdown, named workspaces, and Python state replay.
Add depth, object-count, and payload-size limits to recursive dispatch.
Replace or formally constrain the generic bytes instanceof Uint8Array
geometry heuristic.
Bound loaded JSON size and shape before sending it to a host.
Validate semantic ranges, collection sizes, and degeneracy in addition to
primitive field types.
Review text, labels, colors, URLs, and UI values for HTML/script injection
and uncontrolled browser resource allocation.
Acceptance criteria:
Malformed or hostile input is bounded, produces a useful error, and leaves
connection and scene state valid.
Retry and shutdown tests use controlled timers and never depend on wall-clock
sleeps.
Python reconnect/replay behavior is deterministic and idempotent.
6. Expand tests, compatibility, and CI
The current CI covers Node 22, strict checks, a production audit, a clean packed
consumer, and Chromium Playwright. Extend it where the support policy is broader
than the gate.
Run browser integration tests in Firefox and WebKit, or narrow the stated
browser policy until those engines are continuously tested.
Test the documented minimum Node version and the supported Three.js range.
Add coverage thresholds after dispatcher/lifecycle/command tests are
representative; prioritize complete public-boundary coverage over a broad
repository percentage.
Fail browser tests on unexpected console errors and warnings.
Establish package, bundle, source-map, and startup-performance budgets.
Add grouped automated dependency updates and keep production audit policy
explicit.
Mechanically verify that curated public.d.ts declarations match the
runtime exports, or replace the manual copy with generated declarations.
Acceptance criteria:
Every compatibility promise is exercised in CI or explicitly documented as
manually verified.
Packed-tarball tests cover runtime exports, declarations, CSS/assets, and a
real bundler consumer without repository aliases.
7. Publish complete public documentation and governance
The baseline README, compatibility policy, support matrix, dependency policy,
changelog, and release guide exist. Build the broader documentation only from
contracts established by the preceding slices.
Add VitePress for the site and TypeDoc with typedoc-plugin-markdown for the small public API reference.
Decide whether the TypeScript library has its own site or a section of the
Python documentation, and designate one canonical protocol reference.
Add complete Vite and non-Vite consumer examples using the packed package.
Publish documentation through GitHub Pages and test examples against the
released package.
Add CONTRIBUTING.md with architecture, setup, validation, generated
assets, and pull-request guidance.
Add SECURITY.md with supported versions and private-reporting guidance.
Add contribution templates and a code of conduct if required by the
organization.
Document semantic-versioning, deprecation, support, and emergency npm
deprecation/yank policies.
Acceptance criteria:
A new npm consumer can install, create, configure, use, and dispose a viewer
without reading source code.
Protocol behavior is documented once and linked from the Python and
TypeScript projects without contradictory copies.
8. Add post-1.0 geometry and Graph support
Each addition is a normal backward-compatible feature release with design,
Python fixtures, TypeScript tests, browser coverage, documentation, and a
changelog entry. A source placeholder is not an implementation.
Geometry candidates:
Arc
Bezier
Ellipse
Hyperbola
Parabola
Polygon
PolyhedronFace and MeshFaceList only if they become meaningful top-level
viewer objects
Decide whether Quaternion, Rotation, and Translation need visualizations
or remain non-renderable mathematical data.
For curve and surface additions:
Define sampling tolerances and configurable resolution.
Use robust triangulation for non-convex polygonal faces.
Normalize or reject invalid frames and transforms.
Add positive, invalid, orientation, replacement, material, picking, and
cleanup coverage before changing the support matrix.
Graph support:
Study COMPAS core's GraphSceneObject/compas.scene.GraphObject
behavior and define the intended viewer contract.
Decide whether the viewer consumes a Graph wrapper, an explicit scene
representation, or node/edge geometry messages.
Implement Graph rendering without coupling the public TypeScript API to a
Python-only scene-object implementation.
Add Python fixtures, interaction and cleanup tests, documentation, and a
representative example.
Acceptance criteria:
A new type appears as supported only after its public semantics and failure
behavior are documented and tested.
Additions do not break the stable 1.x viewer API, transport, or lifecycle.
9. Ongoing release and integration maintenance
Monitor npm and GitHub advisories and review dependency updates in focused
groups.
Test new compas-pb-ts, compas_pb, Three.js, Vue, TypeScript, Node, and
browser releases before widening declared ranges.
Keep versioned cross-language fixtures for every supported wire version.
Verify provenance, tarball contents, public quick starts, and npm install
after every release.
Update the Python static assets only from a reviewed frontend commit and
keep that destructive replacement as a separate diff.
Update the VS Code extension to and test it against the public
instance-based API; do not restore window.compasViewer.
Define issue-response, backport, and supported-release policies when more
than one line needs maintenance.
Deprecate public APIs through documented releases rather than silent
changes.
Working discipline
Start new work from current main; inspect active branches before duplicating
work.
Keep changes reviewable: protocol changes, generated Python assets,
mechanical formatting, and release automation should be separate commits.
For Python-to-browser changes, inspect the Python producer and add an exact
payload fixture. For browser-to-Python changes, inspect the Python inbox and
add a joint callback test.
Run both the npm library and standalone application paths. A green library
build alone does not protect the Python consumer.
The standard TypeScript verification set is:
npm run check
npm run audit:prod
npm run test:package
npm run test:browser
git diff --check
Run the sibling Python suite for coordinated protocol or asset changes.
sync_frontend deletes and replaces the packaged frontend directory. Inspect
exact paths first and review the generated asset diff separately.
Never run a checker against the root tsconfig.json without --build; it
contains project references and no root files. Use npm run typecheck.
Release through conventional commits, Release Please, and the protected npm
environment. Do not publish stable versions from a workstation.
Definition of done for a post-1.0 slice
A slice is complete when:
Its public behavior and unsupported cases are explicit.
Unit, compatibility, browser, packed-package, and Python tests have been added
in proportion to the change.
Resource ownership and reset/disposal behavior are covered.
The support matrix, API/protocol documentation, and changelog are consistent.
All relevant CI-equivalent checks pass from a clean dependency installation.
Cross-repository generated assets and integration changes are reviewed
separately.
Publication, when needed, is reproducible from the tagged main commit.
Release Plan and Post-1.0 Roadmap
This document is now the working roadmap for the released
@compas-dev/compas-threejs-tspackage.Current status
Last reviewed: 2026-08-14
v1.0.0was published on 2026-08-13.v1.0.1is the current release onmain; it made npm publication retryable.compas-devand the package is published as@compas-dev/compas-threejs-ts.Actions publishes to npm with Trusted Publishing and provenance.
build and must continue to work without Node.js at installation or runtime.
Remote follow-up work exists on these branches and should be reviewed before
reimplementing the same features:
origin/feature/spinnerorigin/feature/object-visibilityorigin/feature/object-actions-panelTheir status relative to
mainis a dated observation, not a guarantee that apull request is still open.
What shipped in 1.0
The completed release work can be summarized as follows:
createViewerAPI with embedded andWebSocket modes, explicit
dispatch,reset,resize, anddisposelifecycle methods, typed errors, host callbacks, and multi-instance support.
declarations and exports, explicit CSS, restrictive package contents, clean
consumer installation tests, and self-hosted UI fonts.
callbacks, with Python-generated compatibility fixtures and deliberate errors
for unsupported or invalid messages.
Frame, Line, Mesh, Plane, Point, Pointcloud, Polyhedron, Polyline, Sphere,
Torus, and Vector. Python Breps use the view-mesh path.
object actions, visibility commands, picking, and the embedded kitchen-sink
example, subject to the limits recorded in
docs/support-matrix.md.packed-package, production-audit, and Chromium browser gates in CI.
changelog, release instructions, automated GitHub releases, and npm
publication through a protected environment.
compas_pb >=1,<2constraint, its testtask, and the default
PhysicalMaterial.attenuation_distancewire value.The old stacked-PR instructions, rewritten commit SHAs, pre-release gates, and
completed audit narratives have been removed. Consult
git log, the taggedreleases, and
CHANGELOG.mdwhen historical detail is needed.What's left: quick outline
follow-ups and release them through the normal 1.x workflow.
Sky, sunlight, RectAreaLight, advanced physical materials, and exact Python
command parity.
with focused correctness and regression tests.
security coverage.
security policies.
are designed and tested.
Python/VS Code integrations across future 1.x releases.
Detailed plan
1. Integrate the active UI follow-ups
Treat the existing remote branches as review inputs. Rebase or update them from
current
main; do not reproduce their changes from memory.feature/spinnerfor command validation, accessibility, repeatedshow/update/hide behavior, disposal, and Python-generated payload tests.
feature/object-visibilityfor hidden-object picking, reset,replacement, removal, show-all behavior, and keyboard accessibility.
feature/object-actions-panelfor selection changes, empty state,callback values, narrow layouts, and interaction with ObjectInfo.
combined or merged in sequence.
each feature actually ships. Do not retroactively imply that a post-1.0.0
feature was present in the original tarball.
explicit cross-repository change when a standalone feature is merged.
Acceptance criteria:
coverage appropriate to its state.
npm run check,npm run test:package, andnpm run test:browserpass.2. Complete the limited command and protocol surface
Python command parity
UI, text, tag, metadata, object-action, visibility, and spinner variant.
producer, TypeScript discriminated union, validator, handler, tests, and
protocol documentation synchronized.
Selection.optionsanddefault_valueto the contractexpected by the TypeScript
selectcommand, or widen the browser contractdeliberately and test the chosen behavior.
clearcot_roughnessandiridescenceiorthrough a documented deprecationpath rather than an abrupt breaking change.
loaded JSON, and custom host messages.
The earlier default-
PhysicalMaterialblocker is resolved: Python now omits anunspecified attenuation distance and rejects non-finite explicit values. Keep
that behavior covered on both sides.
Text geometry
or supplied through a configurable public asset base URL.
without assuming the host root is
/.degenerate bases.
and disposal. Only then move text geometry out of “limited”.
The bundled Inter WOFF2 file solves the viewer UI font and offline-privacy
problem; it does not supply the Three.js typeface JSON needed by text geometry.
Materials and lights
parseColor/parseInthelpers with a singlevalidated Three.js color conversion and cover valid and invalid forms.
including ranges and optional values.
creating hard-coded white lights at the world origin.
honored.
RectAreaLight, then initialize or defer it explicitly.
material and light variant.
Acceptance criteria:
supported, limited with documented constraints, or unsupported.
such as “basic materials and lights”.
3. Certify and harden the shipped rendering set
Keep the 1.0 geometry boundary stable while improving confidence. Do not mix new
geometry types into these hardening slices.
including non-axis-aligned frames and non-origin positions.
matrixFromElementsagainst aPython-generated, non-symmetric transform fixture.
parallel frame axes, non-finite coordinates, and malformed dimensions.
limitations, normals, and upstream-triangulation guidance.
a finite surface, and Frame/Vector as helpers.
picking, removal, reset, and disposal for every object category.
helpers, points, and datastructures.
Acceptance criteria:
replacement, and cleanup coverage where applicable.
CompasViewerErrors and do not corruptexisting scene state.
4. Finish lifecycle, ownership, and UI correctness
collisions cannot silently replace unrelated objects; remove their DOM
elements on replacement and reset.
TransformControls, its helper resources, axes helpers, defaultlights, and every viewer-owned material exactly once.
object never disposes a material still used by another.
and keyboard mode changes.
p,i, andEscape handler.
collisions.
release-number TODO labels after their behavior is covered.
Acceptance criteria:
render loops, DOM labels, scene objects, or owned GPU resources behind.
content-editable element.
5. Harden transport and untrusted input
constructing the URL.
controlled-timer tests.
from the host page query string; make the precedence explicit.
shutdown, named workspaces, and Python state replay.
bytes instanceof Uint8Arraygeometry heuristic.
primitive field types.
and uncontrolled browser resource allocation.
Acceptance criteria:
connection and scene state valid.
sleeps.
6. Expand tests, compatibility, and CI
The current CI covers Node 22, strict checks, a production audit, a clean packed
consumer, and Chromium Playwright. Extend it where the support policy is broader
than the gate.
browser policy until those engines are continuously tested.
representative; prioritize complete public-boundary coverage over a broad
repository percentage.
explicit.
public.d.tsdeclarations match theruntime exports, or replace the manual copy with generated declarations.
Acceptance criteria:
manually verified.
real bundler consumer without repository aliases.
7. Publish complete public documentation and governance
The baseline README, compatibility policy, support matrix, dependency policy,
changelog, and release guide exist. Build the broader documentation only from
contracts established by the preceding slices.
typedoc-plugin-markdownfor the small public API reference.Python documentation, and designate one canonical protocol reference.
commands, lifecycle, errors, assets, browser support, and troubleshooting.
released package.
CONTRIBUTING.mdwith architecture, setup, validation, generatedassets, and pull-request guidance.
SECURITY.mdwith supported versions and private-reporting guidance.organization.
deprecation/yank policies.
Acceptance criteria:
without reading source code.
TypeScript projects without contradictory copies.
8. Add post-1.0 geometry and Graph support
Each addition is a normal backward-compatible feature release with design,
Python fixtures, TypeScript tests, browser coverage, documentation, and a
changelog entry. A source placeholder is not an implementation.
Geometry candidates:
viewer objects
or remain non-renderable mathematical data.
For curve and surface additions:
cleanup coverage before changing the support matrix.
Graph support:
GraphSceneObject/compas.scene.GraphObjectbehavior and define the intended viewer contract.
representation, or node/edge geometry messages.
incremental updates, and removal.
Python-only scene-object implementation.
representative example.
Acceptance criteria:
behavior are documented and tested.
9. Ongoing release and integration maintenance
groups.
compas-pb-ts,compas_pb, Three.js, Vue, TypeScript, Node, andbrowser releases before widening declared ranges.
after every release.
keep that destructive replacement as a separate diff.
instance-based API; do not restore
window.compasViewer.than one line needs maintenance.
changes.
Working discipline
Start new work from current
main; inspect active branches before duplicatingwork.
Keep changes reviewable: protocol changes, generated Python assets,
mechanical formatting, and release automation should be separate commits.
For Python-to-browser changes, inspect the Python producer and add an exact
payload fixture. For browser-to-Python changes, inspect the Python inbox and
add a joint callback test.
Run both the npm library and standalone application paths. A green library
build alone does not protect the Python consumer.
The standard TypeScript verification set is:
Run the sibling Python suite for coordinated protocol or asset changes.
sync_frontenddeletes and replaces the packaged frontend directory. Inspectexact paths first and review the generated asset diff separately.
Never run a checker against the root
tsconfig.jsonwithout--build; itcontains project references and no root files. Use
npm run typecheck.Release through conventional commits, Release Please, and the protected npm
environment. Do not publish stable versions from a workstation.
Definition of done for a post-1.0 slice
A slice is complete when:
in proportion to the change.
separately.
maincommit.