npx skills add smithery/emalorenzo --skill r3f-best-practices
smithery/neversight
r3f-best-practices
React Three Fiber (R3F) and Poimandres ecosystem best practices. Use when writing, reviewing, or optimizing R3F code. Triggers on tasks involving @react-three/fiber, @react-three/drei, zustand, @react-three/postprocessing, @react-three/rapier, or leva.
Installation
npx skills add smithery/neversight --skill r3f-best-practices
Similar popular skills
Related neighbors and high-traction skills in the same topics — useful to compare before installing.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill shoul…
3.7K installsUse when doing ANY task involving Supabase. Triggers: Supabase products (Database, Auth, Edge F…
1.7K installsReact Native and Expo best practices for building performant mobile apps. Use when building Rea…
1.3K installsRouter for all Remotion skills
5.7K installsPostgres best practices maintained by Supabase, for Postgres running anywhere. Load this skill …
1.4K installsConfigure Better Auth server and client, set up database adapters, manage sessions, add plugins…
330 installsAlso in this package
Other skills from smithery/neversight · top by installs.
npx skills add smithery/neversight
More details
Agent compatibility
Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.
Also listed on
Alternate registries and mirrors of this skill.
Skill metadata
Parsed from SKILL.md frontmatter.
More metadata
- author
- three-agent-skills
- version
- 1.0.0
Package contents
Files included with this skill beyond the listing page.
-
skill md
SKILL.md7,353 B -
docs
SUMMARY.md278 B
History
- First recorded snapshot · 0 installs
SKILL.md
React Three Fiber Best Practices
Comprehensive guide for React Three Fiber and the Poimandres ecosystem. Contains 60+ rules across 11 categories, prioritized by impact.
When to Apply
Reference these guidelines when:
- Writing new R3F components
- Optimizing R3F performance (re-renders are the #1 issue)
- Using Drei helpers correctly
- Managing state with Zustand
- Implementing post-processing or physics
Ecosystem Coverage
- @react-three/fiber - React renderer for Three.js
- @react-three/drei - Useful helpers and abstractions
- @react-three/postprocessing - Post-processing effects
- @react-three/rapier - Physics engine
- zustand - State management
- leva - Debug GUI
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Performance & Re-renders | CRITICAL | perf- |
| 2 | useFrame & Animation | CRITICAL | frame- |
| 3 | Component Patterns | HIGH | component- |
| 4 | Canvas & Setup | HIGH | canvas- |
| 5 | Drei Helpers | MEDIUM-HIGH | drei- |
| 6 | Loading & Suspense | MEDIUM-HIGH | loading- |
| 7 | State Management | MEDIUM | state- |
| 8 | Events & Interaction | MEDIUM | events- |
| 9 | Post-processing | MEDIUM | postpro- |
| 10 | Physics (Rapier) | LOW-MEDIUM | physics- |
| 11 | Leva (Debug GUI) | LOW | leva- |
Quick Reference
1. Performance & Re-renders (CRITICAL)
perf-never-set-state-in-useframe- NEVER call setState in useFrameperf-isolate-state- Isolate components that need React stateperf-zustand-selectors- Use Zustand selectors, not entire storeperf-transient-subscriptions- Use transient subscriptions for continuous valuesperf-memo-components- Memoize expensive componentsperf-keys-for-lists- Use stable keys for dynamic listsperf-avoid-inline-objects- Avoid creating objects/arrays in JSXperf-dispose-auto- Understand R3F auto-dispose behavior
2. useFrame & Animation (CRITICAL)
frame-priority- Use priority for execution orderframe-delta-time- Always use delta for animationsframe-conditional-subscription- Disable useFrame when not neededframe-destructure-state- Destructure only what you needframe-render-on-demand- Use invalidate() for on-demand renderingframe-avoid-heavy-computation- Move heavy work outside useFrame
3. Component Patterns (HIGH)
component-jsx-elements- Use JSX for Three.js objectscomponent-attach-prop- Use attach for non-standard propertiescomponent-primitive- Use primitive for existing objectscomponent-extend- Use extend() for custom classescomponent-forwardref- Use forwardRef for reusable componentscomponent-dispose-null- Set dispose={null} on shared resources
4. Canvas & Setup (HIGH)
canvas-size-container- Canvas fills parent containercanvas-camera-default- Configure camera via propcanvas-gl-config- Configure WebGL contextcanvas-shadows- Enable shadows at Canvas levelcanvas-frameloop- Choose appropriate frameloop modecanvas-events- Configure event handlingcanvas-linear-flat- Use linear/flat for correct colors
5. Drei Helpers (MEDIUM-HIGH)
drei-use-gltf- useGLTF with preloadingdrei-use-texture- useTexture for texture loadingdrei-environment- Environment for realistic lightingdrei-orbit-controls- OrbitControls from Dreidrei-html- Html for DOM overlaysdrei-text- Text for 3D textdrei-instances- Instances for optimized instancingdrei-use-helper- useHelper for debug visualizationdrei-bounds- Bounds to fit cameradrei-center- Center to center objectsdrei-float- Float for floating animation
6. Loading & Suspense (MEDIUM-HIGH)
loading-suspense- Wrap async components in Suspenseloading-preload- Preload assets with useGLTF.preloadloading-use-progress- useProgress for loading UIloading-lazy-components- Lazy load heavy componentsloading-error-boundary- Handle loading errors
7. State Management (MEDIUM)
state-zustand-store- Create focused Zustand storesstate-avoid-objects-in-store- Be careful with Three.js objectsstate-subscribeWithSelector- Fine-grained subscriptionsstate-persist- Persist state when neededstate-separate-concerns- Separate stores by concern
8. Events & Interaction (MEDIUM)
events-pointer-events- Use pointer events on meshesevents-stop-propagation- Prevent event bubblingevents-cursor-pointer- Change cursor on hoverevents-raycast-filter- Filter raycastingevents-event-data- Understand event data structure
9. Post-processing (MEDIUM)
postpro-effect-composer- Use EffectComposerpostpro-common-effects- Common effects referencepostpro-selective-bloom- SelectiveBloom for optimized glowpostpro-custom-shader- Create custom effectspostpro-performance- Optimize post-processing
10. Physics Rapier (LOW-MEDIUM)
physics-setup- Basic Rapier setupphysics-body-types- dynamic, fixed, kinematicphysics-colliders- Choose appropriate collidersphysics-events- Handle collision eventsphysics-api-ref- Use ref for physics APIphysics-performance- Optimize physics
11. Leva (LOW)
leva-basic- Basic Leva usageleva-folders- Organize with foldersleva-conditional- Hide in production
How to Use
Read individual rule files for detailed explanations and code examples:
rules/perf-never-set-state-in-useframe.md
rules/drei-use-gltf.md
rules/state-zustand-selectors.md
Full Compiled Document
For the complete guide with all rules expanded: ../R3FBESTPRACTICES.md
Critical Patterns
NEVER setState in useFrame
// BAD - 60 re-renders per second!
function BadComponent() {
const [position, setPosition] = useState(0);
useFrame(() => {
setPosition(p => p + 0.01); // NEVER DO THIS
});
return <mesh position-x={position} />;
}
// GOOD - Mutate refs directly
function GoodComponent() {
const meshRef = useRef();
useFrame(() => {
meshRef.current.position.x += 0.01;
});
return <mesh ref={meshRef} />;
}
Zustand Selectors
// BAD - Re-renders on ANY store change
const store = useGameStore();
// GOOD - Only re-renders when playerX changes
const playerX = useGameStore(state => state.playerX);
// BETTER - No re-renders, direct mutation
useFrame(() => {
const { value } = useStore.getState();
ref.current.position.x = value;
});
Drei useGLTF
import { useGLTF } from '@react-three/drei';
function Model() {
const { scene } = useGLTF('/model.glb');
return <primitive object={scene} />;
}
// Preload for instant loading
useGLTF.preload('/model.glb');
Suspense Loading
function App() {
return (
<Canvas>
<Suspense fallback={<Loader />}>
<Model />
</Suspense>
</Canvas>
);
}