Skip to content
Back to skills

3d Web Experience

ASecurity

Build immersive 3D web experiences with Three.js, React Three Fiber, Spline, and WebGL. Covers product configurators, 3D portfolios, scroll-driven 3D, model pipeline optimization, performance budgets, and interactive scenes. Use when building 3D websites, three.js scenes, or WebGL experiences.

  • 67 stars
  • 0 votes
  • 3 copies
  • 13 views
  • Added May 26, 2026
developmentgoreactperformance

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add RaheesAhmed/SajiCode --skill 3d-web-experience --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 3d Web Experience?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 3d Web Experience
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/raheesahmed-3d-web-experience/badge)](https://www.skillsdirectory.com/skills/raheesahmed-3d-web-experience)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: 3d-web-experience
description: Build immersive 3D web experiences with Three.js, React Three Fiber, Spline, and WebGL. Covers product configurators, 3D portfolios, scroll-driven 3D, model pipeline optimization, performance budgets, and interactive scenes. Use when building 3D websites, three.js scenes, or WebGL experiences.
---

# 3D Web Experience

**Role**: 3D Web Experience Architect — bringing depth to the web with purpose and performance.

## Stack Selection

| Tool | Best For | Learning Curve | Control |
|------|----------|----------------|---------|
| Spline | Quick prototypes, designer handoff | Low | Medium |
| React Three Fiber | React apps, complex scenes | Medium | High |
| Three.js vanilla | Max control, non-React projects | High | Maximum |
| Babylon.js | Game-like experiences, heavy 3D | High | Maximum |

### Decision Tree
```
Quick 3D element needed? → Spline
Using React? → React Three Fiber (R3F)
Need max performance/control? → Three.js vanilla
Building a game? → Babylon.js
```

## React Three Fiber Setup

```tsx
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Environment, useGLTF, Float } from "@react-three/drei";
import { Suspense } from "react";

function Model({ url }: { url: string }) {
  const { scene } = useGLTF(url);
  return <primitive object={scene} scale={1} />;
}

function LoadingFallback() {
  return (
    <mesh>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color="#8b5cf6" wireframe />
    </mesh>
  );
}

export default function Scene() {
  return (
    <Canvas camera={{ position: [0, 2, 5], fov: 45 }} dpr={[1, 2]}>
      <ambientLight intensity={0.5} />
      <directionalLight position={[5, 5, 5]} intensity={1} castShadow />
      <Suspense fallback={<LoadingFallback />}>
        <Float speed={2} rotationIntensity={0.5} floatIntensity={0.5}>
          <Model url="/model.glb" />
        </Float>
        <Environment preset="city" />
      </Suspense>
      <OrbitControls enableDamping dampingFactor={0.05} />
    </Canvas>
  );
}
```

## 3D Model Pipeline

### Optimization Steps
```
1. Model in Blender/3D software
2. Reduce polygon count (< 100K for web, < 50K for mobile)
3. Bake textures (combine materials, reduce draw calls)
4. Export as GLB (binary GLTF — smallest size)
5. Compress: gltf-transform optimize input.glb output.glb --compress draco --texture-compress webp
6. Target: < 5MB total, < 2MB for mobile
```

### Loading with Progress
```tsx
import { useGLTF, useProgress, Html } from "@react-three/drei";

function Loader() {
  const { progress } = useProgress();
  return (
    <Html center>
      <div style={{ color: "white", fontSize: "1.5rem" }}>
        {progress.toFixed(0)}%
      </div>
    </Html>
  );
}
```

## Scroll-Driven 3D

### R3F + ScrollControls
```tsx
import { ScrollControls, useScroll } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import { useRef } from "react";

function ScrollModel() {
  const scroll = useScroll();
  const ref = useRef<THREE.Group>(null);

  useFrame(() => {
    if (!ref.current) return;
    ref.current.rotation.y = scroll.offset * Math.PI * 2;
    ref.current.position.y = Math.sin(scroll.offset * Math.PI) * 2;
  });

  return <group ref={ref}><Model url="/model.glb" /></group>;
}

export default function ScrollScene() {
  return (
    <Canvas style={{ height: "100vh", position: "fixed", top: 0 }}>
      <ScrollControls pages={3} damping={0.25}>
        <ScrollModel />
      </ScrollControls>
    </Canvas>
  );
}
```

### GSAP + Three.js (vanilla)
```ts
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);

gsap.to(camera.position, {
  scrollTrigger: { trigger: ".hero-section", start: "top top", end: "bottom top", scrub: 1 },
  z: 5, y: 2, duration: 1,
});
```

## Performance Budget
| Metric | Target | Measurement |
|--------|--------|-------------|
| Model file size | < 5MB | gzip compressed |
| Draw calls | < 50 | Three.js stats panel |
| Triangles | < 100K | GPU budget |
| Textures | < 2048px | Power of 2 dimensions |
| FPS | 60fps desktop, 30fps mobile | requestAnimationFrame |
| Load time | < 3s on 4G | Lighthouse |

## Anti-Patterns
- **3D for 3D's sake** — If an image works, use an image. 3D must serve a purpose.
- **Desktop-only 3D** — Test on real mobile devices. Provide static fallbacks.
- **No loading state** — Always show progress. Load 3D after page is interactive.
- **Uncompressed models** — Always run through gltf-transform pipeline.
- **No `Suspense` boundaries** — Wrap 3D content for graceful loading.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…