Use Cases (Aktualisiert: 2.6.2026)

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.

Praktische Three.js 3D Web UI mit Claude Code bauen

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

EinsatzfallNutzen von 3DAufgabe für Claude Code
3D ProduktviewerKäufer sehen Farbe, Tiefe, Finish und RückseiteOrbitControls, Farbvarianten, Licht-Presets, Mobile-Test
DatenvisualisierungCluster, Ausreißer und zeitliche Bewegung werden räumlich sichtbarPunktwolken, 3D Balken, Kameraübergänge, Legenden
Portfolio oder BildungStrukturen lassen sich drehen und erklärenLabels, 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

FehlerWahrscheinliche UrsacheLösung
Weißer CanvasParent-Höhe null, Kamera falsch, kein LichtCSS-Höhe setzen, camera position und controls target prüfen
Verzerrung nach Resizecamera.aspect und renderer size werden nicht gemeinsam aktualisiertcamera.updateProjectionMatrix() und renderer.setSize() aufrufen
Seite wird nach Navigation langsamerThree.js Ressourcen werden nicht freigegebenScene beim Unmount traversieren und dispose ausführen
Smartphone wird heißpixelRatio hoch, Schatten teuer, Modell zu detailliertpixelRatio begrenzen, Schatten und Segmente reduzieren
SSR-FehlerZugriff auf window/document während Server RenderInitialisierung 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.

#Claude Code #Three.js #3D #WebGL #frontend
Kostenlos

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.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.