Skip to content
Development
Skill

/threejs-react-three-fiber

Building three.js scenes from React with React Three Fiber and drei: renderer setup, the scene graph as JSX, frame-loop, state and loading hooks, pointer events, and adaptive performance, on WebGL or with WebGPU and TSL. Use when writing React components that render three.js.

BOOST
From plugin
threejs-skills
3.7k13 skills
Install
$ npx -y skills add cloudai-x/threejs-skills --skill threejs-react-three-fiber --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/threejs-react-three-fiber

Context preview

The summary Claude sees to decide when to auto-load this skill.

Building three.js scenes from React with React Three Fiber and drei: renderer setup, the scene graph as JSX, frame-loop, state and loading hooks, pointer events, and adaptive performance, on WebGL or with WebGPU and TSL. Use when writing React components that render three.js.

SKILL.md

threejs-react-three-fiber.SKILL.md
name: threejs-react-three-fiber
description: "Building three.js scenes from React with React Three Fiber and drei: renderer setup, the scene graph as JSX, frame-loop, state and loading hooks, pointer events, and adaptive performance, on WebGL or with WebGPU and TSL. Use when writing React components that render three.js."

Three.js React Three Fiber

Targets three.js r186. Examples use WebGLRenderer; the WebGPU and TSL section uses WebGPURenderer.

Quick Start

Targets `@react-three/fiber` 9.8 with React 19 and `@react-three/drei` 10.7. The Canvas creates and owns a WebGLRenderer, a scene and a camera; three.js objects become JSX elements. The Canvas fills its parent element, so give the parent a height. The component fragments below render inside a Canvas like this one; lit materials assume its lights.

import { useRef } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";

function Box() {
  const ref = useRef();
  useFrame((_, delta) => {
    ref.current.rotation.y += delta;
  });
  return (
    <mesh ref={ref} position={[0, 0.5, 0]} castShadow>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color="#d9915b" />
    </mesh>
  );
}

export default function App() {
  return (
    <Canvas shadows="percentage" camera={{ position: [3, 2, 4], fov: 50 }}>
      <color attach="background" args={["#111827"]} />
      <ambientLight intensity={0.4} />
      <directionalLight position={[3, 4, 2]} intensity={2} castShadow />
      <Box />
      <mesh rotation-x={-Math.PI / 2} receiveShadow>
        <planeGeometry args={[10, 10]} />
        <meshStandardMaterial color="#20293a" />
      </mesh>
      <OrbitControls makeDefault />
    </Canvas>
  );
}

Canvas Props

export function App() {
  return (
    <Canvas
      shadows="variance"
      dpr={[1, 2]}
      frameloop="demand"
      flat
      camera={{ position: [0, 2, 6], fov: 45 }}
      gl={{ powerPreference: "high-performance" }}
      onCreated={(state) => state.gl.setClearColor("#111827")}
    >
      {/* scene contents */}
    </Canvas>
  );
}
  • `camera`: props for the default camera, or a camera instance. Without it you get a `PerspectiveCamera` with fov 75, near 0.1, far 1000, at z 5 looking at the origin; fiber updates aspect (or left/right/top/bottom with `orthographic`) and the projection matrix on every resize. `camera={{ manual: true }}` puts projection entirely in your hands.
  • `dpr`: a number, or `[min, max]` clamped against `window.devicePixelRatio`; the range follows display changes.
  • `shadows`: `true` enables shadow maps, a string (`'basic'`, `'percentage'`, `'variance'`) picks the filter type, an object merges into the renderer's `shadowMap` properties. `true`, `'soft'` and the default `false` all set PCFSoftShadowMap, which three swaps for PCFShadowMap with a console warning (WebGLRenderer when shadows render, WebGPURenderer on every Canvas); `'percentage'` is the same soft filter without the warning.
  • `flat` sets NoToneMapping; without it fiber applies ACESFilmicToneMapping — unlike plain three.js, tone mapping is on by default. `linear` switches the output to LinearSRGBColorSpace; the default is sRGB. `legacy` disables three's ColorManagement.
  • `gl`: props for the default `new WebGLRenderer({ canvas, antialias: true, alpha: true, powerPreference: "high-performance" })`, a renderer instance, or a factory function (the WebGPU path below).
  • `frameloop`: `'always'` renders every frame, `'demand'` renders only after React changes or `invalidate()`, `'never'` hands the loop over (call the module-level `advance(timestamp)` export with a time in seconds; `useFrame`'s delta is the difference between successive timestamps, so milliseconds make it 1000 times too large).
  • `events` replaces the event manager (the default maps DOM pointer events to raycasts); `eventSource` (an element pointer events attach to, default the Canvas wrapper) and `eventPrefix` (`'offset'` by default; `'page'`, `'client'`, `'layer'`, `'screen'` when the page scrolls or transforms the canvas) tune pointer mapping. `onCreated` runs once the renderer exists; `onPointerMissed` fires on clicks that hit nothing.

The Scene Graph as JSX

Every export of the three namespace is an element: lowercase tag, capitalized class (`<mesh>` → `THREE.Mesh`, `<meshStandardMaterial>` → its material). Props apply to the instance; shorthand values work anywhere three has a `.set()`: `position={[1, 2, 3]}`, `position={new THREE.Vector3(1, 2, 3)}`, `position={5}` (setScalar), `color="#d9915b"`. Dashed props pierce (`rotation-x`, `material-color`, `geometry-attributes-position`); `attach="material-0"` attaches into an array index.

`args` is the constructor argument list; changing it rebuilds the object from scratch. Geometries and materials attach to their parent mesh automatically — no `attach` needed.

function Torus() {
  return (
    <mesh position={[0, 1, 0]}>
      <torusKnotGeometry args={[0.7, 0.25, 128, 24]} />
      <meshStandardMaterial
        color="#42699c"
        roughness={0.2}
        metalness={0.8}
        onUpdate={(self) => console.log(self.type)}
      />
    </mesh>
  );
}

Mount an object you already hold with `<primitive object={obj} />`; one object per primitive (fiber keeps its per-object state on the object), and clone for copies. Fiber never disposes primitives — their lifetime is yours. `dispose={null}` on any element opts it out of unmount disposal. Register classes outside the three namespace with `extend`:

import { extend } from "@react-three/fiber";
import { Water } from "three/addons/objects/Water.js";

extend({ Water });
// then render <water args={[geometry]} /> anywhere in the Canvas

In TypeScript the tags `line`, `audio`, `source` and `path` collide with DOM types; write `threeLine`, `threeAudio`, `threeSource`, `threePath` (fiber strips the prefix and resolves the three class).

Hooks

`

Read more
Ships withthreejs-skills

Skill files that give Claude Code current, verified knowledge of three.js, so the code it writes runs on the release you actually install. The skills target three.js r186 (three@0.186), React Three Fiber 9.8 with drei 10.7, and gltf-transform 4.5.

Get the whole plugin

Other skills on threejs-skills.