sumulige-claude 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -135,7 +135,16 @@
135
135
  "Bash(CLAUDE_PROJECT_DIR=\"/Users/sumulige/Documents/Antigravity/sumulige-claude\" /opt/homebrew/Cellar/node/25.3.0/bin/node .claude/hooks/memory-saver.cjs)",
136
136
  "Bash(du:*)",
137
137
  "Bash(wc:*)",
138
- "Bash(/Users/sumulige/.local/share/fnm/node-versions/v24.3.0/installation/bin/node /Users/sumulige/.local/share/fnm/node-versions/v24.3.0/installation/lib/node_modules/npm/bin/npm-cli.js test)"
138
+ "Bash(/Users/sumulige/.local/share/fnm/node-versions/v24.3.0/installation/bin/node /Users/sumulige/.local/share/fnm/node-versions/v24.3.0/installation/lib/node_modules/npm/bin/npm-cli.js test)",
139
+ "Bash(npx skills add:*)",
140
+ "Bash(npx --version)",
141
+ "WebFetch(domain:api.github.com)",
142
+ "Bash(xargs:*)",
143
+ "Bash(CLAUDE_PROJECT_DIR=\"/Users/sumulige/Documents/Antigravity/sumulige-claude\" CLAUDE_TOOL_NAME=\"Write\" CLAUDE_TOOL_INPUT='{\"\"file_path\"\":\"\"/tmp/test.js\"\"}' /opt/homebrew/Cellar/node/25.3.0/bin/node:*)",
144
+ "Bash(CLAUDE_PROJECT_DIR=\"/Users/sumulige/Documents/Antigravity/sumulige-claude\" CLAUDE_TOOL_NAME=\"Write\" CLAUDE_TOOL_INPUT='{\"\"file_path\"\":\"\"/Users/sumulige/Documents/Antigravity/sumulige-claude/lib/commands.js\"\"}' /opt/homebrew/Cellar/node/25.3.0/bin/node /Users/sumulige/Documents/Antigravity/sumulige-claude/.claude/hooks/live-quality.cjs)",
145
+ "Bash(CLAUDE_PROJECT_DIR=\"/Users/sumulige/Documents/Antigravity/sumulige-claude\" CLAUDE_TOOL_NAME=\"Write\" CLAUDE_TOOL_INPUT='{\"\"file_path\"\":\"\"/tmp/test-flow.js\"\"}' /opt/homebrew/Cellar/node/25.3.0/bin/node:*)",
146
+ "Bash(CLAUDE_PROJECT_DIR=\"/Users/sumulige/Documents/Antigravity/sumulige-claude\" CLAUDE_TOOL_NAME=\"Edit\" CLAUDE_TOOL_INPUT='{\"\"file_path\"\":\"\"/Users/sumulige/Documents/Antigravity/sumulige-claude/.claude/hooks/plan-gate.cjs\"\"}' /opt/homebrew/Cellar/node/25.3.0/bin/node:*)",
147
+ "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm version 1.5.0 --no-git-tag-version)"
139
148
  ]
140
149
  },
141
150
  "hooks": {
@@ -145,7 +154,7 @@
145
154
  "hooks": [
146
155
  {
147
156
  "type": "command",
148
- "command": "node .claude/hooks/conversation-recorder.cjs user \"$ARGUMENTS\""
157
+ "command": "cd \"$CLAUDE_PROJECT_DIR\" && node .claude/hooks/conversation-recorder.cjs user \"$ARGUMENTS\""
149
158
  }
150
159
  ]
151
160
  }
@@ -156,7 +165,7 @@
156
165
  "hooks": [
157
166
  {
158
167
  "type": "command",
159
- "command": "node .claude/hooks/conversation-recorder.cjs today"
168
+ "command": "cd \"$CLAUDE_PROJECT_DIR\" && node .claude/hooks/conversation-recorder.cjs today"
160
169
  }
161
170
  ]
