Claude
Skills
Sign in
Back

unicorn-studio

Included with Lifetime
$97 forever

Setup Unicorn Studio WebGL shaders for stunning visual effects. Use this skill when the user says "setup shaders", "add unicorn studio", "webgl effects", "shader effects", "visual effects", or "unicorn.studio".

General

What this skill does


# Unicorn Studio WebGL Shaders for Next.js

No-code WebGL shader effects with the unicornstudio-react package. Create stunning visual backgrounds, hero sections, and interactive effects.

## Installation

```bash
bun add unicornstudio-react
```

**Version Compatibility:**
- Next.js 15+ with React 19: `[email protected]+`
- SDK version: `[email protected]` (38kb gzipped)

## Configuration Schema

All Unicorn Studio scenes use a single JSON configuration object:

```typescript
type UnicornSceneConfig = {
  // Scene Source (required - choose ONE)
  projectId?: string;           // Unicorn Studio embed ID (cloud-hosted)
  jsonFilePath?: string;        // Path to self-hosted JSON file

  // Dimensions
  width?: number | string;      // Default: "100%"
  height?: number | string;     // Default: "100%"

  // Performance
  scale?: number;               // 0.25-1.0, rendering scale (default: 1)
  dpi?: number;                 // 1.0-2.0, pixel ratio (default: 1.5)
  fps?: 15 | 24 | 30 | 60 | 120;  // Valid frame rates (default: 60)

  // Behavior
  lazyLoad?: boolean;           // Load when visible (default: true)
  production?: boolean;         // Use CDN (default: true)

  // Accessibility
  altText?: string;             // SEO alternative text
  ariaLabel?: string;           // Screen reader label

  // Placeholder
  placeholder?: string;         // Image URL or React component
  showPlaceholderWhileLoading?: boolean;  // Default: true
  showPlaceholderOnError?: boolean;       // Default: true

  // Callbacks
  onLoad?: () => void;
  onError?: (error: Error) => void;
};
```

## Basic Usage

### 1. Client Component with Cloud-Hosted Scene

```tsx
// components/shader/unicorn-scene.tsx
"use client";

import UnicornScene from "unicornstudio-react/next";

type ShaderSceneProps = {
  projectId: string;
  className?: string;
};

export function ShaderScene({ projectId, className }: ShaderSceneProps) {
  return (
    <div className={className}>
      <UnicornScene
        projectId={projectId}
        width="100%"
        height="100%"
        scale={1}
        dpi={1.5}
        fps={60}
        lazyLoad={true}
        production={true}
        altText="Interactive shader effect"
        ariaLabel="Animated WebGL background"
        onLoad={() => console.log("Shader loaded")}
        onError={(err) => console.error("Shader error:", err)}
      />
    </div>
  );
}
```

### 2. Dynamic Import Wrapper (SSR-Safe)

```tsx
// components/shader/dynamic-shader.tsx
"use client";

import dynamic from "next/dynamic";

export const DynamicShader = dynamic(
  () => import("./unicorn-scene").then((mod) => mod.ShaderScene),
  {
    ssr: false,
    loading: () => (
      <div className="h-full w-full animate-pulse bg-gradient-to-br from-muted to-muted/50" />
    ),
  }
);
```

### 3. Use in Page

```tsx
// app/page.tsx
import { DynamicShader } from "@/components/shader/dynamic-shader";

export default function HomePage() {
  return (
    <main>
      {/* Hero with Shader Background */}
      <section className="relative h-screen w-full overflow-hidden">
        <div className="absolute inset-0">
          <DynamicShader
            projectId="YOUR_PROJECT_EMBED_ID"
            className="h-full w-full"
          />
        </div>
        <div className="relative z-10 flex h-full items-center justify-center">
          <h1 className="text-5xl font-bold text-white drop-shadow-lg">
            Welcome
          </h1>
        </div>
      </section>
    </main>
  );
}
```

## Self-Hosted JSON (Legend Subscribers)

For self-hosting shaders via JSON export:

### 1. Export Scene from Unicorn Studio

1. Open your project in Unicorn Studio
2. Click Export > Code (JSON)
3. Download the `.json` file
4. Place in `public/shaders/` directory

### 2. Use with jsonFilePath

```tsx
"use client";

import UnicornScene from "unicornstudio-react/next";

export function SelfHostedShader() {
  return (
    <UnicornScene
      jsonFilePath="/shaders/hero-effect.json"
      width="100%"
      height="100%"
      scale={1}
      dpi={1.5}
      lazyLoad={true}
    />
  );
}
```

