--- id: freshtechbro/claudedesignskills/spline-interactive version: "6621f9f5" license: MIT install: manual updated: 2025-11-20 --- # spline-interactive — spline-interactive equips Claude Code with a professional design agency toolkit for crafting interactive 3D web experiences. Leverage integrated support for Three.js, GSAP, React Three Fiber, Framer Motion, Babylon.js, and modern web frameworks to build visually rich applications without manual code entry. Publisher: freshtechbro · Stars: 618 · Updated: 2025-11-20 Install (manual): `git clone https://github.com/freshtechbro/claudedesignskills` ## SKILL.md # Spline Interactive - Browser-Based 3D Design and Animation ## Overview Spline is a browser-based 3D design and animation platform that enables creators to build interactive 3D experiences without requiring code or specialized software knowledge. It provides a collaborative visual editor for designing, animating, and exporting 3D scenes across multiple platforms. **Key Features**: - Visual 3D modeling with parametric shapes, extrusion, and boolean operations - State-based animation system with timeline controls - Interactive event system (mouse, keyboard, collision, scroll) - Multiple export options (React components, web code, public URLs) - Real-time collaboration with team libraries - AI-powered generation (3D from text, textures, style transfer) - Built-in physics and particle systems **When to Use This Skill**: - Creating 3D web experiences without writing Three.js code - Designing interactive product showcases or configurators - Prototyping 3D UI/UX concepts visually - Building marketing pages with 3D elements - Collaborating with designers on 3D content - Exporting scenes for React or vanilla JS integration **Alternatives**: - **Three.js** (threejs-webgl): For developers who prefer code-first approach and need maximum control - **Babylon.js** (babylonjs-engine): For game-focused projects with built-in physics - **React Three Fiber** (react-three-fiber): For React developers who want to build 3D with JSX ## Core Concepts ### 1. Scene Structure Spline organizes projects into scenes containing: - **Objects**: 3D models, shapes, text, images - **Lights**: Directional, point, spot lights - **Cameras**: Orbital, perspective, orthographic - **Events**: Interaction triggers - **States**: Animation keyframes ### 2. Components System Reusable elements that can be: - Created from any object or group - Instantiated multiple times - Updated across all instances - Overridden per instance ### 3. State-Based Animation Animations are defined as transitions between states: - **Default State**: Initial appearance - **Additional States**: Target appearances - **Events**: Triggers that cause state transitions - **Transitions**: Duration, easing, properties ### 4. Interactivity Model Event-driven system with: - **Events**: User actions or scene triggers - **Conditions**: Logic gates (if/else) - **Actions**: State changes, audio, scene switches - **Variables**: Dynamic data from APIs or user input ### 5. Export Options Multiple deployment methods: - **Public URL**: Direct shareable link - **Code Export**: React component or vanilla JS - **Spline Viewer**: Embedded iframe - **Self-Hosted**: Download and host independently ## Common Patterns ### Pattern 1: Basic React Integration **Use Case**: Embed a Spline scene in a React application **Implementation**: ```bash # Installation npm install @splinetool/react-spline @splinetool/runtime ``` ```jsx import Spline from '@splinetool/react-spline'; export default function Hero() { return (
); } ``` **Key Points**: - Scene URL comes from Spline export dialog - Component fills parent container - Automatically handles loading and rendering ### Pattern 2: Event Handling and Object Interaction **Use Case**: Respond to user clicks on specific objects **Implementation**: ```jsx import Spline from '@splinetool/react-spline'; export default function InteractiveScene() { function onSplineMouseDown(e) { // Check if clicked object is the button if (e.target.name === 'Button') { console.log('Button clicked!'); // Get object properties console.log('Position:', e.target.position); console.log('Rotation:', e.target.rotation); console.log('Scale:', e.target.scale); } } function onSplineMouseHover(e) { if (e.target.name === 'Button') { console.log('Hovering over button'); } } return ( ); } ``` **Available Event Handlers**: - `onSplineMouseDown` - Mouse press on object - `onSplineMouseUp` - Mouse release - `onSplineMouseHover` - Mouse over object - `onSplineKeyDown` - Keyboard press - `onSplineKeyUp` - Keyboard release - `onSplineStart` - Scene loaded and started - `onSplineLookAt` - Camera look-at event - `onSplineFollow` - Camera follow event - `onSplineScroll` - Scroll event ### Pattern 3: Programmatic Object Control **Use Case**: Modify object properties from React code **Implementation**: ```jsx import { useRef } from 'react'; import Spline from '@splinetool/react-spline'; export default function ProductViewer() { const cube = useRef(); const splineApp = useRef(); function onLoad(spline) { // Save Spline instance splineApp.current = spline; // Find object by name const obj = spline.findObjectByName('Product'); // Or by ID // const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E'); cube.current = obj; } function rotateProduct() { if (cube.current) { // Rotate 45 degrees around Y axis cube.current.rotation.y += Math.PI / 4; } } function changeColor() { if (cube.current) { // Change material color (hex color) cube.current.material.color.set(0xff6b6b); } } function moveProduct() { if (cube.current) { cube.current.position.x += 50; cube.current.position.y += 10; } } return (
); } ``` **Object Properties You Can Modify**: - `position` - { x, y, z } - `rotation` - { x, y, z } (radians) - `scale` - { x, y, z } - `material.color` - Color hex value - `visible` - Boolean ### Pattern 4: Triggering Spline Animations **Use Case**: Trigger animations defined in Spline from React **Implementation**: ```jsx import { useRef } from 'react'; import Spline from '@splinetool/react-spline'; export default function AnimatedCard() { const splineApp = useRef(); function onLoad(app) { splineApp.current = app; } function triggerHoverAnimation() { // Emit mouseHover event on 'Card' object splineApp.current.emitEvent('mouseHover', 'Card'); } function triggerClickAnimation() { // Emit mouseDown event on 'Button' object splineApp.current.emitEvent('mouseDown', 'Button'); } function reverseAnimation() { // Play animation in reverse splineApp.current.emitEventReverse('mouseHover', 'Card'); } return (
); } ``` **Available Event Types**: - `mouseDown` - Mouse press - `mouseHover` - Hover effect - `mouseUp` - Mouse release - `keyDown` - Key press - `keyUp` - Key release - `start` - Start event - `lookAt` - Look at camera - `follow` - Follow camera ### Pattern 5: Next.js Integration with SSR **Use Case**: Use Spline in Next.js with server-side rendering benefits **Implementation**: ```jsx // app/page.js (Next.js 13+ App Router) import Spline from '@splinetool/react-spline/next'; export default function Home() { return (
); } ``` **Benefits**: - Placeholder image shown during SSR - Faster perceived load times - Better SEO with fallback content ### Pattern 6: Lazy Loading for Performance **Use Case**: Defer Spline loading until needed **Implementation**: ```jsx import React, { Suspense } from 'react'; // Dynamically import Spline const Spline = React.lazy(() => import('@splinetool/react-spline')); export default function LazyScene() { return (