162
171
  }
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: vercel-react-best-practices
3
+ description: React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
4
+ license: MIT
5
+ metadata:
6
+ author: vercel
7
+ version: "1.0.0"
8
+ ---
9
+
10
+ # Vercel React Best Practices
11
+
12
+ Comprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 45 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
13
+
14
+ ## When to Apply
15
+
16
+ Reference these guidelines when:
17
+ - Writing new React components or Next.js pages
18
+ - Implementing data fetching (client or server-side)
19
+ - Reviewing code for performance issues
20
+ - Refactoring existing React/Next.js code
21
+ - Optimizing bundle size or load times
22
+
23
+ ## Rule Categories by Priority
24
+
25
+ | Priority | Category | Impact | Prefix |
26
+ |----------|----------|--------|--------|
27
+ | 1 | Eliminating Waterfalls | CRITICAL | `async-` |
28
+ | 2 | Bundle Size Optimization | CRITICAL | `bundle-` |
29
+ | 3 | Server-Side Performance | HIGH | `server-` |
30
+ | 4 | Client-Side Data Fetching | MEDIUM-HIGH | `client-` |
31
+ | 5 | Re-render Optimization | MEDIUM | `rerender-` |
32
+ | 6 | Rendering Performance | MEDIUM | `rendering-` |
33
+ | 7 | JavaScript Performance | LOW-MEDIUM | `js-` |
34
+ | 8 | Advanced Patterns | LOW | `advanced-` |
35
+
36
+ ## Quick Reference
37
+
38
+ ### 1. Eliminating Waterfalls (CRITICAL)
39
+
40
+ - `async-defer-await` - Move await into branches where actually used
41
+ - `async-parallel` - Use Promise.all() for independent operations
42
+ - `async-dependencies` - Use better-all for partial dependencies
43
+ - `async-api-routes` - Start promises early, await late in API routes
44
+ - `async-suspense-boundaries` - Use Suspense to stream content
45
+
46
+ ### 2. Bundle Size Optimization (CRITICAL)
47
+
48
+ - `bundle-barrel-imports` - Import directly, avoid barrel files
49
+ - `bundle-dynamic-imports` - Use next/dynamic for heavy components
50
+ - `bundle-defer-third-party` - Load analytics/logging after hydration
51
+ - `bundle-conditional` - Load modules only when feature is activated
52
+ - `bundle-preload` - Preload on hover/focus for perceived speed
53
+
54
+ ### 3. Server-Side Performance (HIGH)
55
+
56
+ - `server-cache-react` - Use React.cache() for per-request deduplication
57
+ - `server-cache-lru` - Use LRU cache for cross-request caching
58
+ - `server-serialization` - Minimize data passed to client components
59
+ - `server-parallel-fetching` - Restructure components to parallelize fetches
60
+ - `server-after-nonblocking` - Use after() for non-blocking operations
61
+
62
+ ### 4. Client-Side Data Fetching (MEDIUM-HIGH)
63
+
64
+ - `client-swr-dedup` - Use SWR for automatic request deduplication
65
+ - `client-event-listeners` - Deduplicate global event listeners
66
+
67
+ ### 5. Re-render Optimization (MEDIUM)
68
+
69
+ - `rerender-defer-reads` - Don't subscribe to state only used in callbacks
70
+ - `rerender-memo` - Extract expensive work into memoized components
71
+ - `rerender-dependencies` - Use primitive dependencies in effects
72
+ - `rerender-derived-state` - Subscribe to derived booleans, not raw values
73
+ - `rerender-functional-setstate` - Use functional setState for stable callbacks
74
+ - `rerender-lazy-state-init` - Pass function to useState for expensive values
75
+ - `rerender-transitions` - Use startTransition for non-urgent updates
76
+
77
+ ### 6. Rendering Performance (MEDIUM)
78
+
79
+ - `rendering-animate-svg-wrapper` - Animate div wrapper, not SVG element
80
+ - `rendering-content-visibility` - Use content-visibility for long lists
81
+ - `rendering-hoist-jsx` - Extract static JSX outside components
82
+ - `rendering-svg-precision` - Reduce SVG coordinate precision
83
+ - `rendering-hydration-no-flicker` - Use inline script for client-only data
84
+ - `rendering-activity` - Use Activity component for show/hide
85
+ - `rendering-conditional-render` - Use ternary, not && for conditionals
86
+
87
+ ### 7. JavaScript Performance (LOW-MEDIUM)
88
+
89
+ - `js-batch-dom-css` - Group CSS changes via classes or cssText
90
+ - `js-index-maps` - Build Map for repeated lookups
91
+ - `js-cache-property-access` - Cache object properties in loops
92
+ - `js-cache-function-results` - Cache function results in module-level Map
93
+ - `js-cache-storage` - Cache localStorage/sessionStorage reads
94
+ - `js-combine-iterations` - Combine multiple filter/map into one loop
95
+ - `js-length-check-first` - Check array length before expensive comparison
96
+ - `js-early-exit` - Return early from functions
97
+ - `js-hoist-regexp` - Hoist RegExp creation outside loops
98
+ - `js-min-max-loop` - Use loop for min/max instead of sort
99
+ - `js-set-map-lookups` - Use Set/Map for O(1) lookups
100
+ - `js-tosorted-immutable` - Use toSorted() for immutability
101
+
102
+ ### 8. Advanced Patterns (LOW)
103
+
104
+ - `advanced-event-handler-refs` - Store event handlers in refs
105
+ - `advanced-use-latest` - useLatest for stable callback refs
106
+
107
+ ## How to Use
108
+
109
+ Read individual rule files for detailed explanations and code examples:
110
+
111
+ ```
112
+ rules/async-parallel.md
113
+ rules/bundle-barrel-imports.md
114
+ rules/_sections.md
115
+ ```
116
+
117
+ Each rule file contains:
118
+ - Brief explanation of why it matters
119
+ - Incorrect code example with explanation
120
+ - Correct code example with explanation
121
+ - Additional context and references
122
+
123
+ ## Full Compiled Document
124
+
125
+ For the complete guide with all rules expanded: `AGENTS.md`
@@ -0,0 +1,488 @@
1
+ ---
2
+ name: threejs-fundamentals
3
+ description: Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.
4
+ ---
5
+
6
+ # Three.js Fundamentals
7
+
8
+ ## Quick Start
9
+
10
+ ```javascript
11
+ import * as THREE from "three";
12
+
13
+ // Create scene, camera, renderer
14
+ const scene = new THREE.Scene();
15
+ const camera = new THREE.PerspectiveCamera(
16
+ 75,
17
+ window.innerWidth / window.innerHeight,
18
+ 0.1,
19
+ 1000,
20
+ );
21
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
22
+
23
+ renderer.setSize(window.innerWidth, window.innerHeight);
24
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
25
+ document.body.appendChild(renderer.domElement);
26
+
27
+ // Add a mesh
28
+ const geometry = new THREE.BoxGeometry(1, 1, 1);
29
+ const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
30
+ const cube = new THREE.Mesh(geometry, material);
31
+ scene.add(cube);
32
+
33
+ // Add light
34
+ scene.add(new THREE.AmbientLight(0xffffff, 0.5));
35
+ const dirLight = new THREE.DirectionalLight(0xffffff, 1);
36
+ dirLight.position.set(5, 5, 5);
37
+ scene.add(dirLight);
38
+
39
+ camera.position.z = 5;
40
+
41
+ // Animation loop
42
+ function animate() {
43
+ requestAnimationFrame(animate);
44
+ cube.rotation.x += 0.01;
45
+ cube.rotation.y += 0.01;
46
+ renderer.render(scene, camera);
47
+ }
48
+ animate();
49
+
50
+ // Handle resize
51
+ window.addEventListener("resize", () => {
52
+ camera.aspect = window.innerWidth / window.innerHeight;
53
+ camera.updateProjectionMatrix();
54
+ renderer.setSize(window.innerWidth, window.innerHeight);
55
+ });
56
+ ```
57
+
58
+ ## Core Classes
59
+
60
+ ### Scene
61
+
62
+ Container for all 3D objects, lights, and cameras.
63
+
64
+ ```javascript
65
+ const scene = new THREE.Scene();
66
+ scene.background = new THREE.Color(0x000000); // Solid color
67
+ scene.background = texture; // Skybox texture
68
+ scene.background = cubeTexture; // Cubemap
69
+ scene.environment = envMap; // Environment map for PBR
70
+ scene.fog = new THREE.Fog(0xffffff, 1, 100); // Linear fog
71
+ scene.fog = new THREE.FogExp2(0xffffff, 0.02); // Exponential fog
72
+ ```
73
+
74
+ ### Cameras
75
+
76
+ **PerspectiveCamera** - Most common, simulates human eye.
77
+
78
+ ```javascript
79
+ // PerspectiveCamera(fov, aspect, near, far)
80
+ const camera = new THREE.PerspectiveCamera(
81
+ 75, // Field of view (degrees)
82
+ window.innerWidth / window.innerHeight, // Aspect ratio
83
+ 0.1, // Near clipping plane
84
+ 1000, // Far clipping plane
85
+ );
86
+
87
+ camera.position.set(0, 5, 10);
88
+ camera.lookAt(0, 0, 0);
89
+ camera.updateProjectionMatrix(); // Call after changing fov, aspect, near, far
90
+ ```
91
+
92
+ **OrthographicCamera** - No perspective distortion, good for 2D/isometric.
93
+
94
+ ```javascript
95
+ // OrthographicCamera(left, right, top, bottom, near, far)
96
+ const aspect = window.innerWidth / window.innerHeight;
97
+ const frustumSize = 10;
98
+ const camera = new THREE.OrthographicCamera(
99
+ (frustumSize * aspect) / -2,
100
+ (frustumSize * aspect) / 2,
101
+ frustumSize / 2,
102
+ frustumSize / -2,
103
+ 0.1,
104
+ 1000,
105
+ );
106
+ ```
107
+
108
+ **ArrayCamera** - Multiple viewports with sub-cameras.
109
+
110
+ ```javascript
111
+ const cameras = [];
112
+ for (let i = 0; i < 4; i++) {
113
+ const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
114
+ subcamera.viewport = new THREE.Vector4(
115
+ Math.floor(i % 2) * 0.5,
116
+ Math.floor(i / 2) * 0.5,
117
+ 0.5,
118
+ 0.5,
119
+ );
120
+ cameras.push(subcamera);
121
+ }
122
+ const arrayCamera = new THREE.ArrayCamera(cameras);
123
+ ```
124
+
125
+ **CubeCamera** - Renders environment maps for reflections.
126
+
127
+ ```javascript
128
+ const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
129
+ const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
130
+ scene.add(cubeCamera);
131
+
132
+ // Use for reflections
133
+ material.envMap = cubeRenderTarget.texture;
134
+
135
+ // Update each frame (expensive!)
136
+ cubeCamera.position.copy(reflectiveMesh.position);
137
+ cubeCamera.update(renderer, scene);
138
+ ```
139
+
140
+ ### WebGLRenderer
141
+
142
+ ```javascript
143
+ const renderer = new THREE.WebGLRenderer({
144
+ canvas: document.querySelector("#canvas"), // Optional existing canvas
145
+ antialias: true, // Smooth edges
146
+ alpha: true, // Transparent background
147
+ powerPreference: "high-performance", // GPU hint
148
+ preserveDrawingBuffer: true, // For screenshots
149
+ });
150
+
151
+ renderer.setSize(width, height);
152
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
153
+
154
+ // Tone mapping
155
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
156
+ renderer.toneMappingExposure = 1.0;
157
+
158
+ // Color space (Three.js r152+)
159
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
160
+
161
+ // Shadows
162
+ renderer.shadowMap.enabled = true;
163
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
164
+
165
+ // Clear color
166
+ renderer.setClearColor(0x000000, 1);
167
+
168
+ // Render
169
+ renderer.render(scene, camera);
170
+ ```
171
+
172
+ ### Object3D
173
+
174
+ Base class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.
175
+
176
+ ```javascript
177
+ const obj = new THREE.Object3D();
178
+
179
+ // Transform
180
+ obj.position.set(x, y, z);
181
+ obj.rotation.set(x, y, z); // Euler angles (radians)
182
+ obj.quaternion.set(x, y, z, w); // Quaternion rotation
183
+ obj.scale.set(x, y, z);
184
+
185
+ // Local vs World transforms
186
+ obj.getWorldPosition(targetVector);
187
+ obj.getWorldQuaternion(targetQuaternion);
188
+ obj.getWorldDirection(targetVector);
189
+
190
+ // Hierarchy
191
+ obj.add(child);
192
+ obj.remove(child);
193
+ obj.parent;
194
+ obj.children;
195
+
196
+ // Visibility
197
+ obj.visible = false;
198
+
199
+ // Layers (for selective rendering/raycasting)
200
+ obj.layers.set(1);
201
+ obj.layers.enable(2);
202
+ obj.layers.disable(0);
203
+
204
+ // Traverse hierarchy
205
+ obj.traverse((child) => {
206
+ if (child.isMesh) child.material.color.set(0xff0000);
207
+ });
208
+
209
+ // Matrix updates
210
+ obj.matrixAutoUpdate = true; // Default: auto-update matrices
211
+ obj.updateMatrix(); // Manual matrix update
212
+ obj.updateMatrixWorld(true); // Update world matrix recursively
213
+ ```
214
+
215
+ ### Group
216
+
217
+ Empty container for organizing objects.
218
+
219
+ ```javascript
220
+ const group = new THREE.Group();
221
+ group.add(mesh1);
222
+ group.add(mesh2);
223
+ scene.add(group);
224
+
225
+ // Transform entire group
226
+ group.position.x = 5;
227
+ group.rotation.y = Math.PI / 4;
228
+ ```
229
+
230
+ ### Mesh
231
+
232
+ Combines geometry and material.
233
+
234
+ ```javascript
235
+ const mesh = new THREE.Mesh(geometry, material);
236
+
237
+ // Multiple materials (one per geometry group)
238
+ const mesh = new THREE.Mesh(geometry, [material1, material2]);
239
+
240
+ // Useful properties
241
+ mesh.geometry;
242
+ mesh.material;
243
+ mesh.castShadow = true;
244
+ mesh.receiveShadow = true;
245
+
246
+ // Frustum culling
247
+ mesh.frustumCulled = true; // Default: skip if outside camera view
248
+
249
+ // Render order
250
+ mesh.renderOrder = 10; // Higher = rendered later
251
+ ```
252
+
253
+ ## Coordinate System
254
+
255
+ Three.js uses a **right-handed coordinate system**:
256
+
257
+ - **+X** points right
258
+ - **+Y** points up
259
+ - **+Z** points toward viewer (out of screen)
260
+
261
+ ```javascript
262
+ // Axes helper
263
+ const axesHelper = new THREE.AxesHelper(5);
264
+ scene.add(axesHelper); // Red=X, Green=Y, Blue=Z
265
+ ```
266
+
267
+ ## Math Utilities
268
+
269
+ ### Vector3
270
+
271
+ ```javascript
272
+ const v = new THREE.Vector3(x, y, z);
273
+ v.set(x, y, z);
274
+ v.copy(otherVector);
275
+ v.clone();
276
+
277
+ // Operations (modify in place)
278
+ v.add(v2);
279
+ v.sub(v2);
280
+ v.multiply(v2);
281
+ v.multiplyScalar(2);
282
+ v.divideScalar(2);
283
+ v.normalize();
284
+ v.negate();
285
+ v.clamp(min, max);
286
+ v.lerp(target, alpha);
287
+
288
+ // Calculations (return new value)
289
+ v.length();
290
+ v.lengthSq(); // Faster than length()
291
+ v.distanceTo(v2);
292
+ v.dot(v2);
293
+ v.cross(v2); // Modifies v
294
+ v.angleTo(v2);
295
+
296
+ // Transform
297
+ v.applyMatrix4(matrix);
298
+ v.applyQuaternion(q);
299
+ v.project(camera); // World to NDC
300
+ v.unproject(camera); // NDC to world
301
+ ```
302
+
303
+ ### Matrix4
304
+
305
+ ```javascript
306
+ const m = new THREE.Matrix4();
307
+ m.identity();
308
+ m.copy(other);
309
+ m.clone();
310
+
311
+ // Build transforms
312
+ m.makeTranslation(x, y, z);
313
+ m.makeRotationX(theta);
314
+ m.makeRotationY(theta);
315
+ m.makeRotationZ(theta);
316
+ m.makeRotationFromQuaternion(q);
317
+ m.makeScale(x, y, z);
318
+
319
+ // Compose/decompose
320
+ m.compose(position, quaternion, scale);
321
+ m.decompose(position, quaternion, scale);
322
+
323
+ // Operations
324
+ m.multiply(m2); // m = m * m2
325
+ m.premultiply(m2); // m = m2 * m
326
+ m.invert();
327
+ m.transpose();
328
+
329
+ // Camera matrices
330
+ m.makePerspective(left, right, top, bottom, near, far);
331
+ m.makeOrthographic(left, right, top, bottom, near, far);
332
+ m.lookAt(eye, target, up);
333
+ ```
334
+
335
+ ### Quaternion
336
+
337
+ ```javascript
338
+ const q = new THREE.Quaternion();
339
+ q.setFromEuler(euler);
340
+ q.setFromAxisAngle(axis, angle);
341
+ q.setFromRotationMatrix(matrix);
342
+
343
+ q.multiply(q2);
344
+ q.slerp(target, t); // Spherical interpolation
345
+ q.normalize();
346
+ q.invert();
347
+ ```
348
+
349
+ ### Euler
350
+
351
+ ```javascript
352
+ const euler = new THREE.Euler(x, y, z, "XYZ"); // Order matters!
353
+ euler.setFromQuaternion(q);
354
+ euler.setFromRotationMatrix(m);
355
+
356
+ // Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'
357
+ ```
358
+
359
+ ### Color
360
+
361
+ ```javascript
362
+ const color = new THREE.Color(0xff0000);
363
+ const color = new THREE.Color("red");
364
+ const color = new THREE.Color("rgb(255, 0, 0)");
365
+ const color = new THREE.Color("#ff0000");
366
+
367
+ color.setHex(0x00ff00);
368
+ color.setRGB(r, g, b); // 0-1 range
369
+ color.setHSL(h, s, l); // 0-1 range
370
+
371
+ color.lerp(otherColor, alpha);
372
+ color.multiply(otherColor);
373
+ color.multiplyScalar(2);
374
+ ```
375
+
376
+ ### MathUtils
377
+
378
+ ```javascript
379
+ THREE.MathUtils.clamp(value, min, max);
380
+ THREE.MathUtils.lerp(start, end, alpha);
381
+ THREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);
382
+ THREE.MathUtils.degToRad(degrees);
383
+ THREE.MathUtils.radToDeg(radians);
384
+ THREE.MathUtils.randFloat(min, max);
385
+ THREE.MathUtils.randInt(min, max);
386
+ THREE.MathUtils.smoothstep(x, min, max);
387
+ THREE.MathUtils.smootherstep(x, min, max);
388
+ ```
389
+
390
+ ## Common Patterns
391
+
392
+ ### Proper Cleanup
393
+
394
+ ```javascript
395
+ function dispose() {
396
+ // Dispose geometries
397
+ mesh.geometry.dispose();
398
+
399
+ // Dispose materials
400
+ if (Array.isArray(mesh.material)) {
401
+ mesh.material.forEach((m) => m.dispose());
402
+ } else {
403
+ mesh.material.dispose();
404
+ }
405
+
406
+ // Dispose textures
407
+ texture.dispose();
408
+
409
+ // Remove from scene
410
+ scene.remove(mesh);
411
+
412
+ // Dispose renderer
413
+ renderer.dispose();
414
+ }
415
+ ```
416
+
417
+ ### Clock for Animation
418
+
419
+ ```javascript
420
+ const clock = new THREE.Clock();
421
+
422
+ function animate() {
423
+ const delta = clock.getDelta(); // Time since last frame (seconds)
424
+ const elapsed = clock.getElapsedTime(); // Total time (seconds)
425
+
426
+ mesh.rotation.y += delta * 0.5; // Consistent speed regardless of framerate
427
+
428
+ requestAnimationFrame(animate);
429
+ renderer.render(scene, camera);
430
+ }
431
+ ```
432
+
433
+ ### Responsive Canvas
434
+
435
+ ```javascript
436
+ function onWindowResize() {
437
+ const width = window.innerWidth;
438
+ const height = window.innerHeight;
439
+
440
+ camera.aspect = width / height;
441
+ camera.updateProjectionMatrix();
442
+
443
+ renderer.setSize(width, height);
444
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
445
+ }
446
+ window.addEventListener("resize", onWindowResize);
447
+ ```
448
+
449
+ ### Loading Manager
450
+
451
+ ```javascript
452
+ const manager = new THREE.LoadingManager();
453
+
454
+ manager.onStart = (url, loaded, total) => console.log("Started loading");
455
+ manager.onLoad = () => console.log("All loaded");
456
+ manager.onProgress = (url, loaded, total) => console.log(`${loaded}/${total}`);
457
+ manager.onError = (url) => console.error(`Error loading ${url}`);
458
+
459
+ const textureLoader = new THREE.TextureLoader(manager);
460
+ const gltfLoader = new GLTFLoader(manager);
461
+ ```
462
+
463
+ ## Performance Tips
464
+
465
+ 1. **Limit draw calls**: Merge geometries, use instancing, atlas textures
466
+ 2. **Frustum culling**: Enabled by default, ensure bounding boxes are correct
467
+ 3. **LOD (Level of Detail)**: Use `THREE.LOD` for distance-based mesh switching
468
+ 4. **Object pooling**: Reuse objects instead of creating/destroying
469
+ 5. **Avoid `getWorldPosition` in loops**: Cache results
470
+
471
+ ```javascript
472
+ // Merge static geometries
473
+ import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
474
+ const merged = mergeGeometries([geo1, geo2, geo3]);
475
+
476
+ // LOD
477
+ const lod = new THREE.LOD();
478
+ lod.addLevel(highDetailMesh, 0);
479
+ lod.addLevel(medDetailMesh, 50);
480
+ lod.addLevel(lowDetailMesh, 100);
481
+ scene.add(lod);
482
+ ```
483
+
484
+ ## See Also
485
+
486
+ - `threejs-geometry` - Geometry creation and manipulation
487
+ - `threejs-materials` - Material types and properties
488
+ - `threejs-lighting` - Light types and shadows
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: web-design-guidelines
3
+ description: Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
4
+ metadata:
5
+ author: vercel
6
+ version: "1.0.0"
7
+ argument-hint: <file-or-pattern>
8
+ ---
9
+
10
+ # Web Interface Guidelines
11
+
12
+ Review files for compliance with Web Interface Guidelines.
13
+
14
+ ## How It Works
15
+
16
+ 1. Fetch the latest guidelines from the source URL below
17
+ 2. Read the specified files (or prompt user for files/pattern)
18
+ 3. Check against all rules in the fetched guidelines
19
+ 4. Output findings in the terse `file:line` format
20
+
21
+ ## Guidelines Source
22
+
23
+ Fetch fresh guidelines before each review:
24
+
25
+ ```
26
+ https://raw.githubusercontent.com/vercel-labs/web-interface-guidelines/main/command.md
27
+ ```
28
+
29
+ Use WebFetch to retrieve the latest rules. The fetched content contains all the rules and output format instructions.
30
+
31
+ ## Usage
32
+
33
+ When a user provides a file or pattern argument:
34
+ 1. Fetch guidelines from the source URL above
35
+ 2. Read the specified files
36
+ 3. Apply all rules from the fetched guidelines
37
+ 4. Output findings using the format specified in the guidelines
38
+
39
+ If no files specified, ask the user which files to review.