The prompt that made it
as published# BACKGROUND PAPER SHADERS — COMPONENT INTEGRATION
YOU ARE GIVEN A TASK TO INTEGRATE AN EXISTING REACT COMPONENT IN THE CODEBASE
THE CODEBASE SHOULD SUPPORT:
- SHADCN PROJECT STRUCTURE
- TAILWIND CSS
- TYPESCRIPT
IF IT DOESN'T, PROVIDE INSTRUCTIONS ON HOW TO SETUP PROJECT VIA SHADCN CLI, INSTALL TAILWIND OR TYPESCRIPT.
DETERMINE THE DEFAULT PATH FOR COMPONENTS AND STYLES.
IF DEFAULT PATH FOR COMPONENTS IS NOT /COMPONENTS/UI, PROVIDE INSTRUCTIONS ON WHY IT'S IMPORTANT TO CREATE THIS FOLDER
COPY-PASTE THIS COMPONENT TO /COMPONENTS/UI FOLDER:
```tsx
background-paper-shaders.tsx
"use client"
import { useRef, useMemo } from "react"
import { useFrame } from "@react-three/fiber"
import * as THREE from "three"
// Custom shader material for advanced effects
const vertexShader = `
uniform float time;
uniform float intensity;
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vUv = uv;
vPosition = position;
vec3 pos = position;
pos.y += sin(pos.x * 10.0 + time) * 0.1 * intensity;
pos.x += cos(pos.y * 8.0 + time * 1.5) * 0.05 * intensity;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`
const fragmentShader = `
uniform float time;
uniform float intensity;
uniform vec3 color1;
uniform vec3 color2;
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vec2 uv = vUv;
// Create animated noise pattern
float noise = sin(uv.x * 20.0 + time) * cos(uv.y * 15.0 + time * 0.8);
noise += sin(uv.x * 35.0 - time * 2.0) * cos(uv.y * 25.0 + time * 1.2) * 0.5;
// Mix colors based on noise and position
vec3 color = mix(color1, color2, noise * 0.5 + 0.5);
color = mix(color, vec3(1.0), pow(abs(noise), 2.0) * intensity);
// Add glow effect
float glow = 1.0 - length(uv - 0.5) * 2.0;
glow = pow(glow, 2.0);
gl_FragColor = vec4(color * glow, glow * 0.8);
}
`
export function ShaderPlane({
position,
color1 = "#ff5722",
color2 = "#ffffff",
}: {
position: [number, number, number]
color1?: string
color2?: string
}) {
const mesh = useRef<THREE.Mesh>(null)
const uniforms = useMemo(
() => ({
time: { value: 0 },
intensity: { value: 1.0 },
color1: { value: new THREE.Color(color1) },
color2: { value: new THREE.Color(color2) },
}),
[color1, color2],
)
useFrame((state) => {
if (mesh.current) {
uniforms.time.value = state.clock.elapsedTime
uniforms.intensity.value = 1.0 + Math.sin(state.clock.elapsedTime * 2) * 0.3
}
})
return (
<mesh ref={mesh} position={position}>
<planeGeometry args={[2, 2, 32, 32]} />
<shaderMaterial
uniforms={uniforms}
vertexShader={vertexShader}
fragmentShader={fragmentShader}
transparent
side={THREE.DoubleSide}
/>
</mesh>
)
}
export function EnergyRing({
radius = 1,
position = [0, 0, 0],
}: {
radius?: number
position?: [number, number, number]
}) {
const mesh = useRef<THREE.Mesh>(null)
useFrame((state) => {
if (mesh.current) {
mesh.current.rotation.z = state.clock.elapsedTime
mesh.current.material.opacity = 0.5 + Math.sin(state.clock.elapsedTime * 3) * 0.3
}
})
return (
<mesh ref={mesh} position={position}>
<ringGeometry args={[radius * 0.8, radius, 32]} />
<meshBasicMaterial color="#ff5722" transparent opacity={0.6} side={THREE.DoubleSide} />
</mesh>
)
}
demo.tsx
"use client"
import { useState } from "react"
import { MeshGradient, DotOrbit } from "@paper-design/shaders-react"
export default function DemoOne() {
const [intensity, setIntensity] = useState(1.5)
const [speed, setSpeed] = useState(1.0)
const [isInteracting, setIsInteracting] = useState(false)
const [activeEffect, setActiveEffect] = useState("mesh")
const [copied, setCopied] = useState(false)
const copyToClipboard = async () => {
try {
await navigator.clipboard.writeText("pnpm i 21st")
setCopied(true)
setTimeout(() => setCopied(false), 2000)
} catch (err) {
console.error("Failed to copy text: ", err)
}
}
return (
<div className="w-full h-screen bg-black relative overflow-hidden">
{activeEffect === "mesh" && (
<MeshGradient
className="w-full h-full absolute inset-0"
colors={["#000000", "#1a1a1a", "#333333", "#ffffff"]}
speed={speed}
backgroundColor="#000000"
/>
)}
{activeEffect === "dots" && (
<div className="w-full h-full absolute inset-0 bg-black">
<DotOrbit
className="w-full h-full"
dotColor="#333333"
orbitColor="#1a1a1a"
speed={speed}
intensity={intensity}
/>
</div>
)}
{activeEffect === "combined" && (
<>
<MeshGradient
className="w-full h-full absolute inset-0"
colors={["#000000", "#1a1a1a", "#333333", "#ffffff"]}
speed={speed * 0.5}
wireframe="true"
backgroundColor="#000000"
/>
<div className="w-full h-full absolute inset-0 opacity-60">
<DotOrbit
className="w-full h-full"
dotColor="#333333"
orbitColor="#1a1a1a"
speed={speed * 1.5}
intensity={intensity * 0.8}
/>
</div>
</>
)}
{/* UI Overlay */}
<div className="absolute inset-0 pointer-events-none">
{/* Header */}
<div className="absolute top-8 left-8 pointer-events-auto"></div>
{/* Effect Controls */}
<div className="absolute bottom-8 left-8 pointer-events-auto"></div>
{/* Parameter Controls */}
<div className="absolute bottom-8 right-8 pointer-events-auto space-y-4"></div>
{/* Status indicator */}
<div className="absolute top-8 right-8 pointer-events-auto"></div>
</div>
{/* Lighting overlay effects */}
<div className="absolute inset-0 pointer-events-none">
<div
className="absolute top-1/4 left-1/3 w-32 h-32 bg-gray-800/5 rounded-full blur-3xl animate-pulse"
style={{ animationDuration: `${3 / speed}s` }}
/>
<div
className="absolute bottom-1/3 right-1/4 w-24 h-24 bg-white/2 rounded-full blur-2xl animate-pulse"
style={{ animationDuration: `${2 / speed}s`, animationDelay: "1s" }}
/>
<div
className="absolute top-1/2 right-1/3 w-20 h-20 bg-gray-900/3 rounded-full blur-xl animate-pulse"
style={{ animationDuration: `${4 / speed}s`, animationDelay: "0.5s" }}
/>
</div>
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
<div className="text-center font-mono text-xs text-white/40">
<div>...21st-cli...</div>
<div className="mt-1 flex items-center gap-2">
<span>pnpm i 21st.dev</span>
<button
onClick={copyToClipboard}
className="pointer-events-auto opacity-30 hover:opacity-60 transition-opacity text-white/60 hover:text-white/80"
title="Copy to clipboard"
>
{copied ? (
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
) : (
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
)}
</button>
</div>
</div>
</div>
</div>
)
}
```
INSTALL NPM DEPENDENCIES:
```bash
three, @react-three/fiber
```
EXTEND EXISTING TAILWIND 4 INDEX.CSS WITH THIS CODE (OR IF PROJECT USES TAILWIND 3, EXTEND TAILWIND.CONFIG.JS OR GLOBALS.CSS):
```css
@import "tailwindcss";
@import "tw-animate-css";
@theme inline {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-destructive-foreground: var(--destructive-foreground);
}
:root {
--background: oklch(0 0 0);
--foreground: oklch(1 0 0);
--card: oklch(0.1 0 0 / 0.1);
--card-foreground: oklch(1 0 0);
--popover: oklch(0 0 0 / 0.8);
--popover-foreground: oklch(1 0 0);
--primary: oklch(1 0 0);
--primary-foreground: oklch(0 0 0);
--secondary: oklch(0.65 0.25 25);
--secondary-foreground: oklch(1 0 0);
--muted: oklch(1 0 0 / 0.5);
--muted-foreground: oklch(0.7 0 0);
--accent: oklch(0.65 0.25 25);
--accent-foreground: oklch(1 0 0);
--destructive: oklch(0.6 0.25 15);
--destructive-foreground: oklch(1 0 0);
--border: oklch(1 0 0 / 0.2);
--input: oklch(1 0 0 / 0.1);
--ring: oklch(1 0 0 / 0.3);
--chart-1: oklch(0.65 0.25 25);
--chart-2: oklch(0.8 0.15 85);
--chart-3: oklch(0.7 0.2 140);
--chart-4: oklch(0.7 0.2 240);
--chart-5: oklch(0.6 0.25 300);
--radius: 0.5rem;
--sidebar: oklch(0 0 0 / 0.9);
--sidebar-foreground: oklch(1 0 0);
--sidebar-primary: oklch(0.65 0.25 25);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.65 0.25 25);
--sidebar-accent-foreground: oklch(1 0 0);
--sidebar-border: oklch(1 0 0 / 0.2);
--sidebar-ring: oklch(1 0 0 / 0.3);
--font-geist-sans: "Geist Sans", sans-serif;
--font-geist-mono: "Geist Mono", monospace;
}
.dark {
--background: oklch(0 0 0);
--foreground: oklch(1 0 0);
--card: oklch(0.1 0 0 / 0.1);
--card-foreground: oklch(1 0 0);
--popover: oklch(0 0 0 / 0.8);
--popover-foreground: oklch(1 0 0);
--primary: oklch(1 0 0);
--primary-foreground: oklch(0 0 0);
--secondary: oklch(0.65 0.25 25);
--secondary-foreground: oklch(1 0 0);
--muted: oklch(1 0 0 / 0.5);
--muted-foreground: oklch(0.7 0 0);
--accent: oklch(0.65 0.25 25);
--accent-foreground: oklch(1 0 0);
--destructive: oklch(0.6 0.25 15);
--destructive-foreground: oklch(1 0 0);
--border: oklch(1 0 0 / 0.2);
--input: oklch(1 0 0 / 0.1);
--ring: oklch(1 0 0 / 0.3);
--chart-1: oklch(0.65 0.25 25);
--chart-2: oklch(0.8 0.15 85);
--chart-3: oklch(0.7 0.2 140);
--chart-4: oklch(0.7 0.2 240);
--chart-5: oklch(0.6 0.25 300);
--sidebar: oklch(0 0 0 / 0.9);
--sidebar-foreground: oklch(1 0 0);
--sidebar-primary: oklch(0.65 0.25 25);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.65 0.25 25);
--sidebar-accent-foreground: oklch(1 0 0);
--sidebar-border: oklch(1 0 0 / 0.2);
--sidebar-ring: oklch(1 0 0 / 0.3);
}
```
## IMPLEMENTATION GUIDELINES
1. ANALYZE THE COMPONENT STRUCTURE AND IDENTIFY ALL REQUIRED DEPENDENCIES
2. REVIEW THE COMPONENT'S ARGUMENS AND STATE
3. IDENTIFY ANY REQUIRED CONTEXT PROVIDERS OR HOOKS AND INSTALL THEM
4. QUESTIONS TO ASK
- WHAT DATA/PROPS WILL BE PASSED TO THIS COMPONENT?
- ARE THERE ANY SPECIFIC STATE MANAGEMENT REQUIREMENTS?
- ARE THERE ANY REQUIRED ASSETS (IMAGES, ICONS, ETC.)?
- WHAT IS THE EXPECTED RESPONSIVE BEHAVIOR?
- WHAT IS THE BEST PLACE TO USE THIS COMPONENT IN THE APP?
## STEPS TO INTEGRATE
0. COPY PASTE ALL THE CODE ABOVE IN THE CORRECT DIRECTORIES
1. INSTALL EXTERNAL DEPENDENCIES
2. FILL IMAGE ASSETS WITH UNSPLASH STOCK IMAGES YOU KNOW EXIST
3. USE LUCIDE-REACT ICONS FOR SVGS OR LOGOS IF COMPONENT REQUIRES THEMAdds a render step. Works best with the HyperFrames or Remotion skills installed. Free, no sign-up.
Prompt by @pulkitxm. Prompts belong to their creators.