Praktische Three.js 3D Web UI mit Claude Code bauen
Baue mit Claude Code und Three.js einen 3D Viewer mit Resize, Cleanup, Review-Prompts und Praxisfallen.
Three.js macht WebGL deutlich zugänglicher, aber eine produktionsreife 3D-Oberfläche ist mehr als ein rotierendes Objekt. Kamera, Licht, Canvas-Größe, mobile GPU-Last, Cleanup beim Unmount und Fallbacks bei Ladefehlern müssen bewusst umgesetzt werden.
Claude Code ist dabei hilfreich, weil es die wiederkehrende Basis für Three.js schnell erzeugen kann. Eine vage Aufgabe wie “mach daraus etwas in 3D” führt aber oft zu einer hübschen Demo ohne saubere Resize-Logik, ohne Dispose-Pfad oder mit zu hoher Last auf Smartphones.
Dieser Artikel zeigt eine kopierbare Vite + React + Three.js Basis und die Review-Anweisungen, mit denen Claude Code den Code vor dem Release prüfen sollte.
Erst den Zweck der3D Ansicht klären
Vor dem Code muss klar sein, welche Information die 3D-Ansicht liefern soll. Bei einem Produktviewer geht es um Farbe, Material, Rückseite und Größengefühl. Bei Datenvisualisierung geht es um Cluster, Ausreißer oder zeitliche Bewegung. Bei Portfolio- oder Lern-Szenen muss die Aufmerksamkeit oft gezielt auf einzelne Bauteile gelenkt werden.
Ein brauchbarer Prompt für Claude Code beschreibt deshalb nicht nur den Stil, sondern konkrete Anforderungen.
Erstelle einen 3D Produktviewer mit Vite + React + TypeScript + three.
Anforderungen:
- Canvas in einem Parent-Element rendern, nicht direkt in document.body
- Größe an den Container anpassen
- Rotation und Zoom mit OrbitControls
- geometry, material, renderer und controls beim Unmount disposen
- devicePixelRatio auf mobilen Geräten auf 2 begrenzen
- Code muss direkt in src/App.tsx kopierbar sein
Diese Vorgaben bilden ein Harness, also ein Arbeitsgerüst, mit dem der Agent sicherer Code erzeugt. Es verhindert typische Fehler: weißer Canvas, verzerrtes Bild, weiterlaufender Renderer nach Navigation und unnötig hohe GPU-Last. API-Details stehen in der offiziellen Three.js Dokumentation, besonders relevant ist WebGLRenderer.
Minimales Setup mit Vite und React
Beginne mit rohem Three.js in React. React Three Fiber ist später oft sinnvoll, aber die direkte Variante zeigt den Lebenszyklus klarer: Renderer erstellen, DOM anhängen, Resize beobachten, animieren und Ressourcen freigeben.
npm create vite@latest three-claude-demo -- --template react-ts
cd three-claude-demo
npm i three
npm run dev
flowchart LR
A["React component"] --> B["mount div"]
B --> C["WebGLRenderer canvas"]
C --> D["Scene"]
D --> E["Camera and lights"]
D --> F["Mesh and material"]
C --> G["OrbitControls"]
G --> H["resize and dispose"]
Kopierbarer 3D Viewer
Füge den folgenden Code in src/App.tsx ein. Er erzeugt ein einfaches Produktobjekt, setzt Licht und Kamera, reagiert auf Resize und gibt Three.js Ressourcen beim Unmount frei.
import { useEffect, useRef } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import "./App.css";
export default function App() {
const mountRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const mount = mountRef.current;
if (!mount) return;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xf6f7fb);
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(3.5, 2.2, 4.5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.shadowMap.enabled = true;
mount.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.minDistance = 2.5;
controls.maxDistance = 8;
controls.target.set(0, 0.4, 0);
scene.add(new THREE.HemisphereLight(0xffffff, 0x7c8594, 1.6));
const keyLight = new THREE.DirectionalLight(0xffffff, 2.4);
keyLight.position.set(3, 5, 4);
keyLight.castShadow = true;
scene.add(keyLight);
const productGeometry = new THREE.BoxGeometry(1.8, 1.2, 1.1, 4, 4, 4);
const productMaterial = new THREE.MeshStandardMaterial({
color: 0x2f6f73,
roughness: 0.42,
metalness: 0.08,
});
const product = new THREE.Mesh(productGeometry, productMaterial);
product.castShadow = true;
product.position.y = 0.75;
scene.add(product);
const floorGeometry = new THREE.CircleGeometry(2.2, 64);
const floorMaterial = new THREE.MeshStandardMaterial({
color: 0xd9dee8,
roughness: 0.7,
});
const floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
const resize = () => {
const width = mount.clientWidth;
const height = mount.clientHeight;
if (width === 0 || height === 0) return;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height, false);
};
let frameId = 0;
const clock = new THREE.Clock();
const animate = () => {
const elapsed = clock.getElapsedTime();
product.rotation.y = elapsed * 0.45;
product.rotation.x = Math.sin(elapsed * 0.8) * 0.08;
controls.update();
renderer.render(scene, camera);
frameId = window.requestAnimationFrame(animate);
};
resize();
animate();
window.addEventListener("resize", resize);
return () => {
window.removeEventListener("resize", resize);
window.cancelAnimationFrame(frameId);
controls.dispose();
scene.traverse((object) => {
if (object instanceof THREE.Mesh) {
object.geometry.dispose();
const materials = Array.isArray(object.material)
? object.material
: [object.material];
materials.forEach((material) => material.dispose());
}
});
renderer.dispose();
renderer.domElement.remove();
};
}, []);
return (
<main className="viewerShell">
<div className="copy">
<p className="eyebrow">Three.js + Claude Code</p>
<h1>3D product viewer</h1>
<p>
Drag to rotate, scroll to zoom, and resize the window to verify that
the canvas follows its container.
</p>
</div>
<div ref={mountRef} className="viewerStage" />
</main>
);
}
Ergänze src/App.css. Entscheidend ist die Höhe von .viewerStage. Ohne Höhe kann der Renderer korrekt laufen und trotzdem nichts sichtbar sein.
body {
margin: 0;
font-family: Inter, system-ui, sans-serif;
background: #eef2f7;
color: #17202a;
}
.viewerShell {
min-height: 100vh;
display: grid;
grid-template-columns: minmax(260px, 0.8fr) minmax(320px, 1.2fr);
gap: 32px;
align-items: center;
padding: 40px;
box-sizing: border-box;
}
.copy {
max-width: 520px;
}
.viewerStage {
height: min(62vh, 560px);
min-height: 360px;
border: 1px solid #ccd5df;
background: #f6f7fb;
}
.viewerStage canvas {
display: block;
}
@media (max-width: 760px) {
.viewerShell {
grid-template-columns: 1fr;
padding: 24px;
}
.viewerStage {
min-height: 300px;
}
}
Claude Code als Reviewer nutzen
Nach der ersten Umsetzung sollte Claude Code nicht nur das Design verbessern, sondern Risiken prüfen.
Reviewe diese React + Three.js Implementierung.
Prüfe:
1. ob der Canvas der Containergröße folgt
2. ob geometry, material, renderer und controls beim Unmount disposed werden
3. ob requestAnimationFrame gestoppt wird
4. ob devicePixelRatio für hochauflösende Mobilgeräte begrenzt ist
5. ob window/document in SSR-Frameworks wie Next.js oder Astro Probleme machen
6. ob Kamera, Licht und Controls zur Produktprüfung passen
Gib konkrete Diffs und eine manuelle Testcheckliste aus.
So wird Claude Code zum zweiten technischen Reviewer. Besonders Cleanup-Pfade sind wichtig, weil Speicher- und GPU-Leaks auf einem Screenshot nicht sichtbar sind. Navigiere mehrfach weg und zurück und prüfe Memory und Performance in DevTools.
Drei praxisnahe Einsatzfälle
| Einsatzfall | Nutzen von 3D | Aufgabe für Claude Code |
|---|---|---|
| 3D Produktviewer | Käufer sehen Farbe, Tiefe, Finish und Rückseite | OrbitControls, Farbvarianten, Licht-Presets, Mobile-Test |
| Datenvisualisierung | Cluster, Ausreißer und zeitliche Bewegung werden räumlich sichtbar | Punktwolken, 3D Balken, Kameraübergänge, Legenden |
| Portfolio oder Bildung | Strukturen lassen sich drehen und erklären | Labels, Hervorhebung von Teilen, geführte Kamerapositionen |
Ein Produktviewer soll Unsicherheit senken, nicht nur beeindrucken. Eine Datenvisualisierung soll Vergleiche erleichtern; wenn Perspektive stört, braucht es eine 2D-Alternative. Eine Lernszene braucht Reihenfolge, Labels und geplante Kamerapfade.
Häufige Fehler und Lösungen
| Fehler | Wahrscheinliche Ursache | Lösung |
|---|---|---|
| Weißer Canvas | Parent-Höhe null, Kamera falsch, kein Licht | CSS-Höhe setzen, camera position und controls target prüfen |
| Verzerrung nach Resize | camera.aspect und renderer size werden nicht gemeinsam aktualisiert | camera.updateProjectionMatrix() und renderer.setSize() aufrufen |
| Seite wird nach Navigation langsamer | Three.js Ressourcen werden nicht freigegeben | Scene beim Unmount traversieren und dispose ausführen |
| Smartphone wird heiß | pixelRatio hoch, Schatten teuer, Modell zu detailliert | pixelRatio begrenzen, Schatten und Segmente reduzieren |
| SSR-Fehler | Zugriff auf window/document während Server Render | Initialisierung in useEffect oder Client-only Komponente |
Bei einem weißen Canvas zuerst vereinfachen: heller Hintergrund, ein Würfel, ein Licht, bekannte Kamera. GLB Loader, HDR, Postprocessing und Layout nicht gleichzeitig debuggen.
Release Check und CTA
Vor dem Release auf dem schwächsten Zielgerät testen: fps, Temperatur, Modellgröße, Fallback-Bild bei WebGL-Fehlern und alternative Beschreibung für Nutzer ohne Canvas-Interaktion. Für Canvas-Architektur hilft der Claude Code Canvas Guide. Für Bewegung ist der Claude Code Animation Guide passend.
Claude Code Lab unterstützt Reviews für 3D Produktviewer, WebGL Datenvisualisierungen und interaktive Lernwelten sowie Trainings für Teams. Hilfreich sind Zielgeräte, Framework, Modellformat, Performance-Budget und der geschäftliche Grund für 3D.
Ergebnis aus dem Test
Ich habe den Code in ein Vite React TypeScript Projekt kopiert und Desktop- sowie Mobile-Breiten getestet. Die feste Höhe von .viewerStage verhindert den typischen weißen Canvas. Das Limit devicePixelRatio auf 2 reduziert unnötige GPU-Arbeit auf dichten Displays. Die Review-Anweisung an Claude Code hilft, vergessene Dispose-Pfade früh zu finden.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.