plugins/react-animation-studio/skills/background-animations/SKILL.md
Expert knowledge for creating stunning animated backgrounds - gradient flows, particle systems, mesh gradients, aurora effects, wave patterns, and dynamic textures that bring depth and life to your interfaces.
npx skillsauth add markus41/claude background-animationsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert knowledge for creating stunning animated backgrounds - gradient flows, particle systems, mesh gradients, aurora effects, wave patterns, and dynamic textures that bring depth and life to your interfaces.
Activate this skill when:
**/*.tsx with background components**/components/Background*.tsx**/components/Hero*.tsximport { motion } from 'framer-motion';
export function FlowingGradient() {
return (
<motion.div
className="absolute inset-0 -z-10"
style={{
background: 'linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab)',
backgroundSize: '400% 400%',
}}
animate={{
backgroundPosition: ['0% 50%', '100% 50%', '0% 50%'],
}}
transition={{
duration: 15,
repeat: Infinity,
ease: 'linear',
}}
/>
);
}
export function RadialPulse() {
return (
<motion.div
className="absolute inset-0 -z-10"
animate={{
background: [
'radial-gradient(circle at 50% 50%, #667eea 0%, transparent 50%)',
'radial-gradient(circle at 50% 50%, #764ba2 0%, transparent 70%)',
'radial-gradient(circle at 50% 50%, #667eea 0%, transparent 50%)',
],
}}
transition={{
duration: 4,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
);
}
export function MeshGradient() {
return (
<div className="absolute inset-0 -z-10 overflow-hidden">
<motion.div
className="absolute w-[150%] h-[150%] -left-[25%] -top-[25%]"
style={{
background: `
radial-gradient(at 40% 20%, #ff6b6b 0px, transparent 50%),
radial-gradient(at 80% 0%, #feca57 0px, transparent 50%),
radial-gradient(at 0% 50%, #48dbfb 0px, transparent 50%),
radial-gradient(at 80% 50%, #ff9ff3 0px, transparent 50%),
radial-gradient(at 0% 100%, #54a0ff 0px, transparent 50%),
radial-gradient(at 80% 100%, #5f27cd 0px, transparent 50%)
`,
}}
animate={{
rotate: [0, 360],
scale: [1, 1.1, 1],
}}
transition={{
rotate: { duration: 60, repeat: Infinity, ease: 'linear' },
scale: { duration: 10, repeat: Infinity, ease: 'easeInOut' },
}}
/>
</div>
);
}
import { motion } from 'framer-motion';
import { useMemo } from 'react';
interface Particle {
id: number;
x: number;
y: number;
size: number;
duration: number;
delay: number;
}
export function FloatingParticles({ count = 50 }: { count?: number }) {
const particles = useMemo<Particle[]>(() =>
Array.from({ length: count }, (_, i) => ({
id: i,
x: Math.random() * 100,
y: Math.random() * 100,
size: Math.random() * 4 + 2,
duration: Math.random() * 20 + 10,
delay: Math.random() * 5,
})),
[count]
);
return (
<div className="absolute inset-0 -z-10 overflow-hidden">
{particles.map((particle) => (
<motion.div
key={particle.id}
className="absolute rounded-full bg-white/20"
style={{
left: `${particle.x}%`,
top: `${particle.y}%`,
width: particle.size,
height: particle.size,
}}
animate={{
y: [0, -100, 0],
x: [0, Math.random() * 50 - 25, 0],
opacity: [0, 1, 0],
}}
transition={{
duration: particle.duration,
delay: particle.delay,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
))}
</div>
);
}
export function Starfield({ count = 200 }: { count?: number }) {
const stars = useMemo(() =>
Array.from({ length: count }, (_, i) => ({
id: i,
x: Math.random() * 100,
y: Math.random() * 100,
size: Math.random() * 2 + 0.5,
twinkleDuration: Math.random() * 3 + 2,
delay: Math.random() * 3,
})),
[count]
);
return (
<div className="absolute inset-0 -z-10 bg-slate-950 overflow-hidden">
{stars.map((star) => (
<motion.div
key={star.id}
className="absolute rounded-full bg-white"
style={{
left: `${star.x}%`,
top: `${star.y}%`,
width: star.size,
height: star.size,
}}
animate={{
opacity: [0.3, 1, 0.3],
scale: [1, 1.2, 1],
}}
transition={{
duration: star.twinkleDuration,
delay: star.delay,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
))}
</div>
);
}
export function AnimatedWaves() {
return (
<div className="absolute bottom-0 left-0 right-0 -z-10 h-64 overflow-hidden">
<svg
viewBox="0 0 1440 320"
className="absolute bottom-0 w-full"
preserveAspectRatio="none"
>
{/* Wave 1 - Back */}
<motion.path
fill="rgba(99, 102, 241, 0.3)"
d="M0,192L48,197.3C96,203,192,213,288,229.3C384,245,480,267,576,250.7C672,235,768,181,864,181.3C960,181,1056,235,1152,234.7C1248,235,1344,181,1392,154.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"
animate={{
d: [
"M0,192L48,197.3C96,203,192,213,288,229.3C384,245,480,267,576,250.7C672,235,768,181,864,181.3C960,181,1056,235,1152,234.7C1248,235,1344,181,1392,154.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
"M0,128L48,154.7C96,181,192,235,288,234.7C384,235,480,181,576,181.3C672,181,768,235,864,250.7C960,267,1056,245,1152,229.3C1248,213,1344,203,1392,197.3L1440,192L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
],
}}
transition={{
duration: 8,
repeat: Infinity,
repeatType: 'reverse',
ease: 'easeInOut',
}}
/>
{/* Wave 2 - Middle */}
<motion.path
fill="rgba(99, 102, 241, 0.5)"
d="M0,256L48,261.3C96,267,192,277,288,266.7C384,256,480,224,576,213.3C672,203,768,213,864,224C960,235,1056,245,1152,234.7C1248,224,1344,192,1392,176L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"
animate={{
d: [
"M0,256L48,261.3C96,267,192,277,288,266.7C384,256,480,224,576,213.3C672,203,768,213,864,224C960,235,1056,245,1152,234.7C1248,224,1344,192,1392,176L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
"M0,160L48,176C96,192,192,224,288,234.7C384,245,480,235,576,224C672,213,768,203,864,213.3C960,224,1056,256,1152,266.7C1248,277,1344,267,1392,261.3L1440,256L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
],
}}
transition={{
duration: 6,
repeat: Infinity,
repeatType: 'reverse',
ease: 'easeInOut',
}}
/>
{/* Wave 3 - Front */}
<motion.path
fill="rgba(99, 102, 241, 0.8)"
d="M0,288L48,282.7C96,277,192,267,288,272C384,277,480,299,576,293.3C672,288,768,256,864,250.7C960,245,1056,267,1152,272C1248,277,1344,267,1392,261.3L1440,256L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"
animate={{
d: [
"M0,288L48,282.7C96,277,192,267,288,272C384,277,480,299,576,293.3C672,288,768,256,864,250.7C960,245,1056,267,1152,272C1248,277,1344,267,1392,261.3L1440,256L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
"M0,256L48,261.3C96,267,192,277,288,272C384,267,480,245,576,250.7C672,256,768,288,864,293.3C960,299,1056,277,1152,272C1248,267,1344,277,1392,282.7L1440,288L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
],
}}
transition={{
duration: 4,
repeat: Infinity,
repeatType: 'reverse',
ease: 'easeInOut',
}}
/>
</svg>
</div>
);
}
export function AuroraBackground() {
return (
<div className="absolute inset-0 -z-10 overflow-hidden bg-slate-950">
{/* Aurora Layer 1 */}
<motion.div
className="absolute inset-0 opacity-50"
style={{
background: 'linear-gradient(180deg, transparent 0%, #00ff8855 30%, #00ffff33 50%, transparent 70%)',
filter: 'blur(60px)',
}}
animate={{
x: ['-20%', '20%', '-20%'],
skewX: ['-5deg', '5deg', '-5deg'],
}}
transition={{
duration: 15,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
{/* Aurora Layer 2 */}
<motion.div
className="absolute inset-0 opacity-40"
style={{
background: 'linear-gradient(180deg, transparent 0%, #ff00ff44 40%, #00ffff22 60%, transparent 80%)',
filter: 'blur(80px)',
}}
animate={{
x: ['20%', '-20%', '20%'],
skewX: ['5deg', '-5deg', '5deg'],
}}
transition={{
duration: 20,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
{/* Aurora Layer 3 */}
<motion.div
className="absolute inset-0 opacity-30"
style={{
background: 'linear-gradient(180deg, transparent 0%, #00ff0033 35%, #ff880022 55%, transparent 75%)',
filter: 'blur(100px)',
}}
animate={{
x: ['-10%', '10%', '-10%'],
y: ['-5%', '5%', '-5%'],
}}
transition={{
duration: 25,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
</div>
);
}
export function GrainOverlay() {
return (
<motion.div
className="pointer-events-none fixed inset-0 z-50 opacity-20"
style={{
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
}}
animate={{
x: [0, -10, 0],
y: [0, -10, 0],
}}
transition={{
duration: 0.2,
repeat: Infinity,
}}
/>
);
}
export function AnimatedGrid() {
return (
<div className="absolute inset-0 -z-10 overflow-hidden">
<motion.div
className="absolute inset-0"
style={{
backgroundImage: `
linear-gradient(rgba(99, 102, 241, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(99, 102, 241, 0.1) 1px, transparent 1px)
`,
backgroundSize: '50px 50px',
}}
animate={{
backgroundPosition: ['0px 0px', '50px 50px'],
}}
transition={{
duration: 20,
repeat: Infinity,
ease: 'linear',
}}
/>
{/* Glow effect at center */}
<div
className="absolute inset-0"
style={{
background: 'radial-gradient(circle at 50% 50%, transparent 0%, rgba(0,0,0,0.8) 100%)',
}}
/>
</div>
);
}
export function MorphingBlobs() {
const blobVariants = {
animate: {
d: [
"M440,320Q410,390,340,410Q270,430,200,410Q130,390,100,320Q70,250,100,180Q130,110,200,90Q270,70,340,90Q410,110,440,180Q470,250,440,320Z",
"M440,320Q440,390,370,420Q300,450,230,420Q160,390,120,320Q80,250,120,180Q160,110,230,80Q300,50,370,80Q440,110,440,180Q440,250,440,320Z",
"M440,320Q410,390,340,410Q270,430,200,410Q130,390,100,320Q70,250,100,180Q130,110,200,90Q270,70,340,90Q410,110,440,180Q470,250,440,320Z",
],
},
};
return (
<div className="absolute inset-0 -z-10 overflow-hidden">
<svg viewBox="0 0 500 500" className="absolute w-full h-full">
<defs>
<linearGradient id="blob-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stopColor="#667eea" />
<stop offset="100%" stopColor="#764ba2" />
</linearGradient>
</defs>
<motion.path
fill="url(#blob-gradient)"
variants={blobVariants}
animate="animate"
transition={{
duration: 10,
repeat: Infinity,
ease: 'easeInOut',
}}
style={{ filter: 'blur(40px)', opacity: 0.6 }}
/>
</svg>
</div>
);
}
will-change: transform for moving elementsfilter: blur() sparingly - it's expensiverequestAnimationFrame for canvas-based effectsCreated by Brookside BI as part of React Animation Studio
development
Enhanced plan-authoring skill with Pre-Writing context gathering, task metadata, non-TDD templates, Red Flags, telemetry, and an automated plan linter. Use when you have a spec or requirements for a multi-step task, before touching code.
tools
Documentation intelligence engine with graph-based API docs, algorithm library, and drift detection
tools
Ultraplan cloud planning — kick off a plan in the cloud from your terminal, review and revise in the browser, then execute remotely or send back to CLI
tools
--- name: mcp description: Configure MCP servers for Claude Code — stdio vs HTTP, authentication, Tools/Resources/Prompts distinction, channels (CI webhook, mobile relay, Discord bridge, fakechat), and cost of always-loaded tools. Use this skill whenever adding an MCP server, debugging connection issues, choosing between MCP Tools vs Prompts vs Resources, installing channel servers, or managing .mcp.json. Triggers on: "MCP server", "mcp config", "add Obsidian MCP", "install context7", "channels"