# React Bits Admin & Architecture Guide

This guide is for developers, architects, and maintainers who want to understand how the React Bits project is built, how it works internally, how to run and deploy it, and how to extend it. It covers the dual nature of the repository — a **component registry** and a **documentation web app** — along with the build pipeline, the four-variant component system, the registry generation that powers CLI installs, and operational concerns for self-hosting a fork.

> [!NOTE]
> This is the *internals* guide. For how to consume React Bits components in your own app (install, props, variants), see the **User Guide**. The two documents are complementary: the User Guide treats React Bits as a product; this guide treats the repository as a system.

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [System Architecture](#2-system-architecture)
3. [Technology Stack](#3-technology-stack)
4. [Repository Structure](#4-repository-structure)
5. [The Four-Variant Component System](#5-the-four-variant-component-system)
6. [The Registry: How CLI Installs Work](#6-the-registry-how-cli-installs-work)
7. [Build & Development Workflow](#7-build--development-workflow)
8. [The Documentation Web App](#8-the-documentation-web-app)
9. [Configuration Reference](#9-configuration-reference)
10. [Deployment](#10-deployment)
11. [Adding & Maintaining Components](#11-adding--maintaining-components)
12. [Security Analysis](#12-security-analysis)
13. [Code Quality & Patterns](#13-code-quality--patterns)
14. [Operations & Troubleshooting](#14-operations--troubleshooting)
15. [Potential Improvements](#15-potential-improvements)
16. [Quick Reference](#16-quick-reference)

---

## 1. Executive Summary

React Bits is a **registry-distributed React component library** with an integrated documentation site. One repository serves two purposes:

1. **A component registry** — 130+ animated components, each authored in four variants (JavaScript/TypeScript × plain-CSS/Tailwind). A build step compiles these into a static registry under `public/r/` that the [shadcn](https://ui.shadcn.com/) and [jsrepo](https://jsrepo.dev/) CLIs consume to copy components into end-user projects.
2. **A documentation single-page app** — a Vite + React 19 site (deployed at [reactbits.dev](https://reactbits.dev)) that previews every component, exposes interactive prop controls, generates copy-ready code, and hosts creative tools.

| Attribute | Value |
|-----------|-------|
| Project type | Registry-distributed component library + documentation SPA |
| Language | JavaScript / TypeScript (React 19) |
| Build tool | Vite 5 |
| Registry tooling | `jsrepo` + `@jsrepo/shadcn` |
| Deployment target | Cloudflare (static assets, SPA fallback) |
| Package status | Private (`"private": true`, `"version": "0.0.0"`) — **not** published to npm |
| License | MIT + Commons Clause |
| Maintainer | David Haz ([DavidHDev](https://github.com/DavidHDev)) |

> [!IMPORTANT]
> The repository is **not** an installable npm package. Its `package.json` is `private` with version `0.0.0`. The distributable output is the generated **registry** (`public/r/`), not a bundle. This is the defining architectural decision: components are *delivered as source*, copied into consumer projects, never imported as a dependency.

---

## 2. System Architecture

There are two distinct data flows: the **authoring/registry flow** (how components reach end users) and the **site flow** (how the docs SPA renders).

```
┌──────────────────────────────────────────────────────────────────────┐
│ AUTHORING / REGISTRY FLOW                                              │
│                                                                        │
│   src/content/      (JS-CSS source — canonical authoring location)     │
│   src/tailwind/     (JS-TW source)                                     │
│   src/ts-default/   (TS-CSS source)                                    │
│   src/ts-tailwind/  (TS-TW source)                                     │
│        │                                                               │
│        │  jsrepo build  (reads jsrepo.config.ts + componentMetadata)   │
│        ▼                                                               │
│   public/r/*.json   (generated registry: one entry per variant)       │
│        │                                                               │
│        │  served at https://reactbits.dev/r/<Name>-<VARIANT>          │
│        ▼                                                               │
│   shadcn / jsrepo CLI  ──copies source──▶  end-user project           │
└──────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────┐
│ DOCS SITE FLOW (Vite SPA)                                              │
│                                                                        │
│   main.jsx ─▶ <Provider> ─▶ <App> (react-router-dom)                   │
│        │                                                               │
│        ├─ /                       LandingPage                          │
│        ├─ /showcase               ShowcasePage                         │
│        ├─ /sponsors               SponsorsPage                         │
│        ├─ /tools/:toolId?         ToolsPage (Background Studio, …)     │
│        ├─ /:category/:subcategory CategoryPage (component demos)       │
│        └─ /favorites              FavoritesPage                        │
│                                                                        │
│   CategoryPage lazy-loads demos from src/demo/<Category>/<Name>Demo    │
│   Demos render the live component + interactive prop controls          │
│   Prop state is synced to the URL via nuqs (shareable preview links)   │
└──────────────────────────────────────────────────────────────────────┘
```

**Key insight:** `src/content/` (and its three sibling variant trees) is *both* the authoring source for the registry *and* the source the demos render. There is no duplication between "library code" and "site code" — the site renders the very components it distributes.

---

## 3. Technology Stack

### Core

| Dependency | Version | Role |
|------------|---------|------|
| `react` / `react-dom` | `^19.0.0` | UI runtime |
| `vite` | `^5.3.4` | Dev server + bundler |
| `@vitejs/plugin-react` | `^4.3.4` | React fast-refresh / JSX |
| `react-router-dom` | `^6.30.1` | SPA routing |
| `typescript` | `^5.7.3` | Types for TS variants + config |

### Registry tooling

| Dependency | Version | Role |
|------------|---------|------|
| `jsrepo` | `^3.2.0` | Registry build + CLI distribution |
| `@jsrepo/shadcn` | `^2.0.0` | Emits shadcn-compatible registry output |

### Styling / UI

| Dependency | Version | Role |
|------------|---------|------|
| `@chakra-ui/react`, `@chakra-ui/icons` | `^3.20.0` / `^2.2.4` | Site UI components |
| `@emotion/react` | `^11.14.0` | Chakra styling engine |
| `tailwindcss`, `@tailwindcss/vite` | `^4.0.3` | Tailwind variants + site styling |
| `tailwind-merge`, `clsx`, `class-variance-authority` | — | Tailwind class composition |
| `geist` | `^1.7.0` | Font |
| `next-themes` | `^0.4.6` | Theme/color-mode handling |
| `lucide-react`, `react-icons` | — | Icon sets |
| `sonner` | `^1.7.1` | Toast notifications |

### Animation / graphics (per-component dependencies)

| Dependency | Version | Used by |
|------------|---------|---------|
| `gsap`, `@gsap/react` | `^3.13.0` / `^2.1.2` | Text animations, scroll triggers (e.g. `SplitText`) |
| `motion` | `^12.23.12` | Motion-driven components/landing |
| `three`, `@react-three/fiber`, `@react-three/drei`, `@react-three/postprocessing`, `@react-three/rapier` | — | 3D components/backgrounds (`ModelViewer`, `Lanyard`, `Ballpit`) |
| `ogl` | `^1.0.11` | Lightweight WebGL shaders (`Aurora`, `PlasmaWave`) |
| `postprocessing` | `^6.36.0` | Post-effects on backgrounds |
| `matter-js` | `^0.20.0` | Physics (`Ballpit`-style effects) |
| `gl-matrix`, `maath`, `mathjs`, `meshline` | — | Math/geometry helpers for shaders |
| `face-api.js` | `^0.22.2` | `ReflectiveCard` webcam features |
| `lenis` | `^1.3.13` | Smooth scrolling |
| `nuqs` | `^2.8.6` | URL-synced prop state for previews |
| `react-virtualized` | `^9.22.6` | Virtualized component index grid |
| `react-syntax-highlighter` | `^15.6.1` | Code blocks on the site |
| `react-confetti`, `react-haiku`, `@use-gesture/react` | — | Misc. interactions |

### Dev tooling

`eslint` (`^8.57.0`) with `eslint-plugin-react`, `eslint-plugin-react-hooks`, `eslint-plugin-react-refresh`; `prettier` (`^3.6.2`); `concurrently` for parallel dev scripts; `tw-animate-css`; `postcss-safe-parser`.

> [!NOTE]
> Most graphics dependencies are **per-component**, not site-wide for end users. The full set lives in this repo's `package.json` because the site renders every component; a consumer only installs what their chosen components require (the registry declares each component's deps).

---

## 4. Repository Structure

```
react-bits/
├── index.html                  # Vite entry HTML
├── package.json                # Private; scripts + full dependency set
├── vite.config.js              # Vite config (aliases, Tailwind, PostCSS)
├── jsrepo.config.ts            # Registry definition (THE registry source of truth)
├── tsconfig.json               # TypeScript config
├── wrangler.jsonc              # Cloudflare deployment config
├── README.md / CONTRIBUTING.md / LICENSE.md
├── scripts/
│   ├── generateComponent.js    # Scaffolds a new component across all 4 variants
│   ├── generateLlmsText.js     # Builds llms.txt for AI consumption
│   └── generateSitemap.js      # Builds sitemap.xml
├── public/
│   ├── r/                      # GENERATED registry (521 files) — jsrepo output
│   └── assets/                 # Videos, images, fonts, demo assets
└── src/
    ├── main.jsx                # React root (mounts <Provider><App/></Provider>)
    ├── App.jsx                 # Router + route table
    ├── content/                # JS-CSS component source  (authoring + demos)
    ├── tailwind/               # JS-TW  component source
    ├── ts-default/             # TS-CSS component source
    ├── ts-tailwind/            # TS-TW  component source
    ├── demo/                   # Per-component demo wrappers used on the site
    ├── docs/                   # Get-Started docs as JSX (Introduction, Installation, McpServer)
    ├── pages/                  # Route-level pages (Landing, Category, Showcase, …)
    ├── components/
    │   ├── common/             # Site UI (ComponentList, BackToTopButton, Preview, …)
    │   ├── landingnew/         # Landing page sections (Hero, Features, QuickStart, …)
    │   ├── context/            # React context providers (Installation, ActiveRoute, …)
    │   ├── layout/             # Providers, SidebarLayout
    │   ├── navs/ code/ setup/  # Navigation, code display, Chakra provider setup
    ├── constants/
    │   ├── Categories.js       # Sidebar grouping of components
    │   ├── Components.js        # category → lazy demo import maps (componentMap)
    │   ├── Information.js       # componentMetadata (THE catalog) + VARIANTS
    │   ├── code/               # Per-component code snippets shown on the site
    │   ├── Tools.js Sponsors.js Showcase.js Site.js colors.js
    ├── hooks/                  # useComponentProps, useInstallation, useStars, …
    ├── utils/                  # cli.js, codeGeneration.js, favorites.js, fuzzy.js, …
    ├── tools/                  # Background Studio, Shape Magic, Texture Lab
    ├── css/                    # Site stylesheets
    └── assets/                 # Logos, icons, fonts
```

> [!TIP]
> Two files are disproportionately important: **`jsrepo.config.ts`** (defines what the registry exposes) and **`src/constants/Information.js`** (`componentMetadata` — the authoritative catalog). The registry config *imports* the catalog, so adding a component is fundamentally about adding a metadata entry plus the four source files.

---

## 5. The Four-Variant Component System

Every component exists in four physically separate source trees, keyed by language and styling:

| Variant | Source tree | File(s) |
|---------|-------------|---------|
| `JS-CSS` | `src/content/<Category>/<Name>/` | `<Name>.jsx` + `<Name>.css` |
| `JS-TW` | `src/tailwind/<Category>/<Name>/` | `<Name>.jsx` |
| `TS-CSS` | `src/ts-default/<Category>/<Name>/` | `<Name>.tsx` + `<Name>.css` |
| `TS-TW` | `src/ts-tailwind/<Category>/<Name>/` | `<Name>.tsx` |

`<Category>` is one of `Animations`, `TextAnimations`, `Components`, `Backgrounds`.

The Vite config exposes aliases for each tree:

```js
// vite.config.js
resolve: {
  alias: {
    '@': '/src',
    '@utils':       'src/utils',
    '@content':     'src/content',     // JS-CSS
    '@tailwind':    'src/tailwind',    // JS-TW
    '@ts-default':  'src/ts-default',  // TS-CSS
    '@ts-tailwind': 'src/ts-tailwind', // TS-TW
    'react-virtualized': 'react-virtualized/dist/commonjs',
  }
}
```

> [!IMPORTANT]
> **All four variants of a component must stay in sync.** The contribution guide is explicit: *"Each component change must be updated in all 4 variants of that particular component."* A fix applied to only `src/content/` will ship a divergent registry for the other three variants. This is the single biggest maintenance burden of the architecture.

---

## 6. The Registry: How CLI Installs Work

The registry is the distributable artifact. It is defined declaratively in `jsrepo.config.ts` and built into `public/r/`.

### 6.1 Registry definition

```ts
// jsrepo.config.ts (abridged)
import { defineConfig, type RegistryItem } from 'jsrepo';
import { output } from '@jsrepo/shadcn';
import { componentMetadata } from './src/constants/Information';

export default defineConfig({
  registry: {
    name: '@react-bits',
    homepage: 'https://reactbits.dev',
    repository: 'https://github.com/DavidHDev/react-bits',
    excludeDeps: ['react'],
    outputs: [output({ dir: 'public/r', format: true })],
    items: [
      ...Object.values(componentMetadata).map(component =>
        defineComponent({
          title: component.name,
          description: component.description,
          category: component.category,
          variants: component.variants,
        })
      )
    ].flat()
  }
});
```

### 6.2 How variants become registry entries

`defineComponent()` expands each catalog entry into up to four `RegistryItem`s, one per variant, each pointing at the correct source tree:

| Variant | Registry item name | Files included |
|---------|--------------------|----------------|
| `JS-CSS` | `<Name>-JS-CSS` | `src/content/<Category>/<Name>` |
| `JS-TW` | `<Name>-JS-TW` | `src/tailwind/<Category>/<Name>` |
| `TS-CSS` | `<Name>-TS-CSS` | `src/ts-default/<Category>/<Name>` |
| `TS-TW` | `<Name>-TS-TW` | `src/ts-tailwind/<Category>/<Name>` |

Defaults: if a catalog entry doesn't restrict `variants`, all four are generated (`['JS-CSS','JS-TW','TS-CSS','TS-TW']`).

> [!NOTE]
> **`react` is excluded from declared dependencies** (`excludeDeps: ['react']`) — consumers already have React, so the registry won't try to install it.

### 6.3 Special case: Lanyard

`defineComponent()` special-cases the **Lanyard** component:

- `dependencyResolution: 'manual'` — its dependencies aren't auto-resolved.
- It lists explicit files (the `.css`/source) rather than a whole directory, because it bundles a 3D `.glb` asset that the generic directory-include would mishandle.

This is why Lanyard historically failed under `shadcn add` with a parse error on the binary asset (issue [#960](https://github.com/DavidHDev/react-bits/issues/960)).

### 6.4 Output and serving

- The build writes one JSON file per registry item into `public/r/` (~521 generated files in the current source).
- After deployment, each is served at `https://reactbits.dev/r/<Name>-<VARIANT>` (and `.../r/<name>.json` for the shadcn registry shorthand).
- Consumers fetch these via `shadcn add @react-bits/<Name>-<VARIANT>` or `jsrepo add https://reactbits.dev/r/<Name>-<VARIANT>`.

> [!WARNING]
> `public/r/` is **generated output**, not hand-edited source. Never edit files under `public/r/` directly — they are overwritten by `jsrepo build`. Edit the component source trees and rebuild.

---

## 7. Build & Development Workflow

All workflows are driven by `package.json` scripts.

| Script | Command | Purpose |
|--------|---------|---------|
| `dev` | `concurrently … "npm run registry:dev" "vite"` | Run the registry watcher **and** the Vite dev server together. |
| `registry:dev` | `jsrepo build --watch` | Rebuild the registry on source changes. |
| `registry:build` | `jsrepo build` | One-off registry build → `public/r/`. |
| `build` | `npm run registry:build && npm run llms:text && npm run sitemap && vite build` | Full production build. |
| `llms:text` | `node ./scripts/generateLlmsText.js` | Generate `llms.txt` for AI consumption. |
| `sitemap` | `node ./scripts/generateSitemap.js` | Generate the sitemap. |
| `new:component` | `node scripts/generateComponent.js` | Scaffold a new component (all variants). |
| `lint` | `eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0` | Lint (zero-warning policy). |
| `format` | `prettier --write .` | Format the codebase. |

### 7.1 Local development

```bash
npm install
npm run dev
```

This launches two processes concurrently (labeled `registry` and `docs`):
- `jsrepo build --watch` keeps `public/r/` in sync as you edit components.
- `vite` serves the docs site with HMR.

### 7.2 Production build

```bash
npm run build
```

Build order matters: the registry is generated **first**, then `llms.txt` and the sitemap, then Vite bundles the site into `dist/`. The Vite step copies `public/` (including the freshly built `public/r/`) into `dist/`, so the served site includes the registry.

> [!TIP]
> Because `build` runs `registry:build` first, a production build always ships a registry consistent with the current component source. If you only ran `vite build`, you could deploy a stale registry — always use the composite `build` script for releases.

### 7.3 Build configuration notes

- **PostCSS uses `postcss-safe-parser`** (`vite.config.js`) so malformed CSS in component files degrades gracefully rather than failing the build.
- **`.glb` files are treated as assets** (`assetsInclude: ['**/*.glb']`) for 3D components.
- **HMR is explicitly enabled** in the dev server config.

---

## 8. The Documentation Web App

### 8.1 Entry & providers

`src/main.jsx` mounts the app inside a Chakra `Provider`, and `src/App.jsx` wraps everything in `Router` → `NuqsAdapter` → `ActiveRouteProvider` → `Providers` (context + Chakra theme), rendering an `AnnouncementModal` globally. On mount, `App` forces dark color mode (`forceChakraDarkTheme()`).

> [!NOTE]
> `main.jsx` deliberately pre-warms `react-syntax-highlighter` by rendering an empty `<SyntaxHighlighter>` into a detached root before mounting the app — a performance trick to load the highlighter chunk early so code blocks render instantly.

### 8.2 Routing

| Route | Page | Notes |
|-------|------|-------|
| `/` | `LandingPage` | Hero, Features, Testimonials, LiveDemo, QuickStart, Sponsors, CTA, Footer; shows a loader until fonts are ready. |
| `/showcase` | `ShowcasePage` | Community projects using React Bits. |
| `/sponsors` | `SponsorsPage` | Sponsor tiers (diamond/platinum/silver) + stats. |
| `/tools/:toolId?` | `ToolsPage` | Lazy-loads Background Studio, Shape Magic, Texture Lab. |
| `/:category/:subcategory` | `CategoryPage` (in `SidebarLayout`) | Renders a component's demo, or the Get-Started docs / Index. |
| `/favorites` | `FavoritesPage` (in `SidebarLayout`) | User's saved components (localStorage). |

### 8.3 Component demos & the catalog

- `src/constants/Information.js` exports `componentMetadata` — the authoritative catalog mapping `"<Category>/<Name>"` → `{ name, description, category, docsUrl, tags, … }`. It also exports `VARIANTS = ['JS-CSS','JS-TW','TS-CSS','TS-TW']`.
- `src/constants/Components.js` exports `componentMap` — slug → lazy `import()` of the demo in `src/demo/`. `CategoryPage` uses this to code-split each demo.
- `src/constants/Categories.js` defines the sidebar grouping and the `NEW` highlight list.

### 8.4 Interactive previews

The site's defining feature is **live prop editing with shareable URLs**:

- `useComponentProps(defaultProps)` (in `src/hooks/`) syncs each prop to the URL query string via **nuqs**, with type-aware parsers for numbers, booleans, and hex colors. Editing a prop updates the URL; sharing the URL reproduces the exact preview.
- `src/utils/codeGeneration.js` turns the current prop values back into a JSX usage snippet (`generatePropsString`, `injectPropsIntoUsage`, `createUsageExample`), so the displayed code always matches the live preview.
- `src/utils/cli.js` (`generateCliCommands`) builds the shadcn/jsrepo/manual install commands for the selected language, style, and package manager.

### 8.5 Supporting features

- **Search** — `src/utils/fuzzy.js` implements Levenshtein-based fuzzy matching for the component index.
- **Favorites** — `src/utils/favorites.js` persists saved components in `localStorage` under `savedComponents`, broadcasting a `favorites:updated` event for cross-tab/state sync.
- **Virtualized index** — `ComponentList` uses `react-virtualized` (`Grid`, `AutoSizer`, `WindowScroller`) to render the large component grid efficiently.
- **Star count** — `useStars` fetches and caches the GitHub star count in `localStorage` for 24 hours, with a default fallback.
- **Installation preference** — `useInstallation` / `InstallationContext` remembers the user's preferred CLI tool and package manager.

---

## 9. Configuration Reference

### 9.1 `vite.config.js`

| Setting | Value | Purpose |
|---------|-------|---------|
| `plugins` | `react()`, `tailwindcss()` | React + Tailwind v4 |
| `server.hmr` | `true` | Hot module replacement |
| `resolve.alias` | `@`, `@utils`, `@content`, `@tailwind`, `@ts-default`, `@ts-tailwind`, `react-virtualized` | Import shortcuts per variant tree |
| `css.postcss.parser` | `postcss-safe-parser` | Tolerant CSS parsing |
| `assetsInclude` | `['**/*.glb']` | Bundle 3D models as assets |

### 9.2 `jsrepo.config.ts`

| Setting | Value |
|---------|-------|
| `registry.name` | `@react-bits` |
| `registry.homepage` | `https://reactbits.dev` |
| `registry.repository` | `https://github.com/DavidHDev/react-bits` |
| `registry.excludeDeps` | `['react']` |
| `registry.outputs` | `output({ dir: 'public/r', format: true })` (shadcn output) |
| `registry.items` | Generated from `componentMetadata` via `defineComponent()` |

### 9.3 `wrangler.jsonc` (Cloudflare)

```jsonc
{
  "name": "react-bits",
  "compatibility_date": "2025-06-15",
  "assets": {
    "directory": "./dist",
    "not_found_handling": "single-page-application"
  }
}
```

| Setting | Value | Purpose |
|---------|-------|---------|
| `assets.directory` | `./dist` | Serve the Vite build output |
| `assets.not_found_handling` | `single-page-application` | Route unknown paths to `index.html` (client-side routing) |

> [!NOTE]
> There are **no application secrets or environment variables** required to build or run React Bits. It is a fully static site plus a static registry; it has no backend, database, or API keys. The only network calls are client-side (e.g. fetching the GitHub star count).

---

## 10. Deployment

React Bits deploys as a **static site on Cloudflare**.

### 10.1 Deploy steps

```bash
# 1. Build (registry → llms.txt → sitemap → vite build into ./dist)
npm run build

# 2. Deploy ./dist to Cloudflare (Wrangler)
npx wrangler deploy
```

The `wrangler.jsonc` config serves `./dist` with SPA fallback, so deep links like `/components/dock` resolve to `index.html` and are handled by `react-router-dom`.

### 10.2 What gets served

- The bundled SPA (`index.html`, JS/CSS chunks, assets).
- The generated registry under `/r/` (copied from `public/r/` into `dist/r/`), making `https://reactbits.dev/r/<Name>-<VARIANT>` available to CLI consumers.
- `llms.txt` and `sitemap.xml` from the generator scripts.

> [!IMPORTANT]
> The registry's availability depends on the site deployment. If the site is down, `shadcn add @react-bits/...` and the `https://reactbits.dev/r/...` URL form will fail. The `jsrepo add github/davidhaz/react-bits ...` form is resilient to site downtime because it pulls from GitHub directly.

### 10.3 Self-hosting a fork

To run your own instance:

1. Fork and `npm install`.
2. Update `jsrepo.config.ts` (`homepage`, `repository`) and any hard-coded `reactbits.dev` URLs (notably in `src/utils/cli.js`, which builds install URLs against `https://reactbits.dev`).
3. `npm run build` and deploy `./dist` to any static host (Cloudflare, Netlify, Vercel static, S3+CloudFront). For non-Cloudflare hosts, configure SPA fallback to `index.html`.

> [!CAUTION]
> If you self-host but leave `src/utils/cli.js`'s `baseUrl = 'https://reactbits.dev'` unchanged, the install commands your site shows will point users back at the official registry, not your fork.

---

## 11. Adding & Maintaining Components

### 11.1 Scaffold a new component

```bash
npm run new:component <ComponentType> <ComponentName>
# e.g.
npm run new:component Backgrounds MyEffect
```

`scripts/generateComponent.js` creates empty files across every tree:

```
src/content/<Type>/<Name>/<Name>.jsx
src/content/<Type>/<Name>/<Name>.css
src/tailwind/<Type>/<Name>/<Name>.jsx
src/ts-default/<Type>/<Name>/<Name>.tsx
src/ts-default/<Type>/<Name>/<Name>.css
src/ts-tailwind/<Type>/<Name>/<Name>.tsx
src/demo/<Type>/<Name>Demo.jsx
src/constants/code/<Type>/<name>Code.js
```

### 11.2 Wire it up

1. Fill in all four variant source files (keep them behaviorally identical).
2. Write the demo in `src/demo/<Type>/<Name>Demo.jsx`.
3. Add a metadata entry to `componentMetadata` in `src/constants/Information.js` (name, description, category, `docsUrl`).
4. Register the demo import in `src/constants/Components.js` (`componentMap`).
5. Add the display name to the right category in `src/constants/Categories.js` (and to `NEW` if it's a fresh addition).
6. Run `npm run registry:build` and verify a `<Name>-*` entry appears under `public/r/`.

### 11.3 Contribution rules

From `CONTRIBUTING.md`:

- Branch naming: `feat/<feature-name>`.
- PRs target `main`.
- **Every component change must be reflected in all four variants.**
- Test locally on desktop and mobile; check the console for errors.
- **New community components are not currently accepted** — only enhancements and bug fixes to existing components.

> [!WARNING]
> The "all four variants" rule is enforced by review, not tooling. There is no automated check that the four variants of a component are equivalent — divergence is a real risk and a good candidate for future CI (see [Potential Improvements](#15-potential-improvements)).

---

## 12. Security Analysis

React Bits is a static, client-only project with a small attack surface, but there are points worth understanding — especially because its core model is **shipping source code into other people's projects**.

### 12.1 Trust model — code is copied, not sandboxed

The defining security consideration: components are **copied as source into consumer projects** and run with full application privileges. Consumers should review the source they install (which is the point of the model — full visibility), but they inherit whatever the component does.

| Area | Assessment |
|------|------------|
| **Supply chain** | No npm package means no post-install scripts reach consumers; they get plain source files. The risk shifts to *the registry serving the expected source* — i.e. integrity of `reactbits.dev`. |
| **WebGL / canvas** | Components run shaders and animation loops with client resources. Malicious shaders aren't a concern in this first-party repo, but resource exhaustion (high CPU/GPU) is a real UX risk (issue [#953](https://github.com/DavidHDev/react-bits/issues/953)). |
| **Webcam access** | `ReflectiveCard` uses `face-api.js`/webcam input. Consumers embedding it must obtain user consent and handle permissions; the effect requests camera access on the client. |
| **External fetches** | The site fetches the GitHub stars API client-side (`utils.js`). No credentials are sent. |
| **Outbound links** | Sponsor/showcase links use `rel="noreferrer"`/`noopener` (verified in `SponsorsPage`/`ShowcasePage`), mitigating reverse-tabnabbing. |

### 12.2 No secrets, no backend

There are **no environment variables, API keys, or server-side code** in the repository. There is nothing to leak in the build, and no authentication/authorization surface. This substantially reduces the security footprint.

### 12.3 Recommendations for consumers

> [!TIP]
> Before deploying a React Bits component to production: (1) read the installed source — you own it; (2) sandbox or gate webcam/3D components behind explicit user action; (3) lazy-load and unmount heavy WebGL backgrounds; (4) pin the per-component dependency versions you install.

---

## 13. Code Quality & Patterns

### 13.1 Conventions

- **Functional components + hooks throughout.** No class components.
- **Custom hooks isolate cross-cutting concerns** — `useComponentProps`, `useInstallation`, `useStars`, `useTransition`, `useActiveRoute`, `useScrollToTop`, `useForceRerender`. Context-backed hooks throw a clear error if used outside their provider (e.g. *"useActiveRoute must be used within an ActiveRouteProvider"*).
- **Lazy loading + code splitting** — demos and tools are loaded with `React.lazy` + `Suspense`, keeping the initial bundle small despite 130+ components.
- **URL as state** — preview prop state lives in the URL (nuqs), making previews shareable and back/forward-navigable.
- **Defensive `localStorage` access** — `favorites.js` and `useStars` wrap reads/writes in `try/catch` and validate shapes, tolerating disabled storage and corrupt values.
- **Zero-warning lint policy** — `--max-warnings 0` makes lint failures block.

### 13.2 Pattern: prop-driven, self-contained components

Each component is a single file (plus an optional `.css`) with a clear destructured prop signature and sensible defaults — e.g. `SplitText` exposes `delay`, `duration`, `ease`, `splitType`, `from`/`to`, `threshold`; `Aurora` exposes `colorStops`, `amplitude`, `blend`, `speed`. This consistency is what makes the registry/preview/codegen pipeline possible: the site can introspect defaults and generate accurate usage code.

### 13.3 Pattern: lifecycle-correct graphics

WebGL/canvas components consistently clean up on unmount — cancelling `requestAnimationFrame`, removing resize listeners, and releasing the GL context (e.g. `Aurora` calls `WEBGL_lose_context` on teardown; `ClickSpark` disconnects its `ResizeObserver`). This is essential given the "many components" use case and the WebGL context-limit risk.

### 13.4 Notable complexity hotspots

- **The four-tree duplication** is the dominant structural complexity — four copies of every component must be maintained in lockstep.
- **`ToolsPage`** carries significant inline UI logic (custom dropdown, tooltips, portals) that could be extracted.
- **Shader components** embed GLSL as template strings (e.g. `Aurora`), which is idiomatic for `ogl`/`three` but is opaque to JS tooling and linting.

---

## 14. Operations & Troubleshooting

Since React Bits is a static site, "operations" centers on the build and the registry's correctness.

### Issue: Registry entry missing after adding a component

**Cause:** The component wasn't added to `componentMetadata`, so `defineComponent()` never generated its items.

**Resolution:** Add the metadata entry in `src/constants/Information.js`, then `npm run registry:build`. Confirm `<Name>-JS-CSS`, `-JS-TW`, `-TS-CSS`, `-TS-TW` appear in `public/r/`.

### Issue: Variants are out of sync

**Cause:** A change was made to one tree (e.g. `src/content/`) but not the other three.

**Resolution:** Re-apply the change to `src/tailwind/`, `src/ts-default/`, and `src/ts-tailwind/`. There is no automated equivalence check — diff the four files manually.

### Issue: `jsrepo build` produces stale or unexpected output

**Cause:** Editing files under `public/r/` directly (they're generated), or a watcher not running during `dev`.

**Resolution:** Never edit `public/r/`. Use `npm run dev` (which runs `registry:dev`) or re-run `npm run registry:build`. Treat `public/r/` as build output.

### Issue: Lanyard (or other asset-bundling component) fails to install

**Cause:** Binary assets (`.glb`) mishandled by the generic installer (issue [#960](https://github.com/DavidHDev/react-bits/issues/960)).

**Resolution:** Lanyard is special-cased in `jsrepo.config.ts` with `dependencyResolution: 'manual'` and explicit file lists. Ensure consumers use `@latest` CLI; recommend manual install for asset-heavy components.

### Issue: Production deploy serves an old registry

**Cause:** Running `vite build` alone instead of the composite `build` script.

**Resolution:** Always run `npm run build`, which regenerates the registry before bundling.

### Issue: Deep links 404 on a non-Cloudflare host

**Cause:** Missing SPA fallback. `wrangler.jsonc` handles this on Cloudflare via `not_found_handling: single-page-application`.

**Resolution:** Configure the host to rewrite unknown routes to `/index.html`.

---

## 15. Potential Improvements

These are observations for maintainers, derived from the codebase structure:

- **Automate variant equivalence.** The "all four variants in sync" rule is manual. A CI check that diffs the logical structure (or runs each variant's demo and snapshot-tests output) would catch divergence — the most common class of bug for this architecture.
- **Generate variants from one source.** The four trees are largely mechanical transforms (JS↔TS, CSS↔Tailwind). A codegen step from a single canonical source could eliminate the duplication burden entirely.
- **Extract `ToolsPage` UI.** The custom dropdown/tooltip/portal logic is large and reusable; extracting it would slim a 780-line page.
- **Accessibility pass.** Several interactive components are pointer-first (e.g. `Carousel` keyboard nav, issue [#976](https://github.com/DavidHDev/react-bits/issues/976)). A systematic a11y audit + keyboard support would broaden adoption.
- **Dependency-version pinning guidance per component.** TS type breakage from upstream graphics libs (e.g. `three` `Clock`→`Timer`, issue [#975](https://github.com/DavidHDev/react-bits/issues/975)) suggests the registry should record tested dependency version ranges.
- **Device-aware perf fallbacks.** A shared helper to detect low-power devices and swap to static placeholders would operationalize the project's own performance advice.

---

## 16. Quick Reference

### 16.1 Scripts

```bash
npm run dev               # registry watcher + Vite dev server (concurrently)
npm run registry:build    # build registry → public/r/
npm run build             # registry + llms.txt + sitemap + vite build → dist/
npm run new:component <Type> <Name>   # scaffold all 4 variants
npm run lint              # eslint, zero warnings allowed
npm run format            # prettier
npx wrangler deploy       # deploy ./dist to Cloudflare
```

### 16.2 Key files

| File | Role |
|------|------|
| `jsrepo.config.ts` | Registry definition (consumes `componentMetadata`) |
| `src/constants/Information.js` | `componentMetadata` — the authoritative catalog + `VARIANTS` |
| `src/constants/Components.js` | slug → lazy demo import map |
| `src/constants/Categories.js` | sidebar grouping + `NEW` list |
| `src/utils/cli.js` | builds shadcn/jsrepo/manual install commands |
| `src/hooks/useComponentProps.js` | URL-synced prop state (nuqs) |
| `vite.config.js` | aliases, Tailwind, PostCSS, asset handling |
| `wrangler.jsonc` | Cloudflare static + SPA fallback |
| `scripts/generateComponent.js` | new-component scaffolder |

### 16.3 Variant matrix

| Variant | Tree | Files | shadcn code | jsrepo code |
|---------|------|-------|-------------|-------------|
| JS-CSS | `src/content` | `.jsx` + `.css` | `JS-CSS` | `default` |
| JS-TW | `src/tailwind` | `.jsx` | `JS-TW` | `tailwind` |
| TS-CSS | `src/ts-default` | `.tsx` + `.css` | `TS-CSS` | `ts/default` |
| TS-TW | `src/ts-tailwind` | `.tsx` | `TS-TW` | `ts/tailwind` |

### 16.4 Facts at a glance

| Item | Value |
|------|-------|
| Components | 130+ across 4 categories |
| Categories | Text Animations, Animations, Components, Backgrounds |
| Variants per component | 4 |
| Registry output | `public/r/` (~521 generated files) |
| Registry name | `@react-bits` |
| Hosting | Cloudflare (`./dist`, SPA fallback) |
| Secrets / backend | None |
| License | MIT + Commons Clause |
| Ports | Vue ([vue-bits.dev](https://vue-bits.dev/)), Svelte ([sveltebits.xyz](https://sveltebits.xyz/)) |

---

_Generated June 2026 from DavidHDev/react-bits at 9d0137e. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
