Vectojs three
Agent skills for building, optimizing, embedding, and exporting VectoJS projects with Codex, Claude Code, Cursor, and GitHub Copilot.
npx -y skills add vectojs/vectojs-skills --skill vectojs-threeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when embedding VectoJS in Three.js or WebXR with @vectojs/three, ThreeAdapter, canvas textures, raycaster input, UV-to-scene event routing, hover/wheel behavior, or disposal.
SKILL.md
4.1 KB, as published. Nobody here has run it
VectoJS Three
Use this skill to place a live VectoJS 2D interface onto a Three.js texture and route 3D pointer input back into the VectoJS scene.
Integration workflow
- Install
@vectojs/core,@vectojs/three,three, and@vectojs/uiif using UI components. - Create one
ThreeAdapterper VectoJS panel texture. - Add VectoJS entities to
adapter.vectoScene, then start the inner scene. - Add
adapter.meshor the adapter texture/material to the host Three.js scene. - In the host pointer/wheel loop, raycast against the adapter mesh and call
adapter.updateIntersection(...). - Call
adapter.dispose()when removing the panel.
Read references/three-recipes.md for snippets.
Constraints
- The default output is a flat textured plane, not DOM rendered in 3D.
- VectoJS logical hit-testing remains 2D even when the mesh is transformed in world space.
- The host application owns the camera, renderer, controls, XR session, raycaster, and occlusion rules.
- Raycast UVs should map to the adapter’s logical
width/height; do not use backing-store size for layout math. - Texture resolution affects sharpness and upload cost. Choose dimensions for the viewing distance.
Common mistakes
| Mistake | Correction |
|---|---|
| Adding an offscreen adapter canvas to the DOM | Add adapter.mesh to Three.js; the canvas backs the texture. |
Forgetting to call updateIntersection | Route host raycaster events into the adapter each pointer/wheel event. |
| Dispatching by screen coordinates | Use raycast UVs through ThreeAdapter. |
| Keeping disposed textures alive | Call adapter.dispose() and remove host references. |
| Expecting full DOM a11y inside XR | Treat the 3D panel as canvas texture; provide host-level semantics where needed. |
Version and backend gotchas (source-verified)
- three ≤ 0.1.3:
ThreeRenderer.flush()performed a full GL render, and the Scene flushes around every non-batched node — frame cost grew O(N²) in entity count. three 0.1.4 renders once per frame via thepresent()hook; upgrade before profiling anything else. - Native input inside a texture is limited. The adapter's canvas is
offscreen, so the Scene's projected a11y elements are never connected to the
document;
updateIntersectionfalls back to VectoJS's own event dispatch. Buttons/hover/wheel work; full native IME/text editing does not — keep text entry outside the 3D panel or accept simplified input. stroke()line width is effectively 1px on most platforms (LineBasicMaterial.linewidthis a known WebGL limitation). Draw thick lines as filled shapes instead.- Texture caches (three 0.1.7+): both
fillTextanddrawImagetextures are cached with a 256-entry LRU (text keyed by font|color|text). Before 0.1.7drawImageallocated a texture per call per frame, so reusing a source canvas mattered more; it is still good practice for very large images. - GPU context loss + runtime DPR (three 0.1.7+):
ThreeRendererrecovers on its own.webglcontextlostispreventDefault()-ed (required, or the browser never fires the restore event) and flipsisContextLost(), which makespresent()a no-op while lost;webglcontextrestoredre-applies pixel ratio and size (a restore can land on a different display) and forces a repaint. A(resolution: Ndppx)media query re-appliessetPixelRatiowhen DPR changes at runtime (monitor move, browser zoom) and re-arms itself. All of it is guarded for SSR/OffscreenCanvas and torn down indispose(). Do not add your own context-loss listener — you would fight the built-in recovery.