MCPInstall

r3f-fundamentals

React Three Fiber core setup, Canvas configuration, scene hierarchy, camera systems, lighting, render loop, and React integration patterns. Use when setting up a new R3F project, configuring the Canvas component, managing scene structure, or understanding the declarative Three.js-in-React paradigm. The foundational skill that all other R3F skills depend on.

Installs
122
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill r3f-fundamentals
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads r3f-fundamentals automatically when relevant.

  3. 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.

React Three Fiber Fundamentals

Declarative Three.js via React components. R3F maps Three.js objects to JSX elements with automatic disposal, reactive updates, and React lifecycle integration.

Quick Start

import { Canvas } from '@react-three/fiber';

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} />
      <mesh>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>
    </Canvas>
  );
}

Core Principle: Declarative Scene Graph

R3F converts Three.js imperative API to React's declarative model:

Three.js (Imperative)R3F (Declarative)
new THREE.Mesh()<mesh>
mesh.position.set(1, 2, 3)<mesh position={[1, 2, 3]}>
scene.add(mesh)JSX nesting handles hierarchy
mesh.geometry.dispose()Automatic on unmount

Canvas Configuration

import { Canvas } from '@react-three/fiber';

<Canvas
  // Renderer settings
  gl={{ antialias: true, alpha: false, powerPreference: 'high-performance' }}
  dpr={[1, 2]}                    // Device pixel ratio range
  shadows                          // Enable shadow maps
  
  // Camera (default: PerspectiveCamera)
  camera={{ 
    fov: 75, 
    near: 0.1, 
    far: 1000, 
    position: [0, 0, 5] 
  }}
  
  // Or use orthographic
  orthographic
  camera={{ zoom: 50, position: [0, 0, 100] }}
  
  // Performance
  frameloop="demand"              // 'always' | 'demand' | 'never'
  performance={{ min: 0.5 }}      // Adaptive performance
  
  // Events
  onCreated={({ gl, scene, camera }) => {
    // Access Three.js objects after mount
  }}
  
  // Sizing
  style={{ width: '100vw', height: '100vh' }}
/>

Frameloop Modes

ModeWhen to Use
alwaysContinuous animation (games, simulations)
demandStatic scenes, only re-render on state change
neverManual control via invalidate()
// Demand mode with manual invalidation
import { useThree } from '@react-three/fiber';

function Controls() {
  const invalidate = useThree(state => state.invalidate);
  
  const handleDrag = () => {
    // Update state...
    invalidate(); // Request re-render
  };
}

Scene Hierarchy

JSX nesting = Three.js parent-child relationships:

<group position={[0, 2, 0]} rotation={[0, Math.PI / 4, 0]}>
  {/* Children inherit parent transforms */}
  <mesh position={[1, 0, 0]}>
    <sphereGeometry args={[0.5, 32, 32]} />
    <meshStandardMaterial color="blue" />
  </mesh>
  
  <mesh position={[-1, 0, 0]}>
    <boxGeometry args={[0.8, 0.8, 0.8]} />
    <meshStandardMaterial color="red" />
  </mesh>
</group>

Common Container Components

// Group: Transform container (no rendering)
<group position={[0, 0, 0]} />

// Object3D: Base class, rarely used directly
<object3D />

// Scene: Usually implicit (Canvas creates one)
<scene />

Camera Systems

Default Perspective Camera

<Canvas camera={{ 
  fov: 75,              // Field of view (degrees)
  aspect: width/height, // Auto-calculated
  near: 0.1,            // Near clipping plane
  far: 1000,            // Far clipping plane
  position: [0, 5, 10]
}} />

Custom Camera Component

import { PerspectiveCamera } from '@react-three/drei';

function Scene() {
  return (
    <>
      <PerspectiveCamera 
        makeDefault           // Set as active camera
        fov={60} 
        position={[0, 2, 8]} 
      />
      {/* Scene contents */}
    </>
  );
}

Camera Access

import { useThree } from '@react-three/fiber';

function CameraController() {
  const { camera } = useThree();
  
  useEffect(() => {
    camera.lookAt(0, 0, 0);
  }, [camera]);
  
  return null;
}

Lighting

Light Types

// Ambient: Uniform, directionless
<ambientLight intensity={0.4} color="#ffffff" />

// Directional: Sun-like, parallel rays
<directionalLight 
  position={[5, 10, 5]} 
  intensity={1} 
  castShadow 
/>

// Point: Radiates from position
<pointLight 
  position={[0, 5, 0]} 
  intensity={1} 
  distance={20}        // Range (0 = infinite)
  decay={2}            // Physical falloff
