salesforce-development
Expert patterns for Salesforce platform development including Lightning Web Components (LWC), Apex triggers and classes, REST/Bulk APIs, Connected Apps, and Salesforce DX with scratch orgs and 2nd ...
threejs-skills
Create 3D scenes, interactive experiences, and visual effects using Three.js. Use when user requests 3D graphics, WebGL experiences, 3D visualizations, animations, or interactive 3D elements.
Full skill instructions
Systematically create high-quality 3D scenes and interactive experiences using Three.js best practices.
Always use the correct CDN version (r128):
import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js";
CRITICAL: Do NOT use example imports like THREE.OrbitControls - they won't work on the CDN.
Every Three.js artifact needs these core components:
// Scene - contains all 3D objects
const scene = new THREE.Scene();
// Camera - defines viewing perspective
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;
// Renderer - draws the scene
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
Use requestAnimationFrame for smooth rendering:
function animate() {
requestAnimationFrame(animate);
// Update object transformations here
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
Start by identifying:
Choose appropriate geometry types:
Basic Shapes:
BoxGeometry - cubes, rectangular prismsSphereGeometry - spheres, planetsCylinderGeometry - cylinders, tubesPlaneGeometry - flat surfaces, ground planesTorusGeometry - donuts, ringsIMPORTANT: Do NOT use CapsuleGeometry (introduced in r142, not available in r128)
Alternatives for capsules:
CylinderGeometry + 2 SphereGeometrySphereGeometry with adjusted parametersChoose materials based on visual needs:
Common Materials:
MeshBasicMaterial - unlit, flat colors (no lighting needed)MeshStandardMaterial - physically-based, realistic (needs lighting)MeshPhongMaterial - shiny surfaces with specular highlightsMeshLambertMaterial - matte surfaces, diffuse reflectionconst material = new THREE.MeshStandardMaterial({
color: 0x00ff00,
metalness: 0.5,
roughness: 0.5,
});
If using lit materials (Standard, Phong, Lambert), add lights:
// Ambient light - general illumination
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// Directional light - like sunlight
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);
Skip lighting if using MeshBasicMaterial - it's unlit by design.
Always add window resize handling:
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
Since THREE.OrbitControls isn't available on CDN, implement custom controls:
let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
renderer.domElement.addEventListener("mousedown", () => {
isDragging = true;
});
renderer.domElement.addEventListener("mouseup", () => {
isDragging = false;
});
renderer.domElement.addEventListener("mousemove", (event) => {
if (isDragging) {
const deltaX = event.clientX - previousMousePosition.x;
const deltaY = event.clientY - previousMousePosition.y;
// Rotate camera around scene
const rotationSpeed = 0.005;
camera.position.x += deltaX * rotationSpeed;
camera.position.y -= deltaY * rotationSpeed;
camera.lookAt(scene.position);
}
previousMousePosition = { x: event.clientX, y: event.clientY };
});
// Zoom with mouse wheel
renderer.domElement.addEventListener("wheel", (event) => {
event.preventDefault();
camera.position.z += event.deltaY * 0.01;
camera.position.z = Math.max(2, Math.min(20, camera.position.z)); // Clamp
});
Detect mouse clicks and hovers on 3D objects:
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const clickableObjects = []; // Array of meshes that can be clicked
// Update mouse position
window.addEventListener("mousemove", (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});
// Detect clicks
window.addEventListener("click", () => {
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(clickableObjects);
if (intersects.length > 0) {
const clickedObject = intersects[0].object;
// Handle click - change color, scale, etc.
clickedObject.material.color.set(0xff0000);
}
});
// Hover effect in animation loop
function animate() {
requestAnimationFrame(animate);
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(clickableObjects);
// Reset all objects
clickableObjects.forEach((obj) => {
obj.scale.set(1, 1, 1);
});
// Highlight hovered object
if (intersects.length > 0) {
intersects[0].object.scale.set(1.2, 1.2, 1.2);
document.body.style.cursor = "pointer";
} else {
document.body.style.cursor = "default";
}
renderer.render(scene, camera);
}
const particlesGeometry = new THREE.BufferGeometry();
const particlesCount = 1000;
const posArray = new Float32Array(particlesCount * 3);
for (let i = 0; i < particlesCount * 3; i++) {
posArray[i] = (Math.random() - 0.5) * 10;
}
particlesGeometry.setAttribute(
"position",
new THREE.BufferAttribute(posArray, 3),
);
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
color: 0xffffff,
});
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particlesMesh);
let mouseX = 0;
let mouseY = 0;
document.addEventListener("mousemove", (event) => {
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
});
function animate() {
requestAnimationFrame(animate);
camera.position.x = mouseX * 2;
camera.position.y = mouseY * 2;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("texture-url.jpg");
const material = new THREE.MeshStandardMaterial({
map: texture,
});
BufferGeometry for custom shapes (more efficient)geometry.dispose();
material.dispose();
texture.dispose();
antialias: true on renderer for smooth edgesTHREE.OrbitControls - not available on CDNTHREE.CapsuleGeometry - requires r142+scene.add()renderer.render() in animation loopUser: "Create an interactive 3D sphere that responds to mouse movement"
SphereGeometry(1, 32, 32) for smooth sphereMeshStandardMaterial for realistic lookBlack screen / Nothing renders:
Poor performance:
Objects not visible:
Shadows:
// Enable shadows on renderer
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Soft shadows
// Light that casts shadows
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
// Configure shadow quality
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 50;
scene.add(directionalLight);
// Objects cast and receive shadows
mesh.castShadow = true;
mesh.receiveShadow = true;
// Ground plane receives shadows
const groundGeometry = new THREE.PlaneGeometry(20, 20);
const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x808080 });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
Environment Maps & Reflections:
// Create environment map from cubemap
const loader = new THREE.CubeTextureLoader();
const envMap = loader.load([
"px.jpg",
"nx.jpg", // positive x, negative x
"py.jpg",
"ny.jpg", // positive y, negative y
"pz.jpg",
"nz.jpg", // positive z, negative z
]);
scene.environment = envMap; // Affects all PBR materials
scene.background = envMap; // Optional: use as skybox
// Or apply to specific materials
const material = new THREE.MeshStandardMaterial({
metalness: 1.0,
roughness: 0.1,
envMap: envMap,
});
Tone Mapping & Output Encoding:
// Improve color accuracy and HDR rendering
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
renderer.outputEncoding = THREE.sRGBEncoding;
// Makes colors more vibrant and realistic
Fog for Depth:
// Linear fog
scene.fog = new THREE.Fog(0xcccccc, 10, 50); // color, near, far
// Or exponential fog (more realistic)
scene.fog = new THREE.FogExp2(0xcccccc, 0.02); // color, density
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
While advanced post-processing may not be available in r128 CDN, basic effects can be achieved with shaders and render targets.
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
group.rotation.y = Math.PI / 4;
scene.add(group);
Three.js artifacts require systematic setup:
Follow these patterns for reliable, performant 3D experiences.
While this skill focuses on CDN-based Three.js (r128) for artifact compatibility, here's what you'd do in production environments:
// In production with npm/vite/webpack:
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
Benefits:
// Smooth timeline-based animations
import gsap from "gsap";
// Instead of manual animation loops:
gsap.to(mesh.position, {
x: 5,
duration: 2,
ease: "power2.inOut",
});
// Complex sequences:
const timeline = gsap.timeline();
timeline
.to(mesh.rotation, { y: Math.PI * 2, duration: 2 })
.to(mesh.scale, { x: 2, y: 2, z: 2, duration: 1 }, "-=1");
Why GSAP:
// Sync 3D animations with page scroll
let scrollY = window.scrollY;
window.addEventListener("scroll", () => {
scrollY = window.scrollY;
});
function animate() {
requestAnimationFrame(animate);
// Rotate based on scroll position
mesh.rotation.y = scrollY * 0.001;
// Move camera through scene
camera.position.y = -(scrollY / window.innerHeight) * 10;
renderer.render(scene, camera);
}
Advanced scroll libraries:
// Level of Detail (LOD)
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 0); // Close up
lod.addLevel(mediumDetailMesh, 10); // Medium distance
lod.addLevel(lowDetailMesh, 50); // Far away
scene.add(lod);
// Instanced meshes for many identical objects
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial();
const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000);
// Set transforms for each instance
const matrix = new THREE.Matrix4();
for (let i = 0; i < 1000; i++) {
matrix.setPosition(
Math.random() * 100,
Math.random() * 100,
Math.random() * 100,
);
instancedMesh.setMatrixAt(i, matrix);
}
// In production, load 3D models:
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
const loader = new GLTFLoader();
loader.load("model.gltf", (gltf) => {
scene.add(gltf.scene);
// Traverse and setup materials
gltf.scene.traverse((child) => {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
});
CDN Approach (Current Skill):
Production Build Approach:
Three.js (latest) + Vite/Webpack
├── GSAP (animations)
├── React Three Fiber (optional - React integration)
├── Drei (helper components)
├── Leva (debug GUI)
└── Post-processing effects
This skill provides CDN-compatible foundations. In production, you'd layer on these modern tools for professional results.
Expert patterns for Salesforce platform development including Lightning Web Components (LWC), Apex triggers and classes, REST/Bulk APIs, Connected Apps, and Salesforce DX with scratch orgs and 2nd ...
Instrument applications with Azure Monitor and OpenTelemetry for JavaScript (@azure/monitor-opentelemetry). Use when adding distributed tracing, metrics, and logs to Node.js applications with Appli...
Create and optimize popups, modals, overlays, slide-ins, and banners to increase conversions without harming user experience or brand trust.
Configure mutual TLS (mTLS) for zero-trust service-to-service communication. Use when implementing zero-trust networking, certificate management, or securing internal service communication.
Build Azure Cosmos DB NoSQL services with Python/FastAPI following production-grade patterns. Use when implementing database client setup with dual auth (DefaultAzureCredential + emulator), service...
Terraform infrastructure as code workflow for provisioning cloud resources, creating reusable modules, and managing infrastructure at scale.
Automate OneDrive file management, search, uploads, downloads, sharing, permissions, and folder operations via Rube MCP (Composio). Always search tools first for current schemas.
Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory...
Handle errors as values using fp-ts Either and TaskEither for cleaner, more predictable TypeScript code. Use when implementing error handling patterns with fp-ts.
You are a code migration expert specializing in transitioning codebases between frameworks, languages, versions, and platforms. Generate comprehensive migration plans, automated migration scripts, and
Real-time, bidirectional voice conversations with AI assistants using WebSocket technology.
A hybrid memory system that provides persistent, searchable knowledge management for AI agents (Architecture, Patterns, Decisions).
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience