fix: restore Three.js skill metadata and sync generated files

This commit is contained in:
sck_0
2026-02-13 15:08:22 +01:00
parent 5ac9d8b9b7
commit 768290ebd1
5 changed files with 86 additions and 66 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -570,7 +570,7 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `subagent-driven-development` | Use when executing implementation plans with independent tasks in the current session | subagent, driven | subagent, driven, development, executing, plans, independent, tasks, current, session |
| `superpowers-lab` | Lab environment for Claude superpowers | superpowers, lab | superpowers, lab, environment, claude |
| `theme-factory` | Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors... | theme, factory | theme, factory, toolkit, styling, artifacts, these, slides, docs, reportings, html, landing, pages |
| `threejs-skills` | Three.js skills for creating 3D elements and interactive experiences | threejs, skills | threejs, skills, three, js, creating, 3d, elements, interactive, experiences |
| `threejs-skills` | Create 3D scenes, interactive experiences, and visual effects using Three.js. Use when user requests 3D graphics, WebGL experiences, 3D visualizations, anima... | threejs, skills | threejs, skills, 3d, scenes, interactive, experiences, visual, effects, three, js, user, requests |
| `turborepo-caching` | Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing d... | turborepo, caching | turborepo, caching, configure, efficient, monorepo, local, remote, setting, up, optimizing, pipelines, implementing |
| `tutorial-engineer` | Creates step-by-step tutorials and educational content from code. Transforms complex concepts into progressive learning experiences with hands-on examples. U... | tutorial | tutorial, engineer, creates, step, tutorials, educational, content, code, transforms, complex, concepts, progressive |
| `ui-skills` | Opinionated, evolving constraints to guide agents when building interfaces | ui, skills | ui, skills, opinionated, evolving, constraints, agents, building, interfaces |

View File

