Skip to main content
ZICQ

Skills ZICQ category:Agent Workflows react-three-fiber

React Three Fiber

Build declarative 3D scenes with React Three Fiber (R3F) - a React renderer for Three.js. Use when building interactive 3D experiences in React applications with component-based architecture, state management, and reusable abstractions. Ideal for product configurators, portfolios, games, data visualization, and immersive web experiences.

3120 installs

Official URL:skills.sh

What this skill does

Intro in this page language first. The official description stays in its original wording; we do not rewrite SKILL.md.

What it does

Build declarative 3D scenes with React Three Fiber (R3F) - a React renderer for Three.js

When to use it

This Skill**:

How agents load it

Per Agent Skills progressive disclosure: name and description load at startup (~100 tokens); the full SKILL.md body loads when the skill activates; scripts/, references/, and assets/ load only as needed. This file's sections: React Three Fiber; Overview; Core Concepts; 1. Canvas Component; 2. Declarative 3D Objects; 3. useFrame Hook.

File analysis

File analysis: besides SKILL.md, the body references references/api_reference.md, references/hooks_guide.md, references/drei_helpers.md, scripts/component_generator.py, scripts/scene_setup.py, assets/starter_r3f/. Those resources load on demand. The body is about 1074 lines, above the spec’s 500-line guidance; agents still load it in full on activation.

React Three FiberOverviewCore Concepts1. Canvas Component2. Declarative 3D Objects3. useFrame Hook4. useThree Hook5. useLoader HookCommon PatternsPattern 1: Basic Scene SetupPattern 2: Interactive Objects (Click, Hover)Pattern 3: Animated Component with useFrame

Source category:skills.sh agent-skill

SKILL.md & Agent activation

Official spec ↗
name
react-three-fiber
description
Build declarative 3D scenes with React Three Fiber (R3F) - a React renderer for Three.js. Use when building interactive 3D experiences in React applications with component-based architecture, state management, and reusable abstractions. Ideal for product configurators, portfolios, games, data visualization, and immersive web experiences.
  1. DiscoverThe client exposes names and descriptions to the agent.
  2. ActivateYour request or the task context selects the skill and loads its instructions.
  3. Load resourcesReferenced scripts, documentation and assets are used when needed.
Files referenced by the instructions · 7
  • references/api_reference.md
  • references/hooks_guide.md
  • references/drei_helpers.md
  • scripts/component_generator.py
  • scripts/scene_setup.py
  • assets/starter_r3f/
  • assets/examples/

These paths are extracted from the text. Check the upstream package to verify the files exist.

Invocation syntax and available tools depend on your Agent client. Client integration guide ↗

Install this skill

Skills CLI ↗

Choose the target agent and installation scope, keep referenced package files, then verify the skill appears in the client's catalog.

This skill references supporting files. Retrieve the complete directory from the source; copying SKILL.md alone may leave missing dependencies.

Ask your Agent to install

Copy these instructions to a compatible agent and confirm the target directory matches your client.

Install the agent skill "react-three-fiber" into my project. The full SKILL.md and official description are at https://zicq.com/en/skills/skl-6994a3ab50fae137-React-Three-Fiber.html
Save it as .cursor/skills/react-three-fiber/SKILL.md or .claude/skills/react-three-fiber/SKILL.md and keep the frontmatter name and description exactly as-is.
This skill also ships scripts/, references/, or assets/ — fetch the whole folder from https://github.com/freshtechbro/claudedesignskills instead of creating only a SKILL.md.

Full package on GitHub ↗

Install from the terminal · Skills CLI

Requires Node.js and npx. First inspect the repository's skill list to confirm the name.

npx skills add 'https://github.com/freshtechbro/claudedesignskills' --list

npx skills add 'https://github.com/freshtechbro/claudedesignskills' --skill 'react-three-fiber'

The CLI lets you choose the agent interactively. The default scope is the project; use -g for user scope. Confirm package availability with the discovery command, then use npx skills list to inspect installed skills.