/>

// Spot: Cone-shaped
<spotLight 
  position={[0, 10, 0]} 
  angle={Math.PI / 6}  // Cone angle
  penumbra={0.5}       // Edge softness
  castShadow 
/>

// Hemisphere: Sky/ground gradient
<hemisphereLight 
  skyColor="#87ceeb" 
  groundColor="#362907" 
  intensity={0.6} 
/>

Shadow Setup

<Canvas shadows>
  <directionalLight
    castShadow
    position={[10, 10, 10]}
    shadow-mapSize={[2048, 2048]}
    shadow-camera-far={50}
    shadow-camera-left={-10}
    shadow-camera-right={10}
    shadow-camera-top={10}
    shadow-camera-bottom={-10}
  />
  
  <mesh castShadow>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>
  
  <mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]} position={[0, -1, 0]}>
    <planeGeometry args={[20, 20]} />
    <meshStandardMaterial />
  </mesh>
</Canvas>

Render Loop (useFrame)

useFrame runs every frame (60fps target). This is where animation happens.

import { useFrame, useThree } from '@react-three/fiber';
import { useRef } from 'react';

function RotatingBox() {
  const meshRef = useRef<THREE.Mesh>(null!);
  
  useFrame((state, delta) => {
    // state: R3F state (camera, scene, clock, etc.)
    // delta: Time since last frame (seconds)
    
    meshRef.current.rotation.x += delta;
    meshRef.current.rotation.y += delta * 0.5;
  });
  
  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshNormalMaterial />
    </mesh>
  );
}

useFrame State Object

useFrame((state) => {
  state.clock        // THREE.Clock
  state.clock.elapsedTime  // Total time (seconds)
  state.camera       // Active camera
  state.scene        // Scene object
  state.gl           // WebGLRenderer
  state.size         // { width, height }
  state.viewport     // { width, height, factor, distance }
  state.mouse        // Normalized mouse position [-1, 1]
  state.raycaster    // THREE.Raycaster
});

Render Priority

// Lower priority runs first, higher runs later
// Default is 0

useFrame(() => {
  // Update physics
}, -1);  // Runs before default

useFrame(() => {
  // Update visuals
}, 0);   // Default

useFrame(() => {
  // Post-processing / camera
}, 1);   // Runs after default

Accessing Three.js Objects

useThree Hook

import { useThree } from '@react-three/fiber';

function SceneInfo() {
  const { 
    gl,           // WebGLRenderer
    scene,        // THREE.Scene
    camera,       // Active camera
    size,         // Canvas dimensions
    viewport,     // Viewport in Three.js units
    clock,        // THREE.Clock
    set,          // Update state
    get,          // Get current state
    invalidate,   // Request re-render (demand mode)
    advance,      // Advance one frame (never mode)
  } = useThree();
  
  return null;
}

Refs for Direct Access

import { useRef } from 'react';
import * as THREE from 'three';

function DirectAccess() {
  const meshRef = useRef<THREE.Mesh>(null!);
  const materialRef = useRef<THREE.MeshStandardMaterial>(null!);
  
  useEffect(() => {
    // Direct Three.js API access
    meshRef.current.geometry.computeBoundingBox();
    materialRef.current.needsUpdate = true;
  }, []);
  
  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial ref={materialRef} />
    </mesh>
  );
}

Events

R3F provides pointer events on meshes:

<mesh
  onClick={(e) => console.log('click', e.point)}
  onContextMenu={(e) => console.log('right click')}
  onDoubleClick={(e) => console.log('double click')}
  onPointerOver={(e) => console.log('hover')}
  onPointerOut={(e) => console.log('unhover')}
  onPointerDown={(e) => console.log('down')}
  onPointerUp={(e) => console.log('up')}
  onPointerMove={(e) => console.log('move')}
>
  <boxGeometry />
  <meshStandardMaterial />
</mesh>

Event Object

onClick={(e) => {
  e.stopPropagation();    // Stop event bubbling
  e.point                 // THREE.Vector3 intersection point
  e.distance              // Distance from camera
  e.object                // Intersected object
  e.face                  // Intersected face
  e.faceIndex             // Face index
  e.uv                    // UV coordinates
  e.camera                // Camera used for raycasting
  e.delta                 // Distance from last event
}}

Suspense & Loading

R3F integrates with React Suspense for async loading:

import { Suspense } from 'react';
import { useLoader } from '@react-three/fiber';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

