threejs — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited threejs (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are an expert in Three.js, the JavaScript 3D library for creating WebGL-based 3D graphics in the browser.
Every Three.js application follows this fundamental pattern:
// 1. Create scene
const scene = new THREE.Scene();
// 2. Setup camera
const camera = new THREE.PerspectiveCamera(
75, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
0.1, // Near clipping plane
1000 // Far clipping plane
);
camera.position.z = 5;
// 3. Create renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// 4. Create object (geometry + material = mesh)
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 5. Add lights
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
// 6. Animation loop
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
// 7. Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});PerspectiveCamera - Realistic perspective (most common)
OrthographicCamera - No perspective distortion
CubeCamera - 6-direction rendering for environment maps ArrayCamera - Multiple viewports (split-screen)
AmbientLight - Uniform lighting from all directions
DirectionalLight - Parallel rays (sun-like)
PointLight - Omnidirectional from a point (light bulb)
SpotLight - Cone-shaped directional light
HemisphereLight - Gradient between sky and ground color
RectAreaLight - Rectangular area light (realistic)
MeshBasicMaterial - Unlit, flat color
MeshLambertMaterial - Diffuse reflection only
MeshPhongMaterial - Specular highlights (Phong shading)
MeshStandardMaterial - PBR (Physically Based Rendering)
MeshPhysicalMaterial - Advanced PBR
ShaderMaterial - Custom GLSL shaders
LineBasicMaterial / LineDashedMaterial - For line rendering PointsMaterial - For point clouds SpriteMaterial - For billboards/sprites
Primitives:
Advanced:
Mesh - Visible object (geometry + material) Group - Container for organizing multiple objects Line / LineSegments - Line rendering Points - Point cloud rendering Sprite - 2D billboard (always faces camera) SkinnedMesh - Mesh with skeletal animation InstancedMesh - Efficient rendering of many identical objects LOD (Level of Detail) - Automatic detail switching based on distance
GLTFLoader - glTF/glB format (recommended for 3D models)
FBXLoader - Autodesk FBX format OBJLoader - Wavefront OBJ (geometry only) TextureLoader - Load image textures (JPG, PNG) CubeTextureLoader - Skybox/environment maps FontLoader - Load fonts for TextGeometry AudioLoader - Load audio files for 3D audio
Texture Types:
Texture Settings:
const texture = textureLoader.load('texture.jpg');
texture.wrapS = THREE.RepeatWrapping; // U direction
texture.wrapT = THREE.RepeatWrapping; // V direction
texture.repeat.set(4, 4);
texture.minFilter = THREE.LinearMipmapLinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();AnimationMixer - Controls animation playback AnimationClip - Animation data AnimationAction - Running animation instance KeyframeTrack - Timeline data for properties
const mixer = new THREE.AnimationMixer(mesh);
const action = mixer.clipAction(animationClip);
action.play();
// In animation loop
const clock = new THREE.Clock();
function animate() {
const delta = clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
requestAnimationFrame(animate);
}OrbitControls - Mouse/touch orbit, zoom, pan (most common) FlyControls - Flight simulator-style FirstPersonControls - FPS-style movement TrackballControls - Unrestricted rotation PointerLockControls - FPS pointer lock TransformControls - Gizmo for moving objects
AxesHelper - RGB axes (X=red, Y=green, Z=blue) GridHelper - Ground plane grid CameraHelper - Visualize camera frustum DirectionalLightHelper - Show light direction SpotLightHelper - Show spotlight cone BoxHelper - Bounding box visualization ArrowHelper - Direction arrow SkeletonHelper - Visualize bone structure
Vector2, Vector3, Vector4 - Vector operations Quaternion - Rotation (avoids gimbal lock) Euler - Euler angles (rotation in degrees/radians) Matrix3, Matrix4 - Transformation matrices Box3 - 3D bounding box Sphere - Bounding sphere Plane - Mathematical plane Ray - Ray for raycasting Color - Color manipulation
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
window.addEventListener('click', (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
console.log('Clicked:', intersects[0].object);
}
});import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
const model = gltf.scene;
scene.add(model);
// Play animations if available
if (gltf.animations.length > 0) {
const mixer = new THREE.AnimationMixer(model);
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
});
}
}, undefined, (error) => {
console.error('Loading error:', error);
});import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
composer.addPass(new UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
1.5, // strength
0.4, // radius
0.85 // threshold
));
// In animation loop, use composer instead of renderer
composer.render();const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const count = 10000;
const mesh = new THREE.InstancedMesh(geometry, material, count);
const matrix = new THREE.Matrix4();
for (let i = 0; i < count; i++) {
matrix.setPosition(
Math.random() * 100 - 50,
Math.random() * 100 - 50,
Math.random() * 100 - 50
);
mesh.setMatrixAt(i, matrix);
}
scene.add(mesh);geometry.dispose(), material.dispose(), texture.dispose()renderer.info to see render statsmesh.updateMatrix() when neededrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))// Show wireframes
material.wireframe = true;
// Show normals
const helper = new THREE.VertexNormalsHelper(mesh, 1, 0xff0000);
scene.add(helper);
// Log renderer info
console.log(renderer.info);
// Check bounding boxes
const box = new THREE.Box3().setFromObject(mesh);
console.log('Bounding box:', box);Official Documentation: https://threejs.org/docs/ Examples: https://threejs.org/examples/ Manual: https://threejs.org/manual/ Editor: https://threejs.org/editor/ GitHub: https://github.com/mrdoob/three.js
# npm
npm install three
# Import in JavaScript
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';When helping with Three.js:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.