references/catalog.md
# React Bits Component Catalog
172 components, 4 variants each (JS-CSS, JS-TW, TS-CSS, TS-TW). Generated from https://reactbits.dev/llms.txt + https://reactbits.dev/r/registry.json by `scripts/gen-catalog.mjs` — do not hand-edit, regenerate instead.
Format: `Name — one-line description (deps: ...)`. Fetch with:
```
node scripts/rb-add.mjs <Name> --variant <JS|TS>-<CSS|TW> --dest <path>
```
## Text Animations (32)
- **ASCIIText** — Renders text with an animated ASCII background for a retro feel. (deps: three)
- **BlurText** — Text starts blurred then crisply resolves for a soft-focus reveal effect. (deps: motion)
- **CircularText** — Layouts characters around a circle with optional rotation animation. (deps: motion)
- **CountUp** — Animated number counter supporting formatting and decimals. (deps: motion)
- **CurvedLoop** — Flowing looping text path along a customizable curve with drag interaction. (deps: none)
- **DecryptedText** — Hacker-style decryption cycling random glyphs until resolving to real text. (deps: motion)
- **DepthText** — Layered extruded type with parallax that shifts against the pointer. (deps: none)
- **EchoText** — Ghosted copies trail behind the text and settle into a single word. (deps: none)
- **FallingText** — Characters fall with gravity + bounce creating a playful entrance. (deps: matter-js)
- **FoldText** — Lines unfold into place like creased paper opening flat. (deps: gsap)
- **FuzzyText** — Vibrating fuzzy text with controllable hover intensity. (deps: none)
- **GlitchText** — RGB split and distortion glitch effect with jitter effects. (deps: none)
- **GradientText** — Animated gradient sweep across live text with speed and color control. (deps: motion)
- **MaskedHeading** — A large headline with a drifting colour mesh or image showing through the glyphs, revealed word by word. (deps: gsap)
- **ParticleText** — Text assembles from drifting particles that scatter and reform on demand. (deps: none)
- **RotatingText** — Cycles through multiple phrases with 3D rotate / flip transitions. (deps: motion)
- **ScrambledText** — Detects cursor position and applies a distortion effect to text. (deps: gsap)
- **ScrollFloat** — Text gently floats / parallax shifts on scroll. (deps: gsap)
- **ScrollReveal** — Text gently unblurs and reveals on scroll. (deps: gsap)
- **ScrollVelocity** — Text marquee animatio - speed and distortion scale with user's scroll velocity. (deps: motion)
- **ShinyText** — Metallic sheen sweeps across text producing a reflective highlight. (deps: motion)
- **Shuffle** — Animated text reveal where characters shuffle before settling. (deps: gsap,@gsap/react)
- **SplitFlapText** — Mechanical split-flap departure board that clacks through to each new phrase. (deps: none)
- **SplitText** — Splits text into characters / words for staggered entrance animation. (deps: gsap,@gsap/react)
- **StrokeText** — Outlined letterforms draw themselves on, then flood with fill. (deps: gsap)
- **TextCursor** — Make any text element follow your cursor, leaving a trail of copies behind it. (deps: motion)
- **TextLoop** — A seamless text marquee that flows along curved SVG paths. (deps: gsap)
- **TextPressure** — Characters scale / warp interactively based on pointer pressure zone. (deps: none)
- **TextType** — Typewriter effect with blinking cursor and adjustable typing cadence. (deps: gsap)
- **TrueFocus** — Applies dynamic blur / clarity based over a series of words in order. (deps: motion)
- **VariableProximity** — Letter styling changes continuously with pointer distance mapping. (deps: motion)
- **WarpText** — WebGL warp that bends and refracts the text around the pointer. (deps: ogl)
## Animations (38)
- **AnimatedContent** — Wrapper that animates any children on scroll or mount with configurable direction, distance, duration, easing and disappear options. (deps: gsap)
- **Antigravity** — 3D antigravity particle field that repels from the cursor with smooth motion. (deps: @react-three/fiber,three)
- **BlobCursor** — Organic blob cursor that smoothly follows the pointer with inertia and elastic morphing. (deps: gsap)
- **ClickSpark** — Creates particle spark bursts at click position. (deps: none)
- **Crosshair** — Custom crosshair cursor with tracking, and link hover effects. (deps: gsap)
- **Cubes** — 3D rotating cube cluster. Supports auto-rotation or hover interaction. (deps: gsap)
- **CursorGrid** — Canvas grid whose cells light up around the cursor with configurable radius, falloff and click pulses. (deps: none)
- **ElasticMesh** — Spring-mesh surface that stretches under the pointer and settles back with damped physics. (deps: ogl)
- **ElectricBorder** — Jittery electric energy border with animated arcs, glow and adjustable intensity. (deps: none)
- **FadeContent** — Simple directional fade / slide entrance / exit wrapper with threshold-based activation. (deps: gsap)
- **GhostCursor** — Semi-transparent ghost cursor that smoothly follows the real cursor with a trailing effect. (deps: three)
- **GlareHover** — Adds a realistic moving glare highlight on hover over any element. (deps: none)
- **GlowCursor** — Shader-powered light trail that smoothly follows the pointer with customizable glow, color, taper and pulse. (deps: ogl)
- **GradualBlur** — Progressively un-blurs content based on scroll or trigger creating a cinematic reveal. (deps: none)
- **HalftoneReveal** — Print-style halftone dot matrix that resolves into sharp content around the cursor. (deps: ogl)
- **ImageTrail** — Cursor-based image trail with several built-in variants. (deps: gsap)
- **LaserFlow** — Dynamic laser light that flows onto a surface, customizable effect. (deps: three)
- **LogoLoop** — Continuously looping marquee of brand or tech logos with seamless repeat and hover pause. (deps: none)
- **MagicRings** — Interactive magic rings effect with customizable parameters. (deps: three)
- **Magnet** — Elements magnetically ease toward the cursor then settle back with spring physics. (deps: none)
- **MagnetLines** — Animated field lines bend toward the cursor. (deps: none)
- **MetaBalls** — Liquid metaball blobs that merge and separate with smooth implicit surface animation. (deps: ogl)
- **MetallicPaint** — Liquid metallic paint shader which can be applied to SVG elements. (deps: none)
- **Noise** — Animated film grain / noise overlay adding subtle texture and motion. (deps: none)
- **OrbitImages** — SVG Path customizable orbiting images effect. (deps: motion)
- **PixelSwap** — Pixel fragments assemble into a full cover, swap arbitrary content, then dissolve away with reversible colors and triggers. (deps: none)
- **PixelTrail** — Pixelated cursor trail emitting fading squares with retro digital feel. (deps: @react-three/drei,@react-three/fiber,three)
- **PixelTransition** — Pixel dissolve transition for content reveal on hover. (deps: gsap)
- **Ribbons** — Flowing responsive ribbons/cursor trail driven by physics and pointer motion. (deps: ogl)
- **RippleDistortion** — Pointer-driven water displacement that warps content and leaves a decaying wake. (deps: ogl)
- **ScrollExpand** — A rounded media frame that grows to full bleed as it scrolls through the viewport. (deps: none)
- **ShapeBlur** — Morphing blurred geometric shape. The effect occurs on hover. (deps: three)
- **SplashCursor** — Liquid splash burst at cursor with curling ripples and waves. (deps: none)
- **StarBorder** — Animated star / sparkle border orbiting content with twinkle pulses. (deps: none)
- **StickerPeel** — Sticker corner lift + peel interaction using 3D transform and shadow depth. (deps: gsap)
- **Strands** — Glowing ribbon-like strands that ripple and weave across a transparent canvas. (deps: ogl)
- **SwarmCursor** — Flocking particle swarm that chases the pointer, jostles for space and drifts apart at rest. (deps: ogl)
- **TargetCursor** — A cursor follow animation with 4 corners that lock onto targets. (deps: react-dom,gsap)
## Components (45)
- **AccordionGallery** — Panels expand on hover or focus, revealing parallax imagery and captions. (deps: gsap)
- **AnimatedList** — List items enter with staggered motion variants for polished reveals. (deps: motion)
- **BorderGlow** — Glowing mesh-gradient border that follows cursor direction and intensifies near edges. (deps: none)
- **BounceCards** — Cards bounce that bounce in on mount. (deps: gsap)
- **BubbleMenu** — Floating circular expanding menu with staggered item reveal. (deps: gsap)
- **CardNav** — Expandable navigation bar with card panels revealing nested links. (deps: gsap,react-icons)
- **CardSwap** — Cards animate position swapping with smooth layout transitions. (deps: gsap)
- **Carousel** — Responsive carousel with touch gestures, looping and transitions. (deps: motion,react-icons)
- **ChromaGrid** — A responsive grid of grayscale tiles. Hovering the grid reaveals their colors. (deps: gsap)
- **CircularGallery** — Circular orbit gallery rotating images. (deps: ogl)
- **Counter** — Flexible animated counter supporting increments + easing. (deps: motion)
- **CurvedInput** — Arc-bent input bar with text, caret and submit button all following the curve. (deps: none)
- **DecayCard** — Hover parallax effect that disintegrates the content of a card. (deps: gsap)
- **DepthCarousel** — Cards recede into depth on a 3D rail, with drag, keyboard and auto-advance. (deps: gsap)
- **Dock** — macOS style magnifying dock with proximity scaling of icons. (deps: motion)
- **DomeGallery** — Immersive 3D dome gallery projecting images on a hemispheric surface. (deps: @use-gesture/react)
- **DriftWall** — An endless perspective wall of tiles drifting past, lifting on hover. (deps: none)
- **ElasticSlider** — Slider handle stretches elastically then snaps with spring physics. (deps: motion)
- **FlowingMenu** — Liquid flowing active indicator glides between menu items. (deps: gsap)
- **FluidGlass** — Glassmorphism container with animated liquid distortion refraction. (deps: three,@react-three/fiber,@react-three/drei,maath)
- **FlyingPosters** — 3D posters rotate on scroll infinitely. (deps: ogl)
- **Folder** — Interactive folder opens to reveal nested content smooth motion. (deps: none)
- **GlassIcons** — Icon set styled with frosted glass blur. (deps: none)
- **GlassSurface** — Advanced Apple-style glass surface with real-time distortion + lighting. (deps: none)
- **GooeyNav** — Navigation indicator morphs with gooey blob transitions between items. (deps: none)
- **InfiniteMenu** — Horizontally looping menu effect that scrolls endlessly with seamless wrap. (deps: gl-matrix)
- **InfiniteSpiral** — An endlessly looping 3D helix of images with customizable motion, depth, spacing and interaction. (deps: none)
- **Lanyard** — Swinging 3D lanyard / badge card with realistic inertial motion. (deps: none)
- **LineSidebar** — Static list navigation with a cursor-proximity effect that shifts and highlights nearby items. (deps: none)
- **MagicBento** — Interactive bento grid tiles expand + animate with various options. (deps: gsap)
- **Masonry** — Responsive masonry layout with animated reflow + gaps optimization. (deps: gsap)
- **ModelViewer** — Three.js model viewer with orbit controls and lighting presets. (deps: @react-three/fiber,@react-three/drei,three)
- **MorphSlider** — WebGL slider that melts between images with a displacement transition. (deps: ogl,gsap)
- **OptionWheel** — Curved option picker that spins via scroll, drag, or arrow keys, fading and tilting items away from the selection. (deps: none)
- **PillNav** — Minimal pill nav with sliding active highlight + smooth easing. (deps: react-router-dom,gsap)
- **PixelCard** — Card content revealed through pixel expansion transition. (deps: none)
- **ProfileCard** — Animated profile card glare with 3D hover effect. (deps: none)
- **ReflectiveCard** — Card with dynamic webcam reflection and glare effects that respond to cursor movement. (deps: lucide-react)
- **ScrollStack** — Overlapping card stack reveals on scroll with depth layering. (deps: lenis)
- **SpecularButton** — Glass button with a shader-driven specular rim light that sweeps around the edge and follows the cursor. (deps: ogl)
- **SpotlightCard** — Dynamic spotlight follows cursor casting gradient illumination. (deps: none)
- **Stack** — Layered stack with swipe animations, autoplay and smooth transitions. (deps: motion)
- **StaggeredMenu** — Menu with staggered item animations and smooth transitions on open/close. (deps: gsap)
- **Stepper** — Animated multi-step progress indicator with active state transitions. (deps: motion)
- **TiltedCard** — 3D perspective tilt card reacting to pointer. (deps: motion)
## Backgrounds (57)
- **AcidSquares** — A crystalline corridor of stacked squares receding into depth. (deps: ogl)
- **AeroShards** — A GPU-driven wind sculpture of folded foil shards with crisp detail, content-safe placements, and responsive pointer interactions. (deps: vgpu)
- **Aurora** — Flowing aurora gradient background. (deps: ogl)
- **Balatro** — The balatro shader, fully customizalbe and interactive. (deps: ogl)
- **Ballpit** — Physics ball pit simulation with bouncing colorful spheres. (deps: gsap,three)
- **Beams** — Crossing animated ribbons with customizable properties. (deps: three,@react-three/fiber,@react-three/drei)
- **ColorBends** — Vibrant color bends with smooth flowing animation. (deps: three)
- **CRTWarp** — Full-canvas CRT plasma with curved distortion, scanlines, bloom and pointer interaction. (deps: three)
- **DarkVeil** — Subtle dark background with a smooth animation and postprocessing. (deps: ogl)
- **Dither** — Retro dithered noise shader background. (deps: @react-three/fiber,@react-three/postprocessing,postprocessing,three)
- **DotField** — Interactive dot grid with cursor bulge, glow, sparkle, and wave effects. (deps: none)
- **DotGrid** — Animated dot grid with cursor interactions. (deps: gsap)
- **EvilEye** — Procedural evil eye shader with animated iris, slit pupil, and fiery outer glow. (deps: ogl)
- **FaultyTerminal** — Terminal CRT scanline squares effect with flicker + noise. (deps: ogl)
- **Ferrofluid** — A churning magnetic fluid traced by glowing contour lines, with a cursor magnet. (deps: ogl)
- **FloatingLines** — 3D floating lines that react to cursor movement. (deps: three)
- **Galaxy** — Parallax realistic starfield with pointer interactions. (deps: ogl)
- **GhostFibers** — A deep-blue recursive fiber field with luminous bands, radial twisting and soft atmospheric glow. (deps: ogl)
- **GradientBlinds** — Layered gradient blinds with spotlight and noise distortion. (deps: ogl)
- **GradientWaves** — Raymarched sine waves rolling toward a soft, hazy horizon. (deps: ogl)
- **Grainient** — Grainy gradient swirls with soft wave distortion. (deps: ogl)
- **GridDistortion** — Warped grid mesh distorts smoothly reacting to cursor. (deps: three)
- **GridMotion** — Perspective moving grid lines based on cusror position. (deps: gsap)
- **GridScan** — Animated grid room 3D scan effect and cool interactions. (deps: face-api.js,postprocessing,three)
- **Hyperspeed** — Animated lines continuously moving to simulate hyperspace travel on click hold. (deps: postprocessing,three)
- **Iridescence** — Slick iridescent shader with shifting waves. (deps: ogl)
- **LetterGlitch** — Matrix style letter animation. (deps: none)
- **Lightfall** — Colorful light streaks raining down a glowing tunnel with a cursor light. (deps: ogl)
- **Lightning** — Procedural lightning bolts with branching and glow flicker. (deps: none)
- **LightPillar** — Vertical pillar of light with glow effects. (deps: three)
- **LightRays** — Volumetric light rays/beams with customizable direction. (deps: ogl)
- **LightTunnel** — A radial fibre-optic tunnel with light pulses racing into depth. (deps: ogl)
- **LineWaves** — Animated line wave pattern with colorful warped distortion. (deps: ogl)
- **LiquidChrome** — Liquid metallic chrome shader with flowing reflective surface. (deps: ogl)
- **LiquidEther** — Interactive liquid shader with flowing distortion and customizable colors. (deps: three)
- **MoltenMetal** — Swirling caustic plasma filaments with molten, white-hot cores. (deps: ogl)
- **Orb** — Floating energy orb with customizable hover effect. (deps: ogl)
- **Particles** — Configurable particle system. (deps: ogl)
- **PixelBlast** — Exploding pixel particle bursts with optional liquid postprocessing. (deps: postprocessing,three)
- **PixelSnow** — Falling pixelated snow effect with customizable density and speed. (deps: three)
- **Plasma** — Organic plasma gradients swirl + morph with smooth turbulence. (deps: ogl)
- **PlasmaWave** — Raymarched plasma waves with dual-wave interference and OGL. (deps: ogl)
- **Prism** — Rotating prism with configurable intensity, size, and colors. (deps: ogl)
- **PrismaticBurst** — Burst of light rays with controllable color, distortion, amount. (deps: ogl)
- **Radar** — Radar sweep effect with concentric rings, radial spokes, and a rotating beam. (deps: ogl)
- **RippleGrid** — A grid that continuously animates with a ripple effect. (deps: ogl)
- **Scanner** — Calm interference bands sweeping across the screen like an oscilloscope. (deps: ogl)
- **ShapeGrid** — Animated grid with shape variants (square, hexagon, circle, triangle) + direction customization. (deps: none)
- **ShapeWaves** — A WebGPU field of triangles, circles and squares that brighten and grow along rolling waves, with an optional text cutout the waves flow around. (deps: vgpu)
- **SideRays** — Animated light rays emanating from the side with customizable colors and speed. (deps: ogl)
- **Silk** — Smooth waves background with soft lighting. (deps: @react-three/fiber,three)
- **SlicedWaves** — A grid of soft glowing bars rippling like a slatted equalizer. (deps: ogl)
- **SoftAurora** — Soft aurora borealis shader with 3D Perlin noise and cosine gradient palettes. (deps: ogl)
- **Threads** — Animated pattern of lines forming a fabric-like motion. (deps: ogl)
- **Topography** — A living contour map with glowing, elevation-tinted lines. (deps: ogl)
- **Waves** — Layered lines that form smooth wave patterns with animation. (deps: none)
- **WebThreads** — Glowing sine threads woven through a luminous convergence point. (deps: ogl)
scripts/gen-catalog.mjs
#!/usr/bin/env node
// gen-catalog — regenerate references/catalog.md from the live React Bits registry + llms.txt.
//
// node scripts/gen-catalog.mjs
//
// Two sources, cross-checked:
// https://reactbits.dev/r/registry.json — component names, deps, files (no category)
// https://reactbits.dev/llms.txt — category + one-line description (no deps)
// registry.json has no category field, so llms.txt is the only source for grouping.
import { writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const BASE = 'https://reactbits.dev';
const CATEGORIES = ['Text Animations', 'Animations', 'Components', 'Backgrounds'];
const OUT = join(dirname(fileURLToPath(import.meta.url)), '..', 'references', 'catalog.md');
async function getJson(url) {
const res = await fetch(url);
const text = await res.text();
console.log(`fetched ${url} -> HTTP ${res.status}, ${text.length} bytes`);
if (text.trimStart().startsWith('<')) throw new Error(`${url} returned the SPA HTML shell`);
return JSON.parse(text);
}
async function getText(url) {
const res = await fetch(url);
const text = await res.text();
console.log(`fetched ${url} -> HTTP ${res.status}, ${text.length} bytes`);
if (text.trimStart().startsWith('<')) throw new Error(`${url} returned the SPA HTML shell`);
return text;
}
// "name@range" -> "name", handling scoped packages like "@react-three/fiber@^9.3.0"
function depName(spec) {
const m = /^(@[^/]+\/[^@]+|[^@]+)@?(.*)$/.exec(spec);
return m ? m[1] : spec;
}
function parseLlmsTxt(text) {
const byName = new Map();
let category = null;
for (const line of text.split('\n')) {
const h = /^## (.+)$/.exec(line.trim());
if (h) {
category = h[1];
continue;
}
if (!CATEGORIES.includes(category)) continue;
const m = /^- \[.+?\]\(.+?\): (.+?) CLI: `(\w+)`\.$/.exec(line.trim());
if (m) byName.set(m[2], { category, description: m[1] });
}
return byName;
}
const [registry, llms] = await Promise.all([
getJson(`${BASE}/r/registry.json`),
getText(`${BASE}/llms.txt`),
]);
const meta = parseLlmsTxt(llms);
const byTitle = new Map();
for (const item of registry.items) {
if (!item.name.endsWith('-TS-TW')) continue; // one entry per component is enough for deps/description
byTitle.set(item.title, item);
}
const missingFromLlms = [...byTitle.keys()].filter((t) => !meta.has(t));
const missingFromRegistry = [...meta.keys()].filter((t) => !byTitle.has(t));
if (missingFromLlms.length) throw new Error(`in registry but not llms.txt: ${missingFromLlms.join(', ')}`);
if (missingFromRegistry.length) throw new Error(`in llms.txt but not registry: ${missingFromRegistry.join(', ')}`);
const byCategory = new Map(CATEGORIES.map((c) => [c, []]));
for (const [name, { category, description }] of meta) {
const deps = (byTitle.get(name).dependencies ?? []).map(depName);
byCategory.get(category).push({ name, description, deps: deps.length ? deps.join(',') : 'none' });
}
for (const list of byCategory.values()) list.sort((a, b) => a.name.localeCompare(b.name));
const total = [...byCategory.values()].reduce((n, l) => n + l.length, 0);
const lines = [
'# React Bits Component Catalog',
'',
`${total} components, 4 variants each (JS-CSS, JS-TW, TS-CSS, TS-TW). Generated from ${BASE}/llms.txt + ${BASE}/r/registry.json by \`scripts/gen-catalog.mjs\` — do not hand-edit, regenerate instead.`,
'',
'Format: `Name — one-line description (deps: ...)`. Fetch with:',
'```',
'node scripts/rb-add.mjs <Name> --variant <JS|TS>-<CSS|TW> --dest <path>',
'```',
];
for (const category of CATEGORIES) {
const items = byCategory.get(category);
lines.push(`\n## ${category} (${items.length})\n`);
for (const { name, description, deps } of items) {
lines.push(`- **${name}** — ${description} (deps: ${deps})`);
}
}
await writeFile(OUT, lines.join('\n') + '\n', 'utf8');
console.log(`wrote ${OUT} (${total} components)`);
scripts/rb-add.mjs
#!/usr/bin/env node
// rb-add — fetch React Bits components from the public shadcn registry.
//
// node scripts/rb-add.mjs Aurora BlurText --variant TS-TW --dest src/components
// node scripts/rb-add.mjs --list
// node scripts/rb-add.mjs Aurora --install
//
// The registry is a static shadcn registry:
// index https://reactbits.dev/r/registry.json
// component https://reactbits.dev/r/<Name>-<JS|TS>-<CSS|TW>.json
//
// reactbits.dev is an SPA: unknown paths return HTTP 200 with an HTML shell,
// so every response must be JSON-validated. Status code alone proves nothing.
import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, join, resolve } from 'node:path';
import { execFileSync } from 'node:child_process';
const BASE = 'https://reactbits.dev';
const VARIANTS = ['JS-CSS', 'JS-TW', 'TS-CSS', 'TS-TW'];
async function getJson(url) {
const res = await fetch(url);
const text = await res.text();
if (text.trimStart().startsWith('<')) {
throw new Error(`${url} returned the SPA HTML shell (component does not exist)`);
}
try {
return JSON.parse(text);
} catch {
throw new Error(`${url} returned non-JSON (${res.status}, ${text.length} bytes)`);
}
}
// Deps are "name@range" strings, but 10 components use scoped packages
// ("@react-three/fiber@^9.3.0"). Splitting on "@" naively yields "".
export function parseDep(spec) {
const m = /^(@[^/]+\/[^@]+|[^@]+)@(.*)$/.exec(spec);
return m ? { name: m[1], range: m[2] } : { name: spec, range: '' };
}
async function loadIndex() {
const reg = await getJson(`${BASE}/r/registry.json`);
const byTitle = new Map();
for (const item of reg.items) {
const variant = item.name.slice(item.title.length + 1);
if (!byTitle.has(item.title)) byTitle.set(item.title, { title: item.title, variants: {} });
byTitle.get(item.title).variants[variant] = item;
}
return byTitle;
}
function resolveName(index, input) {
if (index.has(input)) return input;
const hit = [...index.keys()].find((t) => t.toLowerCase() === input.toLowerCase().replace(/-/g, ''));
if (hit) return hit;
const near = [...index.keys()].filter((t) => t.toLowerCase().includes(input.toLowerCase())).slice(0, 5);
throw new Error(`unknown component "${input}"${near.length ? ` — did you mean: ${near.join(', ')}?` : ''}`);
}
async function add(name, { variant, dest, index }) {
const title = resolveName(index, name);
const entry = index.get(title);
if (!entry.variants[variant]) {
throw new Error(`${title} has no ${variant} variant (has: ${Object.keys(entry.variants).join(', ')})`);
}
const item = await getJson(`${BASE}/r/${title}-${variant}.json`);
if (!item.files?.length) throw new Error(`${title}-${variant} has no files`);
const written = [];
for (const file of item.files) {
if (!file.content) throw new Error(`${title}-${variant}: ${file.path} has empty content`);
const out = resolve(dest, file.path);
await mkdir(dirname(out), { recursive: true });
await writeFile(out, file.content, 'utf8');
written.push({ path: join(dest, file.path), bytes: file.content.length });
}
return { title, description: item.description, written, deps: (item.dependencies ?? []).map(parseDep) };
}
const argv = process.argv.slice(2);
const flag = (name, fallback) => {
const i = argv.indexOf(`--${name}`);
return i === -1 ? fallback : argv[i + 1];
};
const variant = flag('variant', 'TS-TW');
const dest = flag('dest', 'src/components');
const doInstall = argv.includes('--install');
const names = argv.filter((a, i) => !a.startsWith('--') && !argv[i - 1]?.match(/^--(variant|dest)$/));
if (!VARIANTS.includes(variant)) {
console.error(`--variant must be one of ${VARIANTS.join(', ')}`);
process.exit(1);
}
const index = await loadIndex();
if (argv.includes('--list')) {
for (const title of [...index.keys()].sort()) console.log(title);
console.log(`\n${index.size} components`);
process.exit(0);
}
if (!names.length) {
console.error('usage: rb-add <Component...> [--variant TS-TW] [--dest src/components] [--install] [--list]');
process.exit(1);
}
const deps = new Map();
let failed = 0;
for (const name of names) {
try {
const r = await add(name, { variant, dest, index });
for (const d of r.deps) deps.set(d.name, d.range);
const files = r.written.map((w) => `${w.path} (${w.bytes}B)`).join(', ');
console.log(`ok ${r.title.padEnd(20)} ${files}`);
} catch (err) {
failed++;
console.error(`FAIL ${name.padEnd(20)} ${err.message}`);
}
}
if (deps.size) {
const specs = [...deps].map(([n, r]) => (r ? `${n}@${r}` : n));
console.log(`\ndependencies: ${specs.join(' ')}`);
if (doInstall) {
console.log('installing...');
execFileSync('npm', ['install', ...specs], { stdio: 'inherit' });
} else {
console.log(`\n npm install ${specs.join(' ')}`);
}
}
process.exit(failed ? 1 : 0);
SKILL.md
---
name: react-bits
description: Use when adding an animated UI component, text effect, cursor/hover effect, or WebGL/canvas background to a React project via React Bits (reactbits.dev) — or when asked to recall/write a React Bits component's code, props, or install steps from memory instead of fetching it.
---
# React Bits
Fetches real, current component source from the React Bits public registry instead of recalling it from training data. React Bits (reactbits.dev, MIT + Commons Clause, by David Haz) publishes 165 animated components — Text Animations, Animations, Components, Backgrounds — each in 4 variants (JS/TS × CSS/Tailwind).
## The hard rule
**Never write React Bits component code from memory. Always fetch it live.**
Verified failure mode (baseline test, no skill): asked for Aurora + BlurText, an agent hallucinated plausible-looking code, guessed `framer-motion` as a dependency (the live package is `motion`), invented prop defaults, and only disclosed the guessing when explicitly asked. The code looked complete and shippable. It wasn't current.
Training data goes stale; this library updates variants in sync. If you can't reach the registry, say so — don't fall back to recalled code.
## Fetch
```bash
node scripts/rb-add.mjs <Component> [<Component>...] --variant <JS|TS>-<CSS|TW> --dest <path> [--install]
node scripts/rb-add.mjs --list # print all 165 names
```
Writes real source files to `--dest` (default `src/components`) and prints the exact `npm install` line for that component's dependencies (default variant: `TS-TW`). `--install` runs it for you.
No script access? Fetch directly — same registry, same rules:
```bash
curl -s https://reactbits.dev/r/<Name>-<JS|TS>-<CSS|TW>.json # one component, files[].content = source
curl -s https://reactbits.dev/r/registry.json # index, 660 entries, no source, no category field
```
**reactbits.dev is an SPA** — an unknown path still returns HTTP 200 with an HTML shell. A 200 status proves nothing; parse the body as JSON and check it before trusting it.
## Workflow
1. **Confirm the variant** — JS or TS, CSS or Tailwind. Default to matching the project's existing files; ask if genuinely ambiguous.
2. **Find the component** — grep [references/catalog.md](references/catalog.md) (offline, 165 entries with category + description + deps) or `--list`.
3. **Fetch it** with `rb-add.mjs` (above). Never hand-write the file.
4. **Read the fetched file's own prop type/interface before wiring it up.** Don't guess prop names or defaults even for a component you fetched — read what's actually in the file.
5. **Install the printed dependencies** (or pass `--install`).
## Gotchas
- **Scoped-package deps break naive parsing.** 10 components depend on scoped packages, e.g. `PixelTrail` → `@react-three/fiber@^9.3.0`. Splitting a dep string on `@` to get the name yields `""` for these. `rb-add.mjs` parses correctly (`/^(@[^/]+\/[^@]+|[^@]+)@?(.*)$/`); don't reimplement this by hand.
- **CSS variants are multi-file.** `JS-CSS`/`TS-CSS` ship a component file *and* a sibling `.css` file (both must be written). `JS-TW`/`TS-TW` are single-file with Tailwind utility classes.
- **No category field in the registry.** `registry.json` has name/title/deps/files only. Category (Text Animations / Animations / Components / Backgrounds) lives only in `references/catalog.md` (sourced from `reactbits.dev/llms.txt`).
- **`verbatimModuleSyntax` TS projects**: some fetched files import types alongside values in one `import {...}` statement (e.g. `import { motion, Transition } from 'motion/react'`) — split into a separate `import type {...}` if the project's tsconfig has `verbatimModuleSyntax: true`. This is a mechanical fix, not a reason to rewrite the component.
## Categories (165 total)
Text Animations (32) · Animations (36) · Components (44) · Backgrounds (53). Full list with one-line descriptions and dependencies: [references/catalog.md](references/catalog.md) — a GitHub Action regenerates it daily from the live registry, so it stays current without a skill update. Manual refresh: `node scripts/gen-catalog.mjs`.
## After installing
For a craft-bar review of the motion you just wired up (easing, duration, frequency-appropriateness, reduced-motion), the upstream repo ships separate skills at `DavidHDev/react-bits/AGENTS/SKILLS/` (`review-animations`, `improve-animations`, `find-animation-opportunities`, `apple-design`) — not bundled here, distinct concern (craft review vs. correct fetch/install).