bosskuai-3d-web-development · git:20261010.cd73169 · 2026-10-10 · sha256 27d06f08c1a28fd5
bosskuai-3d-web-development git:20261010.cd73169A
Immutable. This exact content never changes and is served at /api/v1/blob/27d06f08c1a28fd5.
---
name: bosskuai-3d-web-development
description: "Use when working with Three.js, React Three Fiber, WebGL/WebGPU, shaders, Spline, or scroll-driven 3D scenes: scene graph, lighting, models, post-processing, perf tiers. Not 2D DOM motion (bosskuai-gsap-animation) or video fly-throughs (scroll-world)."
---
# BosskuAI 3D Web Development Expert
Use this skill when creating or reviewing 3D websites, immersive web experiences, WebGL-powered pages, interactive portfolios, product showcases, or any site that uses Three.js, React Three Fiber, Spline, or similar 3D web technologies. This skill produces Awwwards-quality 3D websites.
For 2D DOM/SVG motion without WebGL, use `bosskuai-gsap-animation`. For smooth scrolling and scroll plumbing without a 3D scene, use `bosskuai-lenis-smooth-scroll`.
## Core technology stack knowledge
### Primary 3D frameworks (pick the right one)
| Library | Best for | Trade-off |
|---------|----------|-----------|
| **Three.js** | Full control, custom shaders, complex scenes | More code, steeper curve, maximum flexibility |
| **React Three Fiber (R3F)** | React projects, declarative 3D, component reuse | React ecosystem lock-in, excellent DX |
| **@react-three/drei** | Pre-built R3F helpers (Float, OrbitControls, useGLTF, Environment, Text3D, MeshTransmission) | Reduces boilerplate dramatically |
| **@react-three/postprocessing** | Bloom, depth of field, vignette, chromatic aberration, god rays | GPU cost, use selectively |
| **Spline (@splinetool/react-spline)** | Designer-friendly 3D, cloud-hosted scenes, no-code 3D creation | Less control, external dependency, larger payload |
| **Cobe** | Lightweight interactive globes | Single-purpose, very small bundle |
| **OGL** | Lightweight WebGL (~5x smaller than Three.js), studios like Active Theory use it | Less ecosystem, more manual work |
| **Troika-three-text** | High-quality SDF text rendering in 3D | Better than Text3D for dynamic text |
Versions: R3F v9 is the React 19 compatibility release; match the project's React major before installing. Its `gl` prop may return a promise, which is how `THREE.WebGPURenderer` is wired (`gl={async (props) => { const r = new THREE.WebGPURenderer(props); await r.init(); return r }}`).
### Animation & motion
| Library | Use case |
|---------|----------|
| **GSAP + ScrollTrigger** | Scroll-synced animations, timeline sequencing, complex easing, scrub-based 3D transforms |
| **Motion** (`motion` package, `import { motion } from "motion/react"`; formerly Framer Motion) | React animations, layout transitions, gesture-driven motion, AnimatePresence |
| **Lenis** | Smooth scroll (buttery 60fps scrolling that syncs with GSAP ScrollTrigger) |
| **Maath (easing)** | Smooth damped camera follow, interpolation utilities inside useFrame |
| **Spring physics** | useSpring + useMotionValue for organic, physics-based transitions |
### Supporting tools
| Tool | Purpose |
|------|---------|
| **gltfjsx** | Auto-generate React components from GLB/GLTF models |
| **Draco / meshopt** | Model compression (reduce GLB size 60-90%) |
| **KTX2 / Basis Universal** | GPU-native texture compression (much smaller than PNG/JPG) |
| **HDR / EXR environments** | Realistic reflections and ambient lighting |
| **Shader chunks / GLSL** | Custom visual effects (noise, distortion, gradient, dissolve) |
| **Noise functions (Simplex/Perlin/Worley)** | Organic movement, procedural textures, generative effects |
| **Blender** | 3D model creation, baking textures/lighting, optimizing geometry |
| **FBO (Frame Buffer Object)** | GPU-computed particle positions for massive counts (100k+) |
| **GSAP Flip plugin** | Smooth page/section transitions that morph 3D scenes |
## Workflow
1. **Classify the 3D approach** — Determine which category the project falls into:
- **Hero 3D scene** — Single interactive 3D element as visual anchor (most common)
- **Full 3D experience** — Entire page is a 3D environment with camera-driven navigation
- **Scroll-driven 3D** — 3D objects transform based on scroll position (GSAP scrub)
- **3D product showcase** — Rotating/interactive product model with environment
- **Particle/generative** — WebGL particles, noise fields, generative backgrounds
- **Hybrid** — 3D elements layered with traditional 2D UI (most Awwwards sites)
2. **Design the scene graph** before writing code:
- Camera type and position (perspective vs orthographic, FOV, near/far)
- Lighting rig (ambient base + accent spots + fill + environment map)
- Model hierarchy (groups, transforms, conditional visibility)
- Post-processing chain (which effects, in what order)
- Interaction model (orbit, scroll-driven, mouse-follow, click-to-reveal)
3. **Set up the Canvas correctly**:
```
Canvas setup checklist:
- Camera: position, FOV, near/far clipping planes
- Suspense: ALWAYS wrap 3D content with fallback loader
- Responsive: useMediaQuery to adjust scale/position per device
- Performance: dpr={[1, 2]} for retina without GPU waste
- Tone mapping: ACESFilmic for cinematic look
- Color management: flat={true} when using post-processing
- Shadows: only when necessary (expensive)
```
4. **Build the lighting rig** (critical for visual quality):
```
Awwwards-quality lighting recipe:
- ambientLight: low intensity (0.1-0.3), tinted color for mood
- 1 key spotLight: dominant directional, high intensity
- 1-2 accent spotLights: tinted with the project's accent token from DESIGN.md (never a default purple/cyan pair)
- 1 rectAreaLight: soft fill from above/side
- 1-2 pointLights: atmospheric glow, deep colors
- Environment map: for realistic reflections on metallic/glass surfaces
```
5. **Load and display 3D models**:
- Use GLB/GLTF format exclusively (web standard)
- Load with `useGLTF()` from drei, preload with `useGLTF.preload()`
- Generate components with gltfjsx for type-safe mesh access
- Override materials when the default look doesn't match the design
- Use `<Float>` from drei for ambient bobbing motion
- Handle animations with `useAnimations()` hook
6. **Implement scroll-driven 3D animations**:
```
GSAP ScrollTrigger pattern:
- Create timeline with scrollTrigger config
- scrub: true for scroll-synced (or scrub: 1 for smooth)
- Pin sections when 3D needs to transform during scroll
- Use gsap.to() to animate 3D object properties (scale, position, rotation)
- onEnter/onLeaveBack callbacks for state changes
- Stagger children for sequential reveals
```
7. **Add post-processing effects** (selective, not all at once):
```
Common Awwwards effect chains:
- SelectiveBloom: glow on emissive elements (screens, lights, accents)
- Vignette: subtle darkening at edges for cinematic framing
- ChromaticAberration: slight color split for stylized look
- DepthOfField: focus on hero element, blur background
- Noise/Film grain: subtle texture for organic feel
- God rays: volumetric light shafts from bright sources
```
8. **Implement mouse/pointer interactions**:
```
Interaction patterns:
- Camera follow: useFrame + easing.damp3() for smooth mouse-driven camera
- Object hover: onPointerEnter/Leave with scale/color transitions
- Parallax layers: useMotionValue + useTransform for depth
- Cursor effects: custom cursor that reacts to 3D hover states
- Drag: useDrag for interactive object manipulation
```
9. **Build particle systems** when needed:
```
Particle system approach:
- Use BufferGeometry + Float32Array for positions
- PointsMaterial with size, opacity, color
- Animate in useFrame: update positions each frame
- Mouse attraction: calculate distance, apply magnetism force
- Edge recycling: respawn particles when they leave bounds
- Count: 50-200 (balance visual density vs performance)
```
10. **Integrate 3D with 2D UI** (the hybrid approach most Awwwards sites use):
```
Integration patterns:
- Canvas as background: absolute positioning, z-index layering
- Text overlay: HTML content positioned over Canvas
- Split layout: text on one side, 3D on the other (responsive grid)
- Scroll sections: full-height sections with Canvas spanning viewport
- Portal: drei's <Html> component for DOM inside 3D scene
- Pointer events: pointer-events-none on overlays that shouldn't block 3D
```
11. **Apply Awwwards-quality visual design principles**:
- **Typography**: Large, bold display fonts contrasting with 3D depth
- **Color**: the project's DESIGN.md palette; one accent used consistently (see `bosskuai-taste`); light or dark as the brand dictates
- **Spacing**: Generous whitespace, sections breathe
- **Transitions**: animate state changes that pass the frequency gate in `animate` (never keyboard or 100+/day actions)
- **Loading**: Preloader with progress animation (not just a spinner)
- **Cursor**: Custom cursor that changes on interactive elements
- **Sound**: Optional ambient sound or interaction feedback (with user opt-in)
- **Scroll**: Smooth scroll (Lenis) synchronized with animations
12. **Optimize for performance** (critical — beautiful but slow loses):
- Compress models: Draco/meshopt compression, reduce polygon count
- Texture optimization: WebP/AVIF textures, power-of-2 dimensions, max 2048px
- Lazy load 3D: React.lazy() + Suspense for code splitting
- Reduce on mobile: fewer particles, simpler lighting, lower-res textures
- Instancing: InstancedMesh for repeated objects
- Frustum culling: default in Three.js, verify not disabled
- Dispose: clean up geometries, materials, textures on unmount
- Frame budget: target 60fps, use `useFrame` wisely (avoid heavy computation)
- Conditional rendering: skip heavy effects on low-power devices
- Preload critical models: `useGLTF.preload()` during loading screen
13. **Handle responsive 3D** (most 3D sites fail here):
```
Responsive strategy:
- useMediaQuery for device detection (mobile < 768px, tablet < 1024px)
- Scale 3D scenes: 0.5-0.7x on mobile, 0.8x tablet, 1x desktop
- Reposition camera: closer on mobile, wider on desktop
- Simplify: fewer lights, no post-processing on mobile
- Touch: replace hover with tap, disable OrbitControls zoom on touch
- Orientation: handle portrait vs landscape camera adjustments
- Fallback: consider 2D fallback for very old devices / no WebGL
```
14. **Test and verify**:
- Visual: does it look as good as the design/reference?
- Performance: Lighthouse score, FPS counter, no jank
- Responsive: test mobile, tablet, desktop, ultra-wide
- Accessibility: prefers-reduced-motion, alt text, keyboard navigation for UI
- Loading: preloader works, no flash of un-styled content
- Cross-browser: Chrome, Safari (WebKit differences), Firefox
- Memory: no leaks (check dispose, cleanup in useEffect return)
## Guardrails
- Do not add post-processing effects without checking GPU and performance budget — effects that look great on desktop can drop mobile to below 30fps.
- Do not use Spline for production-critical scenes without a fallback — external cloud dependency adds latency and single-point failure risk.
- Do not skip responsive adaptation — most 3D sites fail on mobile; test at 375px before calling any scene done.
## Output expectation
- 3D approach classification (hero scene, full experience, scroll-driven, hybrid, etc.)
- Scene graph design (camera, lights, models, effects, interactions)
- Technology selection with rationale (R3F vs Spline vs vanilla Three.js)
- Implementation plan with component structure
- Animation choreography (what moves when, triggered by what)
- Performance budget and optimization strategy
- Responsive adaptation plan
- Code implementation following patterns from reference projects
- Post-processing chain specification
- Loading/preloader strategy
## Code patterns reference (from proven portfolio examples)
### Canvas initialization
```jsx
<Canvas camera={{ position: [0, 0, 15], fov: 45 }} dpr={[1, 2]}>
<ambientLight intensity={0.2} color="#1a1a40" />
<Suspense fallback={<Loader />}>
<group scale={isMobile ? 0.7 : 1}>
<Scene />
</group>
<Lights />
<EffectComposer>
<SelectiveBloom intensity={1.5} luminanceThreshold={0.2} />
</EffectComposer>
</Suspense>
</Canvas>
```
### Camera mouse-follow (Maath easing)
```jsx
function Rig() {
return useFrame((state, delta) => {
easing.damp3(
state.camera.position,
[state.pointer.x / 10, 1 + state.pointer.y / 10, 3], // state.mouse is deprecated in R3F
0.5,
delta
);
});
}
```
### GSAP scroll-driven 3D transform
```jsx
useGSAP(() => {
const tl = gsap.timeline({
scrollTrigger: {
trigger: "#section",
start: "top bottom",
end: "bottom top",
scrub: true,
},
});
tl.to(groupRef.current.rotation, { y: Math.PI / 4 });
tl.to(groupRef.current.position, { y: -2, x: 1 }, "<");
tl.to(groupRef.current.scale, { x: 0.8, y: 0.8, z: 0.8 }, "<");
});
```
### Parallax background layers
```jsx
const scrollY = useScroll();
const mountain3Y = useTransform(scrollY.scrollYProgress, [0, 0.5], ["0%", "70%"]);
const planetsX = useTransform(scrollY.scrollYProgress, [0, 0.5], ["0%", "-20%"]);
<motion.div style={{ y: mountain3Y }}>
<img src="/bg-layer-3.webp" />
</motion.div>
```
### Particle system with mouse attraction
```jsx
function Particles({ count = 100 }) {
const mesh = useRef();
const positions = useMemo(() => {
const arr = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i++) arr[i] = (Math.random() - 0.5) * 10;
return arr;
}, [count]);
useFrame(() => {
const pos = mesh.current.geometry.attributes.position.array;
for (let i = 1; i < pos.length; i += 3) {
pos[i] -= 0.005 + Math.random() * 0.001;
if (pos[i] < -5) pos[i] = 5;
}
mesh.current.geometry.attributes.position.needsUpdate = true;
});
return (
<points ref={mesh}>
<bufferGeometry>
<bufferAttribute attach="attributes-position" array={positions} count={count} itemSize={3} />
</bufferGeometry>
<pointsMaterial size={0.05} color="white" transparent opacity={0.9} />
</points>
);
}
```
### Smooth scroll setup (Lenis; for ScrollTrigger sync use the GSAP-ticker pattern in bosskuai-lenis-smooth-scroll)
```jsx
import { ReactLenis } from "lenis/react";
<ReactLenis root options={{ duration: 2 }}>
<main>{children}</main>
</ReactLenis>
```
### Preloader with GSAP progress
```jsx
function Preloader({ onComplete }) {
const [progress, setProgress] = useState(0);
useEffect(() => {
gsap.to({ val: 0 }, {
val: 100,
duration: 2.5,
ease: "power2.inOut",
onUpdate: function () { setProgress(Math.round(this.targets()[0].val)); },
onComplete,
});
}, []);
return <div className="preloader">{progress}%</div>;
}
```
### Spline integration with object manipulation
```jsx
const Spline = React.lazy(() => import("@splinetool/react-spline"));
function Scene({ onLoad }) {
const handleLoad = (splineApp) => {
const obj = splineApp.findObjectByName("Keyboard");
// Manipulate: obj.scale, obj.position, obj.rotation, obj.visible
splineApp.addEventListener("mouseHover", handleHover);
onLoad();
};
return (
<Suspense fallback={<Loader />}>
<Spline scene="/assets/scene.spline" onLoad={handleLoad} />
</Suspense>
);
}
```
### Interactive globe (Cobe)
```jsx
import createGlobe from "cobe";
useEffect(() => {
const globe = createGlobe(canvasRef.current, {
width: 800, height: 800,
phi: 0, theta: 0.3,
dark: 1, diffuse: 0.4,
mapSamples: 16000, mapBrightness: 1.2,
baseColor: [1, 1, 1],
markerColor: [251/255, 100/255, 21/255],
glowColor: [1.2, 1.2, 1.2],
markers: [{ location: [14.5995, 120.9842], size: 0.03 }],
onRender: (state) => { state.phi = r.get(); state.width = width * 2; },
});
return () => globe.destroy();
}, []);
```
## Advanced techniques (what separates good from award-winning)
### Custom GLSL shaders
Custom shaders are what separate good 3D sites from Awwwards winners. Default materials look generic — custom shaders create uniqueness:
- **Custom vertex shaders**: Mesh deformation (wave effects, morph targets, scroll-driven distortion)
- **Custom fragment shaders**: Stylized materials (gradients, noise textures, iridescence, holographic)
- **Noise-based motion**: Simplex/Perlin/Worley noise for organic, non-repetitive movement
- **ShaderMaterial vs RawShaderMaterial**: Use ShaderMaterial when you want Three.js uniforms/attributes injected; RawShaderMaterial for full control
- **Shader transitions**: Custom fragment shaders for page/section transitions (dissolve, morph, distortion wipe)
### FBO (Frame Buffer Object) particles
For massive particle counts (10k-100k+), compute positions on the GPU:
```
Pattern:
1. Create a DataTexture with initial particle positions
2. Use a ping-pong FBO setup (two render targets)
3. Run a simulation shader each frame that reads one FBO and writes to the other
4. Read the output FBO as position data in the display shader
Result: 100k+ particles at 60fps (impossible with CPU-based positions)
```
### Adaptive performance
Detect device capability and serve appropriate quality:
```
Strategy:
- Check GPU via renderer.getContext().getParameter(renderer.getContext().RENDERER)
- Check device pixel ratio, memory, core count
- Tier 1 (high-end desktop): full effects, high-res textures, max particles
- Tier 2 (mid-range): reduced post-processing, medium textures, fewer particles
- Tier 3 (mobile/low-end): no post-processing, baked materials, minimal particles, or image/video fallback
- Use R3F's frameloop="demand" to only render when something changes (saves battery)
```
### Baked lighting
For complex scenes where real-time lighting is too expensive:
- Bake lighting in Blender onto textures (lightmaps)
- Export with the model — zero runtime lighting cost
- Combine with one dynamic light for interactive highlights
## Awwwards-quality design principles
### What makes a 3D site award-worthy
1. **Purposeful 3D** — 3D enhances the story, not just decoration. Concept first, technology second.
2. **Seamless integration** — 3D and 2D elements feel like one design, not separate layers
3. **Choreographed motion** — Animations are sequenced, not random; every movement has intent
4. **Performance** — Silky smooth on target devices (60fps minimum). Performance IS a feature — fast smooth 3D beats heavy laggy 3D.
5. **Loading experience** — The wait is part of the experience (animated preloader, progressive reveal). Many Awwwards loaders are themselves award-worthy.
6. **Interactivity** — Users can influence the 3D (hover, scroll, click, drag) — it responds
7. **Sound design** — Optional but impactful ambient audio or interaction sounds (always with user opt-in toggle)
8. **Typography** — Bold, oversized type (often 8-15vw) that plays with 3D depth. Premium display fonts (Neue Montreal, Clash Display, PP Mori, Satoshi)
9. **Brand-led palette** - dark themes flatter emissive 3D, but choose light or dark from the brand and DESIGN.md, not by default
10. **Attention to detail** — Custom cursors that react to 3D hover states, micro-interactions, smooth transitions between states
11. **At least one "wow moment"** in the first 5 seconds
12. **Strategic restraint** — Selective use of 3D for key moments often beats "3D everywhere"
### Common Awwwards 3D site categories
- **Portfolio/Agency showcases** — Interactive hero + scroll-driven project reveals
- **Product launches** — 3D product model with configurable options (Apple-style)
- **Brand experiences** — Full WebGL world with narrative-driven navigation
- **Interactive stories** — Scroll-driven camera movement through 3D environment
- **Generative art** — Particle systems, noise fields, procedural geometry
## References
- `../../references/playbooks/3d-web-development-detailed-playbook.md`
- `../../references/checklists/3d-web-development-checklist.md`
- `../../references/playbooks/ui-delivery-playbook.md`
- `../../references/checklists/ui-fidelity-checklist.md`