Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

React Bits Admin & Architecture Guide

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.

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
  2. System Architecture
  3. Technology Stack
  4. Repository Structure
  5. The Four-Variant Component System
  6. The Registry: How CLI Installs Work
  7. Build & Development Workflow
  8. The Documentation Web App
  9. Configuration Reference
  10. Deployment
  11. Adding & Maintaining Components
  12. Security Analysis
  13. Code Quality & Patterns
  14. Operations & Troubleshooting
  15. Potential Improvements
  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 and jsrepo CLIs consume to copy components into end-user projects.
  2. A documentation single-page app — a Vite + React 19 site (deployed at 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)

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:

// 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

// 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 RegistryItems, 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).

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

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

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)

{
  "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

# 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

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).


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).
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).

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.

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). 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) 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

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), Svelte (sveltebits.xyz)