My Page Content

Loading 3D scene...
}>

More content below

); } ``` **Benefits**: - Reduces initial bundle size - Improves page load performance - Shows custom loading UI ### Pattern 7: Responsive Spline Scenes **Use Case**: Make Spline scenes adapt to different screen sizes **Implementation**: ```jsx import Spline from '@splinetool/react-spline'; import { useState, useEffect } from 'react'; export default function ResponsiveScene() { const [isMobile, setIsMobile] = useState(false); useEffect(() => { const checkMobile = () => { setIsMobile(window.innerWidth < 768); }; checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); return (
); } ``` **Alternative Approach** (Single Scene): ```jsx import Spline from '@splinetool/react-spline'; import { useRef, useEffect } from 'react'; export default function ResponsiveScene() { const splineApp = useRef(); function onLoad(app) { splineApp.current = app; adjustForScreenSize(); } function adjustForScreenSize() { if (!splineApp.current) return; const camera = splineApp.current.findObjectByName('Camera'); const isMobile = window.innerWidth < 768; if (isMobile) { // Zoom out on mobile splineApp.current.setZoom(0.7); // Adjust camera position camera.position.z = 1500; } } useEffect(() => { window.addEventListener('resize', adjustForScreenSize); return () => window.removeEventListener('resize', adjustForScreenSize); }, []); return ( ); } ``` ## Integration Patterns ### With Three.js (threejs-webgl) For advanced use cases, combine Spline-designed assets with Three.js code: 1. **Export from Spline**: Use GLTF/GLB export 2. **Import in Three.js**: Load using GLTFLoader 3. **Enhance with code**: Add custom shaders, physics, or effects ```javascript import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; const loader = new GLTFLoader(); loader.load('spline-model.glb', (gltf) => { scene.add(gltf.scene); // Add custom behaviors }); ``` ### With GSAP (gsap-scrolltrigger) Trigger Spline animations on scroll: ```jsx import { useEffect, useRef } from 'react'; import Spline from '@splinetool/react-spline'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); export default function ScrollAnimated() { const splineApp = useRef(); function onLoad(app) { splineApp.current = app; ScrollTrigger.create({ trigger: '.scene-container', start: 'top center', onEnter: () => { app.emitEvent('mouseHover', 'Product'); } }); } return (
); } ``` ### With Framer Motion (motion-framer) Animate container while Spline handles 3D: ```jsx import { motion } from 'framer-motion'; import Spline from '@splinetool/react-spline'; export default function AnimatedContainer() { return ( ); } ``` ## Performance Optimization ### 1. Enable On-Demand Rendering Render only when scene changes, not every frame: ```jsx ``` ### 2. Optimize Scene in Spline Editor **In Spline**: - Reduce polygon count (use decimation) - Compress textures (lower resolution, use JPG over PNG) - Limit lights (2-3 lights maximum) - Use simple materials when possible - Enable LOD (Level of Detail) for distant objects ### 3. Lazy Load Heavy Scenes Use React.lazy() as shown in Pattern 6 ### 4. Preload Critical Scenes ```jsx import { useEffect } from 'react'; import Spline from '@splinetool/react-spline'; export default function PreloadedScene() { useEffect(() => { // Preload scene assets const link = document.createElement('link'); link.rel = 'prefetch'; link.href = 'https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode'; document.head.appendChild(link); }, []); return ( ); } ``` ### 5. Mobile Optimizations - Create separate mobile scenes with lower detail - Reduce canvas resolution on mobile - Disable shadows and reflections - Use simpler materials ```jsx ``` ## Common Pitfalls and Solutions ### Pitfall 1: Scene Not Loading **Problem**: Spline component renders but scene doesn't appear **Solutions**: ```jsx // ❌ Wrong: Invalid scene URL // ✅ Correct: Full URL from Spline export // Check for errors function onLoad(app) { console.log('Scene loaded successfully', app); } ``` **Also Check**: - Scene is published in Spline editor - Network tab shows successful file downloads - No CORS errors in console ### Pitfall 2: Object References Lost After Re-render **Problem**: Object refs become undefined after component updates **Solution**: ```jsx // ❌ Wrong: Storing objects without proper refs let myObject; function onLoad(spline) { myObject = spline.findObjectByName('Cube'); // Lost on re-render } // ✅ Correct: Use React refs const myObject = useRef(); function onLoad(spline) { myObject.current = spline.findObjectByName('Cube'); } ``` ### Pitfall 3: Performance Issues on Mobile **Problem**: Scene runs slowly on mobile devices **Solutions**: ```jsx // Create mobile-optimized version in Spline editor // - Fewer polygons (< 50k triangles) // - Smaller textures (512x512 or less) // - No shadows or reflections // - Simpler materials // Load appropriate version const isMobile = window.innerWidth < 768; const sceneUrl = isMobile ? 'https://prod.spline.design/MOBILE-SCENE/scene.splinecode' : 'https://prod.spline.design/DESKTOP-SCENE/scene.splinecode'; ``` ### Pitfall 4: Events Not Firing **Problem**: Click or hover events don't trigger **Solutions**: ```jsx // ❌ Wrong: Using wrong event name // Not a Spline prop // ✅ Correct: Use Spline event props // Also ensure object has events in Spline editor: // 1. Select object in Spline // 2. Add event in "Events" panel // 3. Assign state transition or action ``` ### Pitfall 5: Animation Not Triggering Programmatically **Problem**: `emitEvent()` doesn't trigger animation **Solutions**: ```jsx // ❌ Wrong: Calling before scene loads function triggerAnimation() { splineApp.current.emitEvent('mouseHover', 'Button'); // Error if not loaded } // ✅ Correct: Ensure scene is loaded const [isLoaded, setIsLoaded] = useState(false); function onLoad(app) { splineApp.current = app; setIsLoaded(true); } function triggerAnimation() { if (isLoaded && splineApp.current) { splineApp.current.emitEvent('mouseHover', 'Button'); } } // Also verify in Spline editor: // - Object has the correct name ('Button') // - mouseHover event is configured // - Event has action (state transition, etc.) ``` ### Pitfall 6: Hydration Errors in Next.js **Problem**: Mismatch between server and client render **Solution**: ```jsx // ❌ Wrong: Using standard import in Next.js import Spline from '@splinetool/react-spline'; // ✅ Correct: Use Next.js-specific import import Spline from '@splinetool/react-spline/next'; // Or use dynamic import with ssr: false import dynamic from 'next/dynamic'; const Spline = dynamic( () => import('@splinetool/react-spline'), { ssr: false } ); ``` ## Resources ### Official Documentation - **Spline Docs**: https://docs.spline.design - **React Spline GitHub**: https://github.com/splinetool/react-spline - **Spline Community**: https://spline.community ### Spline Editor - **Web App**: https://app.spline.design - **Desktop App**: Available for macOS, Windows, Linux ### Learning Resources - **Tutorials**: https://spline.design/tutorials - **YouTube Channel**: Official Spline tutorials - **Examples Gallery**: https://spline.design/community ### Export Formats - React component (via `@splinetool/react-spline`) - Vanilla JavaScript (Web Code API) - GLTF/GLB (for Three.js, Babylon.js) - USDZ (for Apple AR) - STL (for 3D printing) - Video/GIF (for marketing) ## Related Skills - **threejs-webgl**: For code-first 3D development with more control - **react-three-fiber**: For building 3D scenes with React and JSX - **babylonjs-engine**: Alternative 3D engine with editor workflow - **motion-framer**: For animating Spline containers and UI elements - **gsap-scrolltrigger**: For scroll-driven Spline animations - **figma-dev-mode**: For design-to-code workflow (similar visual approach) ## Scripts This skill includes utility scripts: - `project_generator.py` - Generate Spline + React starter projects - `component_builder.py` - Build Spline component wrappers with events Run scripts from the skill directory: ```bash ./scripts/project_generator.py ./scripts/component_builder.py ``` ## Assets Starter templates and examples: - `starter_spline/` - Complete React + Spline template - `examples/` - Real-world integration patterns [View on SkillFed](https://skillfed.io/freshtechbro/claudedesignskills/spline-interactive) · [View on GitHub](https://github.com/freshtechbro/claudedesignskills)