function Model() {
  const gltf = useLoader(GLTFLoader, '/model.glb');
  return <primitive object={gltf.scene} />;
}

function App() {
  return (
    <Canvas>
      <Suspense fallback={<LoadingSpinner />}>
        <Model />
      </Suspense>
    </Canvas>
  );
}

function LoadingSpinner() {
  const meshRef = useRef<THREE.Mesh>(null!);
  useFrame((_, delta) => {
    meshRef.current.rotation.z += delta * 2;
  });
  
  return (
    <mesh ref={meshRef}>
      <torusGeometry args={[1, 0.2, 16, 32]} />
      <meshBasicMaterial color="white" wireframe />
    </mesh>
  );
}

Dependencies

{
  "dependencies": {
    "@react-three/fiber": "^8.15.0",
    "three": "^0.160.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/three": "^0.160.0"
  }
}

File Structure

r3f-fundamentals/
├── SKILL.md
├── references/
│   ├── canvas-props.md       # Complete Canvas prop reference
│   ├── hooks-api.md          # useThree, useFrame, useLoader
│   └── event-system.md       # Event handling deep-dive
└── scripts/
    ├── templates/
    │   ├── basic-scene.tsx   # Minimal starter
    │   ├── lit-scene.tsx     # With proper lighting
    │   └── interactive.tsx   # With events and animation
    └── utils/
        └── canvas-config.ts  # Preset configurations

Reference

  • references/canvas-props.md — Complete Canvas configuration options
  • references/hooks-api.md — All R3F hooks with examples
  • references/event-system.md — Pointer events and raycasting

FAQ

What does the r3f-fundamentals skill do?

React Three Fiber core setup, Canvas configuration, scene hierarchy, camera systems, lighting, render loop, and React integration patterns. Use when setting up a new R3F project, configuring the Canvas component, managing scene structure, or understanding the declarative Three.js-in-React paradigm. The foundational skill that all other R3F skills depend on.

How do I install r3f-fundamentals?

Run npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill r3f-fundamentals 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/r3f-fundamentals/ (personal) or .claude/skills/r3f-fundamentals/ (project).

Which AI agents can use r3f-fundamentals?

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 r3f-fundamentals 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 r3f-fundamentals?

It is published by bbeierle12 in bbeierle12/skill-mcp-claude. It has 122 recorded installs.

More from bbeierle12/skill-mcp-claude

View all →

gsap-react

bbeierle12/skill-mcp-claude

GSAP integration with React including useGSAP hook, ref handling, cleanup patterns, and context management. Use when implementing GSAP animations in React components, handling component lifecycle, or building reusable animation hooks.

Frontend & Design724 installs

gsap-scrolltrigger

bbeierle12/skill-mcp-claude

Scroll-based animations using GSAP ScrollTrigger plugin including pinning, scrubbing, snap points, and parallax effects. Use when creating scroll-driven animations, sticky sections, progress indicators, or parallax scrolling experiences.

AI & Agents605 installs

gsap-fundamentals

bbeierle12/skill-mcp-claude

Core GSAP animation concepts including tweens, timelines, easing functions, and animation properties. Use when implementing basic animations, transitions, or learning GSAP foundations. Essential starting point for any GSAP-based animation work.

Frontend & Design282 installs

shader-effects

bbeierle12/skill-mcp-claude

Visual shader effects—glow/bloom, chromatic aberration, distortion, vignette, film grain, scanlines, glitch, dissolve, outline, and fresnel. Use when adding visual polish, post-processing effects, or stylized rendering to shaders.

AI & Agents214 installs

d3js-visualization

bbeierle12/skill-mcp-claude

Open the skill to read its SKILL.md instructions.

AI & Agents186 installs

particles-gpu

bbeierle12/skill-mcp-claude

GPU-based particle systems using instanced rendering, buffer attributes, Points geometry, and custom shaders. Use when rendering thousands to millions of particles efficiently, creating particle effects like snow, rain, stars, or abstract visualizations.

AI & Agents169 installs

Popular frontend & design skills

View category →

setup-matt-pocock-skills

mattpocock/skills

Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.

Frontend & Design1.1M installs

frontend-design

anthropics/skills

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

OfficialFrontend & Design1M installs

hyperframes-animation

heygen-com/hyperframes

All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.

prototype

mattpocock/skills

Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.

Frontend & Design999.2K installs

hyperframes-core

heygen-com/hyperframes

The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.

Frontend & Design930.5K installs

vercel-react-best-practices

vercel-labs/agent-skills

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.

OfficialFrontend & Design843.1K installs