mrdoob/three.js
JavaScript 3D Library.
Mixed signals — read the receipts
- ✓Last commit today
- ✓5 active contributors
- ✓MIT licensed
- ✓CI configured
- ⚠Small team — 5 top contributors
- ⚠Concentrated ownership — top contributor handles 56% of commits
- ⚠No test directory detected
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Embed this verdict
[](https://repopilot.app/r/mrdoob/three.js)Paste into your README — the badge live-updates from the latest cached analysis.
Onboarding doc
Onboarding: mrdoob/three.js
Generated by RepoPilot · 2026-05-04 · Source
Verdict
WAIT — Mixed signals — read the receipts
- Last commit today
- 5 active contributors
- MIT licensed
- CI configured
- ⚠ Small team — 5 top contributors
- ⚠ Concentrated ownership — top contributor handles 56% of commits
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
TL;DR
three.js is a JavaScript 3D library that abstracts WebGL and WebGPU rendering into a high-level scene graph API. It lets developers create 3D scenes with cameras, geometries, materials, lights, and animations without writing raw shader/GPU code. The repo ships multiple build targets in build/ — including three.webgpu.js for WebGPU, three.tsl.js for the Three.js Shading Language node system, and three.cjs for CommonJS consumers. The repo is a monolith: src/ holds the core library split into subdirectories (cameras/, geometries/, materials/, renderers/, nodes/ for TSL), examples/ holds standalone HTML demos plus addons/ for optional loaders and controls, and build/ contains pre-bundled distribution files generated from src/. The devtools/ folder is a standalone browser extension for scene inspection.
Who it's for
Web developers and creative coders building interactive 3D experiences in the browser — games, data visualizations, product configurators, CAD tools, and generative art. Contributors range from graphics engineers adding WebGPU backend features to addon authors writing loaders (GLTFLoader, etc.) and examples under the examples/ directory.
Maturity & risk
three.js is one of the most mature JavaScript 3D libraries in existence, with over a decade of active development, 100k+ GitHub stars, and continuous weekly releases tracked in Releases. CI runs via .github/workflows/ci.yml including CodeQL security scanning. It is unambiguously production-ready and used in thousands of commercial products.
The library has virtually no external runtime dependencies — the core src/ is self-contained JavaScript. The primary risk is API churn: the migration guide (wiki/Migration-Guide) documents frequent breaking changes each release (e.g., renderer API shifts for WebGPU). The WebGPU/TSL/node-material system (build/three.webgpu.nodes.js) is still stabilizing and not yet considered API-stable.
Active areas of work
Active development is focused on the WebGPU renderer and the TSL (Three.js Shading Language) node-based material system, evidenced by dedicated build artifacts (build/three.tsl.js, build/three.webgpu.nodes.js) and the docs/TSL.md documentation file. The renovate.json config keeps dev tooling dependencies auto-updated, and .github/workflows/read-size.yml / report-size.yml track bundle size regressions per PR.
Get running
git clone --depth=1 https://github.com/mrdoob/three.js.git cd three.js npm install npm start
Daily commands: npm start # launches a local dev server serving examples/ at http://localhost:8080 npm run build # regenerates all files in build/ npm test # runs the CI test suite
Map of the codebase
build/three.module.js— The primary ESM build output that consumers import; understanding its structure reveals how all core classes (Scene, Camera, Renderer, Geometry, Material) are composed and exported.build/three.webgpu.js— The WebGPU renderer build entry point, representing the next-generation rendering pipeline and TSL node system that is the primary active development focus.build/three.core.js— The minimal core build exposing the fundamental abstractions (Object3D, BufferGeometry, Material, etc.) that every other subsystem depends on.build/three.tsl.js— The Three Shading Language (TSL) node-based shader system build; critical for understanding how materials and shaders are authored in the modern rendering pipeline..github/CONTRIBUTING.md— Defines contribution conventions, coding standards, and PR workflow that every contributor must follow to get changes merged.docs/TSL.md— The authoritative documentation for the Three Shading Language, the central abstraction for cross-backend (WebGL/WebGPU) shader authoring.build/three.cjs— The CommonJS build entry point used by Node.js consumers and test environments; understanding it clarifies module boundary decisions.
How to make changes
Add a new geometry type
- Create a new class extending BufferGeometry in src/geometries/, following the naming convention (e.g. MyShapeGeometry.js). Define constructor parameters and call super(); then use setAttribute() with BufferAttribute for position, normal, uv indices. (
build/three.core.js) - Export the new geometry class from the main src/Three.js barrel file so it is included in all builds. (
build/three.module.js) - Add a documentation page describing constructor parameters, inherited properties, and usage examples following the existing pattern. (
docs/pages/ArcCurve.html)
Add a new TSL (Three Shading Language) node
- Create a new Node subclass in src/nodes/, extending the appropriate base (e.g. TempNode, Node) and implementing generate(builder) to emit GLSL/WGSL code. Follow existing nodes like ArrayElementNode as reference. (
docs/pages/ArrayElementNode.html) - Register the node with the NodeBuilder registry and export it from the nodes barrel so it is included in the TSL and WebGPU builds. (
build/three.tsl.js) - Add the WebGPU/WebGL backend code generation path inside the relevant backend compiler, ensuring WGSL and GLSL output are both handled. (
build/three.webgpu.nodes.js) - Add a documentation page for the new node describing inputs, outputs, and shader behavior. (
docs/pages/AONode.html)
Add a new post-processing pass node
- Create a new PassNode subclass in src/renderers/common/nodes/ that reads from render targets, applies effects via TSL node graph, and writes to output. Reference AfterImageNode or AnamorphicNode. (
docs/pages/AfterImageNode.html) - Expose the pass through the TSL build so it can be used via the node-based post-processing pipeline. (
build/three.tsl.js) - Add documentation page describing parameters, usage with PostProcessing, and any performance considerations. (
docs/pages/AnamorphicNode.html)
Add a new loader for a 3D file format
- Create a new Loader subclass in src/loaders/ (or examples/jsm/loaders/) extending Loader and implementing load(url, onLoad, onProgress, onError). Parse the format and populate a BufferGeometry or Group. (
docs/pages/AMFLoader.html) - Register the MIME type and file extension in the LoaderUtils helpers if needed, and add any binary parsing using DataView or similar. (
build/three.module.js) - Add a documentation page following the AMFLoader pattern, listing constructor, methods, and usage examples. (
docs/pages/AMFLoader.html)
Why these technologies
- JavaScript / ESModules — Maximizes browser compatibility with zero runtime dependencies; ESM enables tree-shaking so consumers only bundle what they use, keeping download size minimal.
- WebGPU API — Next-generation graphics API offering explicit pipeline control, compute shaders, and better multi-threading — enabling features impossible or impractical in WebGL (e.g. real-time ray tracing, GPU-driven rendering).
- TSL (Three Shading Language) — Abstraction layer over GLSL/WGSL allowing a single material definition to target both WebGL and WebGPU backends, future-proofing shader code against backend changes.
- Node-based shader graph — Compositional shader authoring without string concatenation; nodes can be cached, reused, and inspected programmatically, enabling editor tooling and runtime optimization.
Trade-offs already made
-
Maintain both WebGL and WebGPU backends simultaneously
- Why: WebGPU is not universally available; WebGL is still required for broad device coverage including mobile and Safari.
- Consequence: Dual code paths increase maintenance burden; TSL node system adds abstraction complexity to keep backends in sync.
-
Ship compiled build files in the repository
- Why: Allows CDN usage without a build step and enables version pinning for consumers not using npm.
- Consequence: Repo size is larger; build files can conflict in PRs; contributors must remember to rebuild.
-
No runtime dependency on external libraries
- Why: Keeps bundle size minimal and eliminates supply-chain risk.
- Consequence: Common utilities (math, parsing) must be reimplemented internally rather than reused from ecosystem packages.
-
Node/TSL system replaces legacy ShaderMaterial approach
- Why: Enables cross-backend shader portability and programmatic composition.
- Consequence: Learning curve for users familiar with raw GLSL; legacy ShaderMaterial remains for backward compatibility, creating two parallel material authoring paradigms.
Non-goals (don't propose these)
- Server-side (Node.js) rendering without a headless GPU context
- Physics simulation (deferred to third-party libraries like Ammo.js/Rapier)
- Audio spatialization beyond basic positional audio wrappers
- UI / 2D rendering (HTML Canvas 2D, DOM, SVG are out-of-scope for the core renderer)
- Asset pipeline tooling (baking, compression — handled by external tools like gltf-pipeline)
Traps & gotchas
- The examples/jsm/ addons are NOT included in the core build/three.module.js — they must be imported separately from the examples/jsm/ path or via the three/addons npm subpath. 2) The WebGPU renderer requires a browser/environment with WebGPU support (Chrome 113+, no Firefox stable as of 2024). 3) When building locally, the build/ artifacts are committed to the repo — do NOT manually edit them; regenerate via npm run build. 4) The devtools extension requires loading as an unpacked extension from the devtools/ directory; it is not on the Chrome Web Store in the repo's own builds.
Architecture
Concepts to learn
- Scene Graph — three.js is organized as a hierarchical scene graph (Object3D parent/child tree); understanding this is prerequisite to manipulating transforms, visibility, and render order.
- WebGPU API — The new rendering backend in build/three.webgpu.js targets the WebGPU API, which replaces WebGL with an explicit, lower-overhead GPU interface — critical for contributors working in src/renderers/webgpu/.
- GLSL Shader Programs — WebGL materials compile to GLSL; understanding vertex and fragment shaders is essential for working on src/renderers/webgl/WebGLProgram.js and custom ShaderMaterial.
- Node-based Shader Graph — The TSL system in src/nodes/ represents shaders as composable JavaScript node graphs (similar to Blender's shader nodes), compiling to both GLSL and WGSL — a fundamentally different mental model from raw shader strings.
- Physically Based Rendering (PBR) — MeshStandardMaterial and MeshPhysicalMaterial implement PBR workflows (metalness/roughness) — understanding the underlying lighting model is needed to write correct custom materials.
- UVs and Texture Mapping — Geometry UV attributes and texture coordinate systems are central to how materials display images in three.js; misunderstanding UV space causes common visual bugs in examples and custom geometries.
- glTF 2.0 Format — glTF is the primary 3D asset interchange format supported by examples/jsm/loaders/GLTFLoader.js; understanding its binary/JSON structure is essential for working on asset loading and extensions.
Related repos
BabylonJS/Babylon.js— Direct alternative 3D WebGL/WebGPU library for the browser, more enterprise-focused with TypeScript-first codebase.pixijs/pixijs— Alternative WebGL renderer but focused on 2D; shares the audience of web developers who want GPU-accelerated graphics without raw WebGL.pmndrs/react-three-fiber— The dominant React wrapper around three.js — most three.js users in React apps go through this ecosystem.mrdoob/three.js— N/A — this IS the repo.gkjohnson/three-mesh-bvh— Popular companion library for accelerated raycasting and spatial queries on three.js geometries, commonly used alongside the core.
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for TSL (Three Shading Language) node system
The repo has a dedicated docs/TSL.md and build artifacts like build/three.tsl.js and build/three.tsl.min.js, indicating TSL is a significant feature. However, looking at the file structure, there are no corresponding unit test files for TSL nodes (e.g., AONode, AmbientLightDataNode, AmbientLightNode, AfterImageNode). Adding unit tests for these node types would improve stability and catch regressions as the WebGPU/TSL pipeline matures.
- [ ] Audit existing test coverage by examining the test/ directory for any TSL-related test files
- [ ] Add unit tests for core node types found in docs/pages/ such as AONode.html, AmbientLightNode.html, AmbientLightDataNode.html, and AfterImageNode.html
- [ ] Write tests that instantiate each node, verify constructor parameters, check .nodeType and .nodeFunction properties, and assert correct shader string output using the existing node compiler
- [ ] Reference build/three.tsl.js as the module under test and ensure tests run as part of the existing CI workflow in .github/workflows/ci.yml
- [ ] Submit PR with a test file per major node category (e.g., test/unit/nodes/lighting/AmbientLightNode.tests.js)
Add a GitHub Actions workflow to validate build artifact sizes against thresholds
The repo already has .github/workflows/read-size.yml and .github/workflows/report-size.yml for tracking bundle sizes, but there is no workflow that fails the CI build when a PR causes a significant size regression (e.g., >5% increase) in critical bundles like build/three.module.min.js, build/three.webgpu.min.js, or build/three.tsl.min.js. Adding a size-gate workflow would prevent accidental size bloat from being merged.
- [ ] Inspect .github/workflows/read-size.yml and report-size.yml to understand the current size-reporting mechanism and what data is already collected
- [ ] Create a new file .github/workflows/size-limit.yml that installs size-limit or uses a comparable action (e.g., andresz1/size-limit-action)
- [ ] Configure thresholds for each minified build artifact: build/three.module.min.js, build/three.webgpu.min.js, build/three.core.min.js, build/three.tsl.min.js
- [ ] Set the workflow to trigger on pull_request events and post a comment on the PR showing before/after sizes with a failure status if any threshold is exceeded
- [ ] Document the thresholds and how to update them in .github/CONTRIBUTING.md
Add documentation pages for WebGPU-specific renderer features missing from docs/pages/
The file structure shows build artifacts build/three.webgpu.js, build/three.webgpu.nodes.js, and build/three.tsl.js, and there is a docs/TSL.md, but scanning the docs/pages/ listing reveals no dedicated HTML documentation pages for the WebGPU renderer itself (e.g., WebGPURenderer, WebGPUBackend, or StorageBufferNode). In contrast, older features like AfterimagePass.html have full docs pages. Adding structured docs pages for these new WebGPU APIs aligns the docs with the build outputs and helps adopters migrate.
- [ ] Identify which WebGPU-related classes are exported in build/three.webgpu.js and build/three.webgpu.nodes.js but lack a corresponding file in docs/pages/
- [ ] Create docs/pages/WebGPURenderer.html and docs/pages/WebGPURenderer.html.md following the exact same structure as existing pages such as docs/pages/AmbientLight.html and docs/pages/AmbientLight.html.
Good first issues
- Add JSDoc/TypeScript declaration coverage to src/nodes/ — the TSL node system is the newest subsystem and many node classes lack inline documentation compared to the older src/geometries/ files. 2) Write unit tests for specific math utilities in src/math/ (e.g., Frustum.js, Sphere.js) — the CI workflow exists but math utility test coverage is historically sparse. 3) Improve the devtools/panel/panel.js to display WebGPU-specific resource info (bind groups, pipelines) since the panel was built primarily for WebGL scenes and the WebGPU backend is now a first-class target.
Top contributors
- @Mugen87 — 42 commits
- @sunag — 11 commits
- @mrdoob — 9 commits
- @RenaudRohlinger — 7 commits
- @renovate[bot] — 6 commits
Recent commits
f85aef5— WebGPURenderer: Introduce descriptor classes and caching. (#33525) (Mugen87)733d924— Examples: Added GUI to Furnace Tests (#33523) (WestLangley)6d97cbf— BufferGeometry: Fix attribute count mismatch incomputeVertexNormals()andcomputeTangents(). (#33520) (Mugen87)be8a9e8— WebGPURenderer: Support rendering to texture arrays. (#33507) (cabanier)831b0c1— chore(deps): update github/codeql-action digest to e46ed2c (#33521) (renovate[bot])e5b8682— chore(deps): update devdependencies (non-major) (#33522) (renovate[bot])b5aef65— TSL: Add support fortextureGatherandtextureGatherCompare(#33475) (shotamatsuda)967ce5c— Examples: Addwebgpu_furnace_test.html(#33516) (WestLangley)7a76854— TSL: Cache function nodes per renderer's backend (#33517) (sunag)aa22216— BezierInterpolant: RefactorinTangents/outTangents. (#33515) (Mugen87)
Security observations
- Medium · Potential XSS via Dynamic HTML Injection in Documentation Pages —
docs/index.html, devtools/panel/panel.html, devtools/panel/panel.js. The docs/ directory contains many .html and .html.md files that are served as documentation pages. If any of these pages dynamically render user-controlled content (e.g., URL parameters, query strings) without proper sanitization, they could be vulnerable to reflected XSS. The devtools/panel/panel.html and devtools/panel/panel.js files in particular may render scene/object data from the inspected page into the DevTools panel DOM without sanitization. Fix: Ensure all dynamic content inserted into the DOM is properly escaped or sanitized. Use textContent instead of innerHTML where possible. Implement a strict Content Security Policy (CSP) header on documentation and DevTools pages. - Medium · DevTools Extension Content Script Injection Risk —
devtools/content-script.js, devtools/bridge.js, devtools/panel/panel.js. The devtools/content-script.js and devtools/bridge.js files communicate between the browser extension and the inspected page context. If these scripts relay arbitrary data from the inspected page DOM/JS context back to the DevTools panel without sanitization, malicious page content could execute code or exfiltrate data within the extension's privileged context. Fix: Strictly validate and sanitize all messages passed between content scripts and the DevTools panel. Use a well-defined message schema and reject any unexpected message formats. Avoid using eval() or innerHTML with data sourced from page context. - Medium · Missing Content Security Policy (CSP) in DevTools Extension Manifest —
devtools/manifest.json. The devtools/manifest.json likely does not define a strict Content Security Policy for the extension pages (devtools.html, panel.html, index.html). Without a CSP, these pages are more susceptible to XSS attacks if user-controlled data is reflected into the DOM. Fix: Add a strict Content Security Policy to the extension manifest, e.g.: 'content_security_policy': 'script-src 'self'; object-src 'self''. For Manifest V3 extensions, ensure the CSP is defined appropriately per the MV3 specification. - Low · Sensitive Email Address Hardcoded in SECURITY.md —
SECURITY.md. The SECURITY.md file contains a hardcoded email address (hello@mrdoob.com) as the security disclosure contact. While this is intentional for a public security policy, it exposes the maintainer's email to scrapers and may result in spam or phishing attempts targeting the project maintainer. Fix: Consider using a dedicated security disclosure email address or a platform-based private vulnerability reporting mechanism (e.g., GitHub's built-in private vulnerability reporting feature) rather than a personal email address. - Low · No Subresource Integrity (SRI) Checks on External Resources in Documentation —
docs/index.html. The docs/index.html and associated documentation pages may load external JavaScript or CSS resources without Subresource Integrity (SRI) hashes. If an external CDN is compromised, malicious scripts could be served to users visiting the documentation. Fix: Add integrity and crossorigin attributes to all externally loaded scripts and stylesheets. Example: <script src='...' integrity='sha384-...' crossorigin='anonymous'></script>. - Low · No Dependency Lock File Visible for Vulnerability Auditing —
package.json (not shown), build pipeline. The provided file structure does not include a package-lock.json or yarn.lock file at the root level in the partial listing, making it difficult to perform precise dependency vulnerability auditing. Unpinned dependencies in package.json can result in pulling in vulnerable transitive dependencies during CI/CD builds. Fix: Ensure a lock file (package-lock.json or yarn.lock) is committed to the repository and regularly audited using 'npm audit' or equivalent tools. Pin all dependencies to specific versions where possible. The existing .github/workflows/ci.yml should include a dependency audit step. - Low · Build Artifacts Committed to Repository —
undefined. The build/ directory contains pre-built distribution files (three.cjs, three.module.js, three.webgpu.js, etc.) committed directly to the repository. If the build pipeline is ever compromised or if these files are manually edited, mal Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.