### Example JSON Structure

```json
{
  "version": "2.0.1",
  "name": "Hero Gradient",
  "width": 1920,
  "height": 1080,
  "fps": 60,
  "layers": [
    {
      "type": "gradient",
      "colors": ["#667eea", "#764ba2"],
      "angle": 45,
      "animated": true
    }
  ],
  "effects": [
    {
      "type": "noise",
      "intensity": 0.1,
      "scale": 2.0
    }
  ],
  "interactivity": {
    "mouse": {
      "enabled": true,
      "strength": 0.5
    }
  }
}
```

## Performance Configuration

### Performance Presets

```tsx
// High Performance (Mobile-friendly)
const mobileConfig = {
  scale: 0.5,
  dpi: 1,
  fps: 30,
  lazyLoad: true,
};

// Balanced (Default)
const balancedConfig = {
  scale: 0.75,
  dpi: 1.5,
  fps: 60,
  lazyLoad: true,
};

// High Quality (Desktop)
const highQualityConfig = {
  scale: 1,
  dpi: 2,
  fps: 60,
  lazyLoad: false,
};
```

### Adaptive Performance Component

```tsx
"use client";

import { useState, useEffect } from "react";
import UnicornScene from "unicornstudio-react/next";

type PerformanceLevel = "low" | "medium" | "high";

const PERFORMANCE_CONFIGS: Record<PerformanceLevel, {
  scale: number;
  dpi: number;
  fps: 15 | 24 | 30 | 60 | 120;
}> = {
  low: { scale: 0.5, dpi: 1, fps: 30 },
  medium: { scale: 0.75, dpi: 1.5, fps: 60 },
  high: { scale: 1, dpi: 2, fps: 60 },
};

type AdaptiveShaderProps = {
  projectId: string;
  className?: string;
};

export function AdaptiveShader({ projectId, className }: AdaptiveShaderProps) {
  const [performanceLevel, setPerformanceLevel] = useState<PerformanceLevel>("medium");

  useEffect(() => {
    // Detect device capability
    const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
    const hasReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const hardwareConcurrency = navigator.hardwareConcurrency || 4;

    if (hasReducedMotion || isMobile || hardwareConcurrency < 4) {
      setPerformanceLevel("low");
    } else if (hardwareConcurrency >= 8) {
      setPerformanceLevel("high");
    } else {
      setPerformanceLevel("medium");
    }
  }, []);

  const config = PERFORMANCE_CONFIGS[performanceLevel];

  return (
    <div className={className}>
      <UnicornScene
        projectId={projectId}
        width="100%"
        height="100%"
        {...config}
        lazyLoad={true}
        production={true}
      />
    </div>
  );
}
```

## Common Patterns

### Hero Section with Overlay

```tsx
export function ShaderHero({
  projectId,
  title,
  subtitle,
}: {
  projectId: string;
  title: string;
  subtitle?: string;
}) {
  return (
    <section className="relative h-[80vh] min-h-[600px] w-full overflow-hidden">
      {/* Shader Background */}
      <div className="absolute inset-0">
        <DynamicShader projectId={projectId} className="h-full w-full" />
      </div>

      {/* Gradient Overlay */}
      <div className="absolute inset-0 bg-gradient-to-t from-background via-background/50 to-transparent" />

      {/* Content */}
      <div className="relative z-10 flex h-full flex-col items-center justify-center px-4 text-center">
        <h1 className="text-4xl font-bold text-foreground md:text-6xl">
          {title}
        </h1>
        {subtitle && (
          <p className="mt-4 max-w-2xl text-lg text-muted-foreground">
            {subtitle}
          </p>
        )}
      </div>
    </section>
  );
}
```

### Card with Shader Background

```tsx
export function ShaderCard({
  projectId,
  children,
}: {
  projectId: string;
  children: React.ReactNode;
}) {
  return (
    <div className="relative overflow-hidden rounded-xl border border-border">
      <div className="absolute inset-0 opacity-30">
        <DynamicShader projectId={projectId} className="h-full w-full" />
      </div>
      <div className="relative z-10 p-6">{children}</div>
    </div>
  );
}
```

### Interacti
Files: 4
Size: 62.7 KB
Complexity: 50/100
Category: General

Related in General