@@ -19332,7 +19332,7 @@
{
"id": "threejs-skills",
"name": "threejs-skills",
"description": "Three.js skills for creating 3D elements and interactive experiences",
"description": "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.",
"category": "general",
"tags": [
"threejs",
@@ -19341,13 +19341,16 @@
"triggers": [
"threejs",
"skills",
"3d",
"scenes",
"interactive",
"experiences",
"visual",
"effects",
"three",
"js",
"creating",
"3d",
"elements",
"interactive",
"experiences"
"user",
"requests"
],
"path": "skills/threejs-skills/SKILL.md"
},

View File

@@ -1,6 +1,8 @@
---
name: threejs-skills
description: 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.
source: https://github.com/CloudAI-X/threejs-skills
risk: safe
---
# Three.js Skills
@@ -23,7 +25,7 @@ Systematically create high-quality 3D scenes and interactive experiences using T
Always use the correct CDN version (r128):
```javascript
import * as THREE from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js';
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.
@@ -38,10 +40,10 @@ const scene = new THREE.Scene();
// Camera - defines viewing perspective
const camera = new THREE.PerspectiveCamera(
75, // Field of view
75, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
0.1, // Near clipping plane
1000 // Far clipping plane
0.1, // Near clipping plane
1000, // Far clipping plane
);
camera.position.z = 5;
@@ -58,11 +60,11 @@ Use requestAnimationFrame for smooth rendering:
```javascript
function animate() {
requestAnimationFrame(animate);
// Update object transformations here
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
@@ -84,6 +86,7 @@ Start by identifying:
Choose appropriate geometry types:
**Basic Shapes:**
- `BoxGeometry` - cubes, rectangular prisms
- `SphereGeometry` - spheres, planets
- `CylinderGeometry` - cylinders, tubes
@@ -93,6 +96,7 @@ Choose appropriate geometry types:
**IMPORTANT**: Do NOT use `CapsuleGeometry` (introduced in r142, not available in r128)
**Alternatives for capsules:**
- Combine `CylinderGeometry` + 2 `SphereGeometry`
- Use `SphereGeometry` with adjusted parameters
- Create custom geometry with vertices
@@ -102,6 +106,7 @@ Choose appropriate geometry types:
Choose 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 highlights
@@ -111,7 +116,7 @@ Choose materials based on visual needs:
const material = new THREE.MeshStandardMaterial({
color: 0x00ff00,
metalness: 0.5,
roughness: 0.5
roughness: 0.5,
});
```
@@ -137,7 +142,7 @@ scene.add(directionalLight);
Always add window resize handling:
```javascript
window.addEventListener('resize', () => {
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
@@ -165,31 +170,31 @@ Since `THREE.OrbitControls` isn't available on CDN, implement custom controls:
let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
renderer.domElement.addEventListener('mousedown', () => {
renderer.domElement.addEventListener("mousedown", () => {
isDragging = true;
});
renderer.domElement.addEventListener('mouseup', () => {
renderer.domElement.addEventListener("mouseup", () => {
isDragging = false;
});
renderer.domElement.addEventListener('mousemove', (event) => {
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) => {
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
@@ -206,16 +211,16 @@ const mouse = new THREE.Vector2();
const clickableObjects = []; // Array of meshes that can be clicked
// Update mouse position
window.addEventListener('mousemove', (event) => {
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', () => {
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.
@@ -226,23 +231,23 @@ window.addEventListener('click', () => {
// Hover effect in animation loop
function animate() {
requestAnimationFrame(animate);
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(clickableObjects);
// Reset all objects
clickableObjects.forEach(obj => {
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';
document.body.style.cursor = "pointer";
} else {
document.body.style.cursor = 'default';
document.body.style.cursor = "default";
}
renderer.render(scene, camera);
}
```
@@ -259,13 +264,13 @@ for (let i = 0; i < particlesCount * 3; i++) {
}
particlesGeometry.setAttribute(
'position',
new THREE.BufferAttribute(posArray, 3)
"position",
new THREE.BufferAttribute(posArray, 3),
);
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
color: 0xffffff
color: 0xffffff,
});
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);
@@ -278,7 +283,7 @@ scene.add(particlesMesh);
let mouseX = 0;
let mouseY = 0;
document.addEventListener('mousemove', (event) => {
document.addEventListener("mousemove", (event) => {
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
});
@@ -296,10 +301,10 @@ function animate() {
```javascript
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('texture-url.jpg');
const texture = textureLoader.load("texture-url.jpg");
const material = new THREE.MeshStandardMaterial({
map: texture
map: texture,
});
```
@@ -356,18 +361,21 @@ User: "Create an interactive 3D sphere that responds to mouse movement"
## Troubleshooting
**Black screen / Nothing renders:**
- Check if objects added to scene
- Verify camera position isn't inside objects
- Ensure renderer.render() is called
- Add lights if using lit materials
**Poor performance:**
- Reduce particle count
- Lower geometry detail (segments)
- Reuse materials/geometries
- Check browser console for errors
**Objects not visible:**
- Check object position vs camera position
- Verify material has visible color/properties
- Ensure camera far plane includes objects
@@ -416,19 +424,22 @@ scene.add(ground);
// 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
"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
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
envMap: envMap,
});
```
@@ -457,12 +468,8 @@ scene.fog = new THREE.FogExp2(0xcccccc, 0.02); // color, density
```javascript
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));
const vertices = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
```
### Post-Processing Effects
@@ -482,6 +489,7 @@ scene.add(group);
## Summary
Three.js artifacts require systematic setup:
1. Import correct CDN version (r128)
2. Initialize scene, camera, renderer
3. Create geometry + material = mesh
@@ -500,13 +508,14 @@ While this skill focuses on CDN-based Three.js (r128) for artifact compatibility
```javascript
// 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';
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:**
- Tree-shaking (smaller bundle sizes)
- Access to full example library (OrbitControls, loaders, etc.)
- Latest Three.js features (r150+)
@@ -516,23 +525,24 @@ import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer
```javascript
// Smooth timeline-based animations
import gsap from 'gsap';
import gsap from "gsap";
// Instead of manual animation loops:
gsap.to(mesh.position, {
x: 5,
duration: 2,
ease: 'power2.inOut'
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');
.to(mesh.scale, { x: 2, y: 2, z: 2, duration: 1 }, "-=1");
```
**Why GSAP:**
- Professional easing functions
- Timeline control (pause, reverse, scrub)
- Better than manual lerping for complex animations
@@ -543,24 +553,25 @@ timeline
// Sync 3D animations with page scroll
let scrollY = window.scrollY;
window.addEventListener('scroll', () => {
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:**
- ScrollTrigger (GSAP plugin)
- Locomotive Scroll
- Lenis smooth scroll
@@ -570,9 +581,9 @@ function animate() {
```javascript
// Level of Detail (LOD)
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 0); // Close up
lod.addLevel(highDetailMesh, 0); // Close up
lod.addLevel(mediumDetailMesh, 10); // Medium distance
lod.addLevel(lowDetailMesh, 50); // Far away
lod.addLevel(lowDetailMesh, 50); // Far away
scene.add(lod);
// Instanced meshes for many identical objects
@@ -583,7 +594,11 @@ 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);
matrix.setPosition(
Math.random() * 100,
Math.random() * 100,
Math.random() * 100,
);
instancedMesh.setMatrixAt(i, matrix);
}
```
@@ -592,12 +607,12 @@ for (let i = 0; i < 1000; i++) {
```javascript
// In production, load 3D models:
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
const loader = new GLTFLoader();
loader.load('model.gltf', (gltf) => {
loader.load("model.gltf", (gltf) => {
scene.add(gltf.scene);
// Traverse and setup materials
gltf.scene.traverse((child) => {
if (child.isMesh) {
@@ -611,12 +626,14 @@ loader.load('model.gltf', (gltf) => {
### When to Use What
**CDN Approach (Current Skill):**
- Quick prototypes and demos
- Educational content
- Artifacts and embedded experiences
- No build step required
**Production Build Approach:**
- Client projects and portfolios
- Complex applications
- Need latest features (r150+)

View File

@@ -7006,7 +7006,7 @@
"path": "skills/threejs-skills",
"category": "uncategorized",
"name": "threejs-skills",
"description": "Three.js skills for creating 3D elements and interactive experiences",
"description": "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.",
"risk": "safe",
"source": "https://github.com/CloudAI-X/threejs-skills"
},