
threejs-tresjs
3D HUD rendering with Three.js and TresJS for JARVIS AI Assistant
- Installs
- 252
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/martinholovsky/claude-skills-generator --skill threejs-tresjs- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads threejs-tresjs automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Three.js / TresJS Development Skill
File Organization: This skill uses split structure. See
references/for advanced patterns and security examples.
1. Overview
This skill provides expertise for building 3D HUD interfaces using Three.js and TresJS (Vue 3 integration). It focuses on creating performant, visually stunning holographic displays for the JARVIS AI Assistant.
Risk Level: MEDIUM - GPU resource consumption, potential ReDoS in color parsing, WebGL security considerations
Primary Use Cases:
- Rendering 3D holographic HUD panels
- Animated status indicators and gauges
- Particle effects for system visualization
- Real-time metric displays with 3D elements
2. Core Responsibilities
2.1 Fundamental Principles
- TDD First: Write tests before implementation - verify 3D components render correctly
- Performance Aware: Optimize for 60fps with instancing, LOD, and efficient render loops
- Resource Management: Always dispose of geometries, materials, and textures to prevent memory leaks
- Vue Reactivity Integration: Use TresJS for seamless Vue 3 composition API integration
- Safe Color Parsing: Validate color inputs to prevent ReDoS attacks
- GPU Protection: Implement safeguards against GPU resource exhaustion
- Accessibility: Provide fallbacks for devices without WebGL support
3. Technology Stack & Versions
3.1 Recommended Versions
| Package | Version | Security Notes |
|---|---|---|
| three | ^0.160.0+ | Latest stable, fixes CVE-2020-28496 ReDoS |
| @tresjs/core | ^4.0.0 | Vue 3 integration |
| @tresjs/cientos | ^3.0.0 | Component library |
| postprocessing | ^6.0.0 | Effects library |
3.2 Security-Critical Updates
{
"dependencies": {
"three": "^0.160.0",
"@tresjs/core": "^4.0.0",
"@tresjs/cientos": "^3.0.0"
}
}
Note: Versions before 0.137.0 have XSS vulnerabilities, before 0.125.0 have ReDoS vulnerabilities.
4. Implementation Patterns
4.1 Basic HUD Scene Setup
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
const gl = {
clearColor: '#000011',
alpha: true,
antialias: true,
powerPreference: 'high-performance'
}
</script>
<template>
<TresCanvas v-bind="gl">
<TresPerspectiveCamera :position="[0, 0, 5]" />
<OrbitControls :enable-damping="true" />
<HUDPanels />
<MetricsDisplay />
<ParticleEffects />
</TresCanvas>
</template>
4.2 Secure Color Handling
// utils/safeColor.ts
import { Color } from 'three'
// ✅ Safe color parsing with validation
export function safeParseColor(input: string): Color {
// Validate format to prevent ReDoS
const hexPattern = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/
const rgbPattern = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/
if (!hexPattern.test(input) && !rgbPattern.test(input)) {
console.warn('Invalid color format, using default')
return new Color(0x00ff00) // Default JARVIS green
}
return new Color(input)
}
// ❌ DANGEROUS - User input directly to Color
// const color = new Color(userInput) // Potential ReDoS
// ✅ SECURE - Validated input
const color = safeParseColor(userInput)
4.3 Memory-Safe Component
<script setup lang="ts">
import { onUnmounted, shallowRef } from 'vue'
import { Mesh, BoxGeometry, MeshStandardMaterial } from 'three'
// ✅ Use shallowRef for Three.js objects
const meshRef = shallowRef<Mesh | null>(null)
// ✅ Cleanup on unmount
onUnmounted(() => {
if (meshRef.value) {
meshRef.value.geometry.dispose()
if (Array.isArray(meshRef.value.material)) {
meshRef.value.material.forEach(m => m.dispose())
} else {
meshRef.value.material.dispose()
}
}
})
</script>
<template>
<TresMesh ref="meshRef">
<TresBoxGeometry :args="[1, 1, 1]" />
<TresMeshStandardMaterial color="#00ff41" />
</TresMesh>
</template>
4.4 Performance-Optimized Instancing
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { InstancedMesh, Object3D, Matrix4 } from 'three'
const instanceCount = 1000
const instancedMeshRef = ref<InstancedMesh | null>(null)
onMounted(() => {
if (!instancedMeshRef.value) return
const dummy = new Object3D()
const matrix = new Matrix4()
// ✅ Batch updates for performance
for (let i = 0; i < instanceCount; i++) {
dummy.position.set(
Math.random() * 10 - 5,
Math.random() * 10 - 5,
Math.random() * 10 - 5
)
dummy.updateMatrix()
instancedMeshRef.value.setMatrixAt(i, dummy.matrix)
}
instancedMeshRef.value.instanceMatrix.needsUpdate = true
})
</script>
<template>
<TresInstancedMesh ref="instancedMeshRef" :args="[null, null, instanceCount]">
<TresSphereGeometry :args="[0.05, 8, 8]" />
<TresMeshBasicMaterial color="#00ff41" />
</TresInstancedMesh>
</template>
4.5 HUD Panel with Text
<script setup lang="ts">
import { Text } from '@tresjs/cientos'
const props = defineProps<{
title: string
value: number
}>()
// ✅ Sanitize text content
const safeTitle = computed(() =>
props.title.replace(/[<>]/g, '').slice(0, 50)
)
</script>
<template>
<TresGroup>
<!-- Panel background -->
<TresMesh>
<TresPlaneGeometry :args="[2, 1]" />
<TresMeshBasicMaterial
color="#001122"
:transparent="true"
:opacity="0.8"
/>
</TresMesh>
<!-- Title text -->
<Text
:text="safeTitle"
:font-size="0.15"
color="#00ff41"
:position="[-0.8, 0.3, 0.01]"
/>
<!-- Value display -->
<Text
:text="String(props.value)"
:font-size="0.3"
color="#ffffff"
:position="[0, -0.1, 0.01]"
/>
</TresGroup>
</template>
5. Implementation Workflow (TDD)
5.1 TDD Process for 3D Components
Step 1: Write Failing Test First
// tests/components/hud-panel.test.ts
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { mount, VueWrapper } from '@vue/test-utils'
import { Scene, WebGLRenderer } from 'three'
import HUDPanel from '~/components/hud/HUDPanel.vue'
describe('HUDPanel', () => {
let wrapper: VueWrapper
beforeEach(() => {
// Mock WebGL context for testing
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl2')
vi.spyOn(HTMLCanvasElement.prototype, 'getContext').mockReturnValue(gl)
})
afterEach(() => {
wrapper?.unmount()
vi.restoreAllMocks()
})
it('renders panel with correct dimensions', () => {
wrapper = mount(HUDPanel, {
props: { width: 2, height: 1, title: 'Status' }
})
// Test fails until component is implemented
expect(wrapper.exists()).toBe(true)
})
it('disposes resources on unmount', async () => {
wrapper = mount(HUDPanel, {
props: { width: 2, height: 1, title: 'Status' }
})
const disposeSpy = vi.fn()
wrapper.vm.meshRef.geometry.dispose = disposeSpy
wrapper.unmount()
expect(disposeSpy).toHaveBeenCalled()
})
})
Step 2: Implement Minimum to Pass
<script setup lang="ts">
import { shallowRef, onUnmounted } from 'vue'
import { Mesh } from 'three'
const props = defineProps<{
width: number
height: number
title: string
}>()
const meshRef = shallowRef<Mesh | null>(null)
onUnmounted(() => {
if (meshRef.value) {
meshRef.value.geometry.dispose()
;(meshRef.value.material as any).dispose()
}
})
</script>
<template>
<TresMesh ref="meshRef">
<TresPlaneGeometry :args="[props.width, props.height]" />
<TresMeshBasicMaterial color="#001122" :transparent="true" :opacity="0.8" />
</TresMesh>
</template>
Step 3: Refactor Following Patterns
// After tests pass, add performance optimizations
// - Use instancing for multiple panels
// - Add LOD for distant panels
// - Implement texture atlases for text
Step 4: Run Full Verification
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# Type check
npm run typecheck
# Performance benchmark
npm run test:perf
5.2 Testing 3D Animations
import { describe, it, expect, vi } from 'vitest'
import { useRenderLoop } from '@tresjs/core'
describe('Animation Loop', () => {
it('maintains 60fps during animation', async () => {
const frameTimes: number[] = []
let lastTime = performance.now()
const { onLoop } = useRenderLoop()
onLoop(() => {
const now = performance.now()
frameTimes.push(now - lastTime)
lastTime = now
})
// Simulate 60 frames
await new Promise(resolve => setTimeout(resolve, 1000))
const avgFrameTime = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length
expect(avgFrameTime).toBeLessThan(16.67) // 60fps = 16.67ms per frame
})
it('cleans up animation loop on unmount', () => {
const cleanup = vi.fn()
const { pause } = useRenderLoop()
// Component unmounts
pause()
expect(cleanup).not.toThrow()
})
})
5.3 Testing Resource Disposal
describe('Resource Management', () => {
it('disposes all GPU resources', () => {
const geometry = new BoxGeometry(1, 1, 1)
const material = new MeshStandardMaterial({ color: 0x00ff41 })
const mesh = new Mesh(geometry, material)
const geoDispose = vi.spyOn(geometry, 'dispose')
const matDispose = vi.spyOn(material, 'dispose')
// Cleanup function
mesh.geometry.dispose()
mesh.material.dispose()
expect(geoDispose).toHaveBeenCalled()
expect(matDispose).toHaveBeenCalled()
})
it('handles material arrays correctly', () => {
const materials = [
new MeshBasicMaterial(),
new MeshStandardMaterial()
]
const mesh = new Mesh(new BoxGeometry(), materials)
const spies = materials.map(m => vi.spyOn(m, 'dispose'))
materials.forEach(m => m.dispose())
spies.forEach(spy => expect(spy).toHaveBeenCalled())
})
})
6. Performance Patterns
6.1 Geometry Instancing
// Good: Use InstancedMesh for repeated objects
import { InstancedMesh, Matrix4, Object3D } from 'three'
const COUNT = 1000
const mesh = new InstancedMesh(geometry, material, COUNT)
const dummy = new Object3D()
for (let i = 0; i < COUNT; i++) {
dummy.position.set(Math.random() * 10, Math.random() * 10, Math.random() * 10)
dummy.updateMatrix()
mesh.setMatrixAt(i, dummy.matrix)
}
mesh.instanceMatrix.needsUpdate = true
// Bad: Creating individual meshes
for (let i = 0; i < COUNT; i++) {
const mesh = new Mesh(geometry.clone(), material.clone()) // Memory waste!
scene.add(mesh)
}
6.2 Texture Atlases
// Good: Single texture atlas for multiple sprites
const atlas = new TextureLoader().load('/textures/hud-atlas.png')
const materials = {
panel: new SpriteMaterial({ map: atlas }),
icon: new SpriteMaterial({ map: atlas })
}
// Set UV offsets for different sprites
materials.panel.map.offset.set(0, 0.5)
materials.panel.map.repeat.set(0.5, 0.5)
// Bad: Loading separate textures
const panelTex = new TextureLoader().load('/textures/panel.png')
const iconTex = new TextureLoader().load('/textures/icon.png')
// Multiple draw calls, more GPU memory
6.3 Level of Detail (LOD)
// Good: Use LOD for complex objects
import { LOD } from 'three'
const lod = new LOD()
// High detail - close up
const highDetail = new Mesh(
new SphereGeometry(1, 32, 32),
material
)
lod.addLevel(highDetail, 0)
// Medium detail - mid range
const medDetail = new Mesh(
new SphereGeometry(1, 16, 16),
material
)
lod.addLevel(medDetail, 10)
// Low detail - far away
const lowDetail = new Mesh(
new SphereGeometry(1, 8, 8),
material
)
lod.addLevel(lowDetail, 20)
scene.add(lod)
// Bad: Always rendering high detail
const sphere = new Mesh(new SphereGeometry(1, 64, 64), material)
6.4 Frustum Culling
// Good: Enable frustum culling (default, but verify)
mesh.frustumCulled = true
// For custom bounds optimization
mesh.geometry.computeBoundingSphere()
mesh.geometry.computeBoundingBox()
// Manual visibility check for complex scenes
const frustum = new Frustum()
const matrix = new Matrix4().multiplyMatrices(
camera.projectionMatrix,
camera.matrixWorldInverse
)
frustum.setFromProjectionMatrix(matrix)
objects.forEach(obj => {
obj.visible = frustum.intersectsObject(obj)
})
// Bad: Disabling culling or rendering everything
mesh.frustumCulled = false // Renders even when off-screen
6.5 Object Pooling
// Good: Pool and reuse objects
class ParticlePool {
private pool: Mesh[] = []
private active: Set<Mesh> = new Set()
constructor(private geometry: BufferGeometry, private material: Material) {
// Pre-allocate pool
for (let i = 0; i < 100; i++) {
const mesh = new Mesh(geometry, material)
mesh.visible = false
this.pool.push(mesh)
}
}
acquire(): Mesh | null {
const mesh = this.pool.find(m => !this.active.has(m))
if (mesh) {
mesh.visible = true
this.active.add(mesh)
return mesh
}
return null
}
release(mesh: Mesh): void {
mesh.visible = false
this.active.delete(mesh)
}
}
// Bad: Creating/destroying objects each frame
function spawnParticle() {
const mesh = new Mesh(geometry, material) // GC pressure!
scene.add(mesh)
setTimeout(() => {
scene.remove(mesh)
mesh.geometry.dispose()
}, 1000)
}
6.6 RAF Optimization
// Good: Efficient render loop
let lastTime = 0
const targetFPS = 60
const frameInterval = 1000 / targetFPS
function animate(currentTime: number) {
requestAnimationFrame(animate)
const delta = currentTime - lastTime
// Skip frame if too soon (for battery saving)
if (delta < frameInterval) return
lastTime = currentTime - (delta % frameInterval)
// Update only what changed
if (needsUpdate) {
updateScene()
renderer.render(scene, camera)
}
}
// Bad: Rendering every frame unconditionally
function animate() {
requestAnimationFrame(animate)
// Always updates everything
updateAllObjects()
renderer.render(scene, camera) // Even if nothing changed
}
6.7 Shader Optimization
// Good: Simple, optimized shaders
const material = new ShaderMaterial({
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
uniform vec3 color;
void main() {
gl_FragColor = vec4(color, 1.0);
}
`,
uniforms: {
color: { value: new Color(0x00ff41) }
}
})
// Bad: Complex calculations in fragment shader
// Avoid: loops, conditionals, texture lookups when possible
7. Security Standards
7.1 Known Vulnerabilities
| CVE | Severity | Description | Mitigation |
|---|---|---|---|
| CVE-2020-28496 | HIGH | ReDoS in color parsing | Update to 0.125.0+, validate colors |
| CVE-2022-0177 | MEDIUM | XSS in docs | Update to 0.137.0+ |
7.2 OWASP Top 10 Coverage
| OWASP Category | Risk | Mitigation |
|---|---|---|
| A05 Injection | MEDIUM | Validate all color/text inputs |
| A06 Vulnerable Components | HIGH | Keep Three.js updated |
7.3 GPU Resource Protection
// composables/useResourceLimit.ts
export function useResourceLimit() {
const MAX_TRIANGLES = 1_000_000
const MAX_DRAW_CALLS = 100
let triangleCount = 0
function checkGeometry(geometry: BufferGeometry): boolean {
const triangles = geometry.index
? geometry.index.count / 3
: geometry.attributes.position.count / 3
if (triangleCount + triangles > MAX_TRIANGLES) {
console.error('Triangle limit exceeded')
return false
}
triangleCount += triangles
return true
}
return { checkGeometry }
}
6. Testing & Quality
6.1 Component Testing
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
describe('HUD Panel', () => {
it('sanitizes malicious title input', () => {
const wrapper = mount(HUDPanel, {
props: {
title: '<script>alert("xss")</script>Status',
value: 75
}
})
expect(wrapper.vm.safeTitle).not.toContain('<script>')
})
})
6.2 Performance Testing
describe('Instanced Mesh', () => {
it('handles 1000 instances without frame drop', async () => {
const scene = new Scene()
// Setup instanced mesh...
const startTime = performance.now()
renderer.render(scene, camera)
const renderTime = performance.now() - startTime
expect(renderTime).toBeLessThan(16.67) // 60fps target
})
})
8. Common Mistakes & Anti-Patterns
8.1 Critical Security Anti-Patterns
Never: Parse User Colors Directly
// ❌ DANGEROUS - ReDoS vulnerability
const color = new Color(userInput)
// ✅ SECURE - Validated input
const color = safeParseColor(userInput)
Never: Skip Resource Disposal
// ❌ MEMORY LEAK
const mesh = new Mesh(geometry, material)
scene.remove(mesh)
// Geometry and material still in GPU memory!
// ✅ PROPER CLEANUP
scene.remove(mesh)
mesh.geometry.dispose()
mesh.material.dispose()
8.2 Performance Anti-Patterns
Avoid: Creating Objects in Render Loop
// ❌ BAD - Creates garbage every frame
function animate() {
mesh.position.add(new Vector3(0, 0.01, 0)) // New object every frame!
}
// ✅ GOOD - Reuse objects
const velocity = new Vector3(0, 0.01, 0)
function animate() {
mesh.position.add(velocity)
}
13. Pre-Deployment Checklist
Security Verification
- Three.js version >= 0.137.0 (XSS fix)
- All color inputs validated before parsing
- No user input directly to
new Color() - Resource limits enforced
Performance Verification
- All geometries/materials disposed on unmount
- Instancing used for repeated objects
- No object creation in render loop
- LOD implemented for complex scenes
14. Summary
Three.js/TresJS provides 3D rendering for the JARVIS HUD:
- Security: Validate all inputs, especially colors to prevent ReDoS
- Memory: Always dispose resources on component unmount
- Performance: Use instancing, avoid allocations in render loop
- Integration: TresJS provides seamless Vue 3 reactivity
Remember: WebGL has direct GPU access - always validate inputs and manage resources carefully.
References:
references/advanced-patterns.md- Complex 3D patternsreferences/security-examples.md- WebGL security practices
FAQ
What does the threejs-tresjs skill do?
3D HUD rendering with Three.js and TresJS for JARVIS AI Assistant
How do I install threejs-tresjs?
Run npx skills add https://github.com/martinholovsky/claude-skills-generator --skill threejs-tresjs in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/threejs-tresjs/ (personal) or .claude/skills/threejs-tresjs/ (project).
Which AI agents can use threejs-tresjs?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is threejs-tresjs safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains threejs-tresjs?
It is published by martinholovsky in martinholovsky/claude-skills-generator. It has 252 recorded installs.
More from martinholovsky/claude-skills-generator
sqlite database expert
martinholovsky/claude-skills-generator
Expert in SQLite embedded database development for Tauri/desktop applications with focus on SQL injection prevention, migrations, FTS search, and secure data handling
gsap
martinholovsky/claude-skills-generator
GSAP animations for JARVIS HUD transitions and effects
windows-ui-automation
martinholovsky/claude-skills-generator
Expert in Windows UI Automation (UIA) and Win32 APIs for desktop automation. Specializes in accessible, secure automation of Windows applications including element discovery, input simulation, and process interaction. HIGH-RISK skill requiring strict security controls for system access.
ui-ux-expert
martinholovsky/claude-skills-generator
Expert UI/UX designer specializing in user-centered design, accessibility (WCAG 2.2), design systems, and responsive interfaces. Use when designing web/mobile applications, implementing accessible interfaces, creating design systems, or conducting usability testing.
cicd-expert
martinholovsky/claude-skills-generator
Elite CI/CD pipeline engineer specializing in GitHub Actions, GitLab CI, Jenkins automation, secure deployment strategies, and supply chain security. Expert in building efficient, secure pipelines with proper testing gates, artifact management, and ArgoCD/GitOps patterns. Use when designing pipelines, implementing security gates, or troubleshooting CI/CD issues.
webgl
martinholovsky/claude-skills-generator
WebGL shaders and effects for JARVIS 3D HUD
Popular media & creative skills
hyperframes
heygen-com/hyperframes
Read first to make, edit, animate or render any video with HyperFrames (HTML rendered to video), including launch films, explainers, music videos, charts, maps, vertical clips, title cards, captions and overlays. Holds the render contract, the work loop and what each kind of video needs.
media-use
heygen-com/hyperframes
Get or make any media for a HyperFrames video - music, sound effects, images, icons, logos, voiceover, avatar and generated video, transcripts, cutouts, colour grades and looks - with HeyGen or free local tools, and mix placed audio. Also for footage that looks dark, flat or dull, or should be stylized or hidden.
hyperframes-registry
heygen-com/hyperframes
About 450 ready-made HyperFrames blocks and components installed as editable source - transitions, overlays, titles, kinetic type, captions, charts, map overlays, 3D, camera moves. Use it before hand-building any named visual (CRT scanlines, glitch, film grain, a chart); also for hyperframes add and catalog.
hyperframes-creative
heygen-com/hyperframes
Non-animation creative direction for HyperFrames videos. Use for design spec (frame.md / design.md) handling, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns, and brand / style decisions. For atomic motion patterns and scene blueprints, use hyperframes-animation.
ai-video-generation
101-skills/superpowers
Generate AI videos with Google Veo, Seedance 2.0, HappyHorse, Wan, Grok and 40+ models via inference.sh CLI. Models: Veo 3.1, Veo 3, Seedance 2.0, HappyHorse 1.0, Wan 2.5, Grok Imagine Video, OmniHuman, Fabric, HunyuanVideo. Capabilities: text-to-video, image-to-video, reference-to-video, video editing, lipsync, avatar animation, video upscaling, foley sound. Use for: social media videos, marketing content, explainer videos, product demos, AI avatars. Triggers: video generation, ai video, text to video, image to video, veo, animate image, video from image, ai animation, video generator, generate video, t2v, i2v, ai video maker, create video with ai, runway alternative, pika alternative, sora alternative, kling alternative, seedance, happyhorse
ai-image-generation
101-skills/superpowers
Generate AI images with GPT-Image-2, FLUX, Gemini, Grok, Seedream, Reve and 50+ models via inference.sh CLI. Models: GPT-Image-2, FLUX Dev LoRA, FLUX.2 Klein LoRA, Gemini 3 Pro Image, Grok Imagine, Seedream 4.5, Reve, ImagineArt. Capabilities: text-to-image, image-to-image, inpainting, LoRA, image editing, upscaling, text rendering. Use for: AI art, product mockups, concept art, social media graphics, marketing visuals, illustrations. Triggers: flux, image generation, ai image, text to image, stable diffusion, generate image, ai art, midjourney alternative, dall-e alternative, text2img, t2i, image generator, ai picture, create image with ai, generative ai, ai illustration, grok image, gemini image, gpt image, openai image, chatgpt image