Readable layout
--- name: react-three-fiber description: Build declarative 3D scenes with React Three Fiber (R3F) - a React renderer for Three.js. Use when building interactive 3D experiences in React applications with component-based architecture, state management, and reusable abstractions. Ideal for product configurators, portfolios, games, data visualization, and immersive web experiences. --- # React Three Fiber ## Overview React Three Fiber (R3F) is a React renderer for Three.js that brings declarative, component-based 3D development to React applications. Instead of imperatively creating and managing Three.js objects, you build 3D scenes using JSX components that map directly to Three.js objects. **When to Use This Skill**: - Building 3D experiences within React applications - Creating interactive product configurators or showcases - Developing 3D portfolios, galleries, or storytelling experiences - Building games or simulations in React - Adding 3D elements to existing React projects - When you need state management and React hooks with 3D graphics - When working with React frameworks (Next.js, Gatsby, Remix) **Key Benefits**: - **Declarative**: Write 3D scenes like React components - **React Integration**: Full access to hooks, context, state management - **Reusability**: Create and share 3D component libraries - **Performance**: Automatic render optimization and reconciliation - **Ecosystem**: Works with Drei helpers, Zustand, Framer Motion, etc. - **TypeScript Support**: Full type safety for Three.js objects --- ## Core Concepts ### 1. Canvas Component The `` component sets up a Three.js scene, camera, renderer, and render loop. ```jsx import { Canvas } from '@react-three/fiber' function App() { return ( {/* 3D content goes here */} ) } ``` **Canvas Props**: - `camera` - Camera configuration (position, fov, near, far) - `gl` - WebGL renderer settings - `dpr` - Device pixel ratio (default: [1, 2]) - `shadows` - Enable shadow mapping (default: false) - `frameloop` - "always" (default), "demand", or "never" - `flat` - Disable color management for simpler colors - `linear` - Use linear color space instead of sRGB ### 2. Declarative 3D Objects Three.js objects are created using JSX with kebab-case props: ```jsx // THREE.Mesh + THREE.BoxGeometry + THREE.MeshStandardMaterial ``` **Prop Mapping**: - `position` → `object.position.set(x, y, z)` - `rotation` → `object.rotation.set(x, y, z)` - `scale` → `object.scale.set(x, y, z)` - `args` → Constructor arguments for geometry/material - `attach` → Attach to parent property (e.g., `attach="material"`) **Shorthand Notation**: ```jsx // Full notation // Axis-specific (dash notation) ``` ### 3. useFrame Hook Execute code on every frame (animation loop): ```jsx import { useFrame } from '@react-three/fiber' import { useRef } from 'react' function RotatingBox() { const meshRef = useRef() useFrame((state, delta) => { // Rotate mesh on every frame meshRef.current.rotation.x += delta meshRef.current.rotation.y += delta * 0.5 // Access scene state const time = state.clock.elapsedTime meshRef.current.position.y = Math.sin(time) * 2 }) return ( ) } ``` **useFrame Parameters**: - `state` - Scene state (camera, scene, gl, clock, etc.) - `delta` - Time since last frame (for frame-rate independence) - `xrFrame` - XR frame data (for VR/AR) **Important**: Never use `setState` inside `useFrame` - it causes unnecessary re-renders! ### 4. useThree Hook Access scene state and methods: ```jsx import { useThree } from '@react-three/fiber' function CameraInfo() { const { camera, gl, scene, size, viewport } = useThree() // Selective subscription (only re-render on size change) const size = useThree((state) => state.size) // Get state non-reactively const get = useThree((state) => state.get) const freshState = get() // Latest state without triggering re-render return null } ``` **Available State**: - `camera` - Default camera - `scene` - Three.js scene - `gl` - WebGL renderer - `size` - Canvas dimensions - `viewport` - Viewport dimensions in 3D units - `clock` - Three.js clock - `pointer` - Normalized mouse coordinates - `invalidate()` - Manually trigger render - `setSize()` - Manually resize canvas ### 5. useLoader Hook Load assets with automatic caching and Suspense integration: ```jsx import { Suspense } from 'react' import { useLoader } from '@react-three/fiber' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { TextureLoader } from 'three' function Model() { const gltf = useLoader(GLTFLoader, '/model.glb') return } function TexturedMesh() { const texture = useLoader(TextureLoader, '/texture.jpg') return ( ) } function App() { return ( }> ) } ``` **Loading Multiple Assets**: ```jsx const [texture1, texture2, texture3] = useLoader(TextureLoader, [ '/tex1.jpg', '/tex2.jpg', '/tex3.jpg' ]) ``` **Loader Extensions**: ```jsx import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader' useLoader(GLTFLoader, '/model.glb', (loader) => { const dracoLoader = new DRACOLoader() dracoLoader.setDecoderPath('/draco/') loader.setDRACOLoader(dracoLoader) }) ``` **Pre-loading**: ```jsx // Pre-load assets before component mounts useLoader.preload(GLTFLoader, '/model.glb') ``` --- ## Common Patterns ### Pattern 1: Basic Scene Setup ```jsx import { Canvas } from '@react-three/fiber' function Scene() { return ( <> {/* Lights */} {/* Objects */} ) } function App() { return ( ) } ``` ### Pattern 2: Interactive Objects (Click, Hover) ```jsx import { useState } from 'react' function InteractiveBox() { const [hovered, setHovered] = useState(false) const [active, setActive] = useState(false) return ( setActive(!active)} onPointerOver={() => setHovered(true)} onPointerOut={() => setHovered(false)} > ) } ``` ### Pattern 3: Animated Component with useFrame ```jsx import { useRef } from 'react' import { useFrame } from '@react-three/fiber' function AnimatedSphere() { const meshRef = useRef() useFrame((state, delta) => { // Rotate meshRef.current.rotation.y += delta // Oscillate position const time = state.clock.elapsedTime meshRef.current.position.y = Math.sin(time) * 2 }) return ( ) } ``` ### Pattern 4: Loading GLTF Models ```jsx import { Suspense } from 'react' import { useLoader } from '@react-three/fiber' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' function Model({ url }) { const gltf = useLoader(GLTFLoader, url) return ( ) } function App() { return ( }> ) } function LoadingPlaceholder() { return ( ) } ``` ### Pattern 5: Multiple Lights ```jsx function Lighting() { return ( <> {/* Ambient light for base illumination */} {/* Directional light with shadows */} {/* Point light for accent */} {/* Spot light for focused illumination */} ) } ``` ### Pattern 6: Instancing (Many Objects) ```jsx import { useMemo, useRef } from 'react' import * as THREE from 'three' import { useFrame } from '@react-three/fiber' function Particles({ count = 1000 }) { const meshRef = useRef() // Generate random positions const particles = useMemo(() => { const temp = [] for (let i = 0; i < count; i++) { const t = Math.random() * 100 const factor = 20 + Math.random() * 100 const speed = 0.01 + Math.random() / 200 const x = Math.random() * 2 - 1 const y = Math.random() * 2 - 1 const z = Math.random() * 2 - 1 temp.push({ t, factor, speed, x, y, z, mx: 0, my: 0 }) } return temp }, [count]) const dummy = useMemo(() => new THREE.Object3D(), []) useFrame(() => { particles.forEach((particle, i) => { let { t, factor, speed, x, y, z } = particle t = particle.t += speed / 2 const a = Math.cos(t) + Math.sin(t * 1) / 10 const b = Math.sin(t) + Math.cos(t * 2) / 10 const s = Math.cos(t) dummy.position.set( x + Math.cos((t / 10) * factor) + (Math.sin(t * 1) * factor) / 10, y + Math.sin((t / 10) * factor) + (Math.cos(t * 2) * factor) / 10, z + Math.cos((t / 10) * factor) + (Math.sin(t * 3) * factor) / 10 ) dummy.scale.set(s, s, s) dummy.updateMatrix() meshRef.current.setMatrixAt(i, dummy.matrix) }) meshRef.current.instanceMatrix.needsUpdate = true }) return ( ) } ``` ### Pattern 7: Groups and Nesting ```jsx function Robot() { return ( {/* Body */} {/* Head */} {/* Arms */} ) } ``` --- ## Integration with Drei Helpers [Drei](https://github.com/pmndrs/drei) is the essential helper library for R3F, providing ready-to-use components: ### OrbitControls ```jsx import { OrbitControls } from '@react-three/drei' ``` ### Environment & Lighting ```jsx import { Environment, ContactShadows } from '@react-three/drei' {/* HDRI environment map */} {/* Or custom */} {/* Soft contact shadows */} ``` ### Text ```jsx import { Text, Text3D } from '@react-three/drei' // 2D Billboard text Hello World // 3D extruded text 3D Text ``` ### useGLTF Hook (Drei) ```jsx import { useGLTF } from '@react-three/drei' function Model() { const { scene, materials, nodes } = useGLTF('/model.glb') return } // Pre-load useGLTF.preload('/model.glb') ``` ### Center & Bounds ```jsx import { Center, Bounds, useBounds } from '@react-three/drei' // Auto-center objects // Auto-fit camera to bounds ``` ### HTML Overlay ```jsx import { Html } from '@react-three/drei'
This is a box
``` ### Scroll Controls ```jsx import { ScrollControls, Scroll, useScroll } from '@react-three/drei' import { useFrame } from '@react-three/fiber' function AnimatedScene() { const scroll = useScroll() const meshRef = useRef() useFrame(() => { const offset = scroll.offset // 0-1 normalized scroll position meshRef.current.position.y = offset * 10 }) return ... } {/* HTML overlay */}

Scrollable content

``` --- ## Integration with Other Libraries ### With GSAP ```jsx import { useRef, useEffect } from 'react' import { useFrame } from '@react-three/fiber' import gsap from 'gsap' function AnimatedBox() { const meshRef = useRef() useEffect(() => { // GSAP timeline animation const tl = gsap.timeline({ repeat: -1, yoyo: true }) tl.to(meshRef.current.position, { y: 2, duration: 1, ease: 'power2.inOut' }) .to(meshRef.current.rotation, { y: Math.PI * 2, duration: 2, ease: 'none' }, 0) return () => tl.kill() }, []) return ( ) } ``` ### With Framer Motion ```jsx import { motion } from 'framer-motion-3d' function AnimatedSphere() { return ( ) } ``` ### With Zustand (State Management) ```jsx import create from 'zustand' const useStore = create((set) => ({ color: 'orange', setColor: (color) => set({ color }) })) function Box() { const color = useStore((state) => state.color) const setColor = useStore((state) => state.setColor) return ( setColor('hotpink')}> ) } ``` --- ## Performance Optimization ### 1. On-Demand Rendering ```jsx {/* Only renders when needed */} // Manually trigger render function MyComponent() { const invalidate = useThree((state) => state.invalidate) return ( invalidate()}> ) } ``` ### 2. Instancing Use `` for rendering many identical objects: ```jsx function Particles({ count = 10000 }) { const meshRef = useRef() useEffect(() => { const temp = new THREE.Object3D() for (let i = 0; i < count; i++) { temp.position.set( Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5 ) temp.updateMatrix() meshRef.current.setMatrixAt(i, temp.matrix) } meshRef.current.instanceMatrix.needsUpdate = true }, [count]) return ( ) } ``` ### 3. Frustum Culling Objects outside the camera view are automatically culled. ```jsx // Disable for always-visible objects ``` ### 4. LOD (Level of Detail) ```jsx import { Detailed } from '@react-three/drei' {/* High detail - close to camera */} {/* Medium detail */} {/* Low detail - far from camera */} ``` ### 5. Adaptive Performance ```jsx import { AdaptiveDpr, AdaptiveEvents, PerformanceMonitor } from '@react-three/drei' {/* Reduce DPR when performance drops */} {/* Reduce raycast frequency */} {/* Monitor and respond to performance */} console.log('Performance improved')} onDecline={() => console.log('Performance degraded')} > ``` ### 6. Selective Re-renders Use `useThree` selectors to avoid unnecessary re-renders: ```jsx // ❌ Re-renders on any state change const state = useThree() // ✅ Only re-renders when size changes const size = useThree((state) => state.size) // ✅ Only re-renders when camera changes const camera = useThree((state) => state.camera) ``` --- ## Common Pitfalls & Solutions ### ❌ Pitfall 1: setState in useFrame ```jsx // ❌ BAD: Triggers React re-renders every frame const [x, setX] = useState(0) useFrame(() => setX((x) => x + 0.1)) return ``` ✅ **Solution**: Mutate refs directly ```jsx // ✅ GOOD: Direct mutation, no re-renders const meshRef = useRef() useFrame((state, delta) => { meshRef.current.position.x += delta }) return ``` ### ❌ Pitfall 2: Creating Objects in Render ```jsx // ❌ BAD: Creates new Vector3 every render ``` ✅ **Solution**: Use arrays or useMemo ```jsx // ✅ GOOD: Use array notation // Or useMemo for complex objects const position = useMemo(() => new THREE.Vector3(1, 2, 3), []) ``` ### ❌ Pitfall 3: Not Using useLoader Cache ```jsx // ❌ BAD: Loads texture every render function Component() { const [texture, setTexture] = useState() useEffect(() => { new TextureLoader().load('/texture.jpg', setTexture) }, []) return texture ? : null } ``` ✅ **Solution**: Use useLoader (automatic caching) ```jsx // ✅ GOOD: Cached and reused function Component() { const texture = useLoader(TextureLoader, '/texture.jpg') return } ``` ### ❌ Pitfall 4: Conditional Mounting (Expensive) ```jsx // ❌ BAD: Unmounts and remounts (expensive) {stage === 1 && } {stage === 2 && } {stage === 3 && } ``` ✅ **Solution**: Use visibility prop ```jsx // ✅ GOOD: Components stay mounted, just hidden function Stage1({ visible, ...props }) { return ... } ``` ### ❌ Pitfall 5: useThree Outside Canvas ```jsx // ❌ BAD: Crashes - useThree must be inside Canvas function App() { const { size } = useThree() return ... } ``` ✅ **Solution**: Use hooks inside Canvas children ```jsx // ✅ GOOD: useThree inside Canvas child function CameraInfo() { const { size } = useThree() return null } function App() { return ( ) } ``` ### ❌ Pitfall 6: Not Disposing Resources ```jsx // ❌ BAD: Memory leak - textures not disposed const texture = useLoader(TextureLoader, '/texture.jpg') ``` ✅ **Solution**: R3F handles disposal automatically, but be careful with manual Three.js objects ```jsx // ✅ GOOD: Manual cleanup when needed useEffect(() => { const geometry = new THREE.SphereGeometry(1) const material = new THREE.MeshBasicMaterial() return () => { geometry.dispose() material.dispose() } }, []) ``` --- ## Best Practices ### 1. Component Composition Break scenes into reusable components: ```jsx function Lights() { return ( <> ) } function Scene() { return ( <> ) } ``` ### 2. Suspend Heavy Assets Always wrap async operations in Suspense: ```jsx }> ``` ### 3. Use TypeScript ```typescript import { ThreeElements } from '@react-three/fiber' function Box(props: ThreeElements['mesh']) { return ( ) } ``` ### 4. Organize by Feature ``` src/ components/ 3d/ Scene.tsx Lights.tsx Camera.tsx models/ Robot.tsx Character.tsx effects/ PostProcessing.tsx ``` ### 5. Test with React DevTools Profiler Monitor re-renders and optimize components causing performance issues. --- ## Resources ### References - `references/api_reference.md` - Complete R3F & Drei API documentation - `references/hooks_guide.md` - Detailed hooks usage and patterns - `references/drei_helpers.md` - Comprehensive Drei library guide ### Scripts - `scripts/component_generator.py` - Generate R3F component boilerplate - `scripts/scene_setup.py` - Initialize R3F scene with common patterns ### Assets - `assets/starter_r3f/` - Complete R3F + Vite starter template - `assets/examples/` - Real-world R3F component examples ### External Resources - [Official Docs](https://docs.pmnd.rs/react-three-fiber) - [Drei Docs](https://github.com/pmndrs/drei) - [Three.js Docs](https://threejs.org/docs/) - [R3F Discord](https://discord.gg/ZZjjNvJ) - [Poimandres (pmnd.rs)](https://pmnd.rs/) - Ecosystem overview

Related skills

Agent Workflows

Skill Creator

Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that exte…

Agent Workflows

Clawdhub

Use the ClawdHub CLI to search, install, update, and publish agent skills from clawdhub.com. Use when you need to fetch new skills on the fl…

Agent Workflows

Agent Team Orchestration

Orchestrate multi-agent teams with defined roles, task lifecycles, handoff protocols, and review workflows. Use when: (1) Setting up a team …

Agent Workflows

Superpowers

Spec-first, TDD, subagent-driven software development workflow. Use when: (1) building any new feature or app — triggers brainstorm → plan →…