# create-reactivite

[![CI](https://github.com/jsznpm/create-reactivite/actions/workflows/ci.yml/badge.svg)](https://github.com/jsznpm/create-reactivite/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/create-reactivite.svg)](https://www.npmjs.com/package/create-reactivite)
[![npm downloads](https://img.shields.io/npm/dm/create-reactivite.svg)](https://www.npmjs.com/package/create-reactivite)
[![node](https://img.shields.io/badge/node-%5E20.19%20%7C%7C%20%3E%3D22.12-brightgreen.svg)](https://nodejs.org)
[![license](https://img.shields.io/npm/l/create-reactivite.svg)](./LICENSE)

A modern frontend boilerplate generator. On run it asks which template you want, then scaffolds a production-ready app with TypeScript, Tailwind CSS v4 and shadcn/ui pre-wired.

## 🚀 Templates

When you run the CLI you pick one of four templates:

| Template | Stack |
| --- | --- |
| **React + Vite** | React 19, Vite 8 (Rolldown), Tailwind v4, shadcn/ui, React Router v8, Recharts |
| **Next.js 16** | Next.js 16 (App Router), React 19, Tailwind v4, shadcn/ui, i18n, TanStack Query, axios + orval, Zustand, react-hook-form + zod, husky, Vitest + MSW |
| **Rspack** | React 19 + TypeScript, Rspack bundler (SWC), Tailwind v4, shadcn/ui, React Router v7, Matrix/terminal theme |
| **UI Kit** | A publishable component library — shadcn/Radix, two runtime deps, tsup (ESM+CJS+types), per-component subpath exports, prebuilt CSS, Storybook, npm/Nexus release scripts |

```
$ npx create-reactivite my-app

? Project name: my-app
? Pick a template: ›
❯ React + Vite (Tailwind v4, shadcn/ui, React Router)
  Next.js 16 (App Router, i18n, TanStack Query, orval, Zustand, husky)
  Rspack (Tailwind v4, shadcn/ui, React Router, Matrix theme)
  UI Kit library (shadcn/Radix, tsup, Storybook, npm/Nexus publish)
```

## 📦 Installation

**Requires Node `^20.19.0 || >=22.12.0`** — that is Vite 8's and Rspack 2's floor, and every template builds on one of them. The CLI checks your version up front and stops with a clear message rather than letting the scaffold fail later during a build.

### Using npx (Recommended)

```bash
npx create-reactivite my-app
cd my-app
pnpm dev
```

### Using npm

```bash
npm create reactivite my-app
cd my-app
npm run dev
```

### Install in current directory

```bash
npx create-reactivite .
```

Dependencies install automatically (`pnpm`, falling back to `npm`). Pass `--no-install` to skip that step.

## 🛠️ CLI usage

The CLI runs interactively (prompts) or non-interactively (flags) — flags skip the matching prompt, so it works in scripts and CI.

```
npx create-reactivite [name] [options]
```

| Argument / Flag | Alias | Description |
| --- | --- | --- |
| `name` | | Project folder. Use `.` to scaffold into the current directory. Omit to be prompted. Must be lowercase letters, digits, `-` `.` `_` `~`. |
| `--template <name>` | `-t` | `template` · `template2` · `template3` · `template4` (alias `uikit`). Omit to be prompted. |
| `--storybook` / `--no-storybook` | | Keep or strip Storybook. Applies to `template` only — the other three are unaffected. Omit to be prompted. |
| `--no-install` | | Scaffold and stop, without installing dependencies. |
| `--help` | `-h` | Print usage and exit. |
| `--version` | `-v` | Print version and exit. |

```bash
# fully non-interactive (no prompts)
npx create-reactivite my-app --template template2
npx create-reactivite my-app -t template3
npx create-reactivite my-ui -t uikit

# `template` also asks about Storybook — pass the flag to stay non-interactive
npx create-reactivite my-app -t template --no-storybook

npx create-reactivite --help
npx create-reactivite --version
```

After copying the template the CLI sets `name` in the new `package.json`, removes any bundled lockfile (fresh resolve), runs `git init`, then installs dependencies. Scaffolding into `.` takes the name from the current folder.

---

## ⚛️ Template 1 — React + Vite

### Features

- **⚡ Vite 8** — Lightning-fast build tool and dev server (Rolldown bundler)
- **⚛️ React 19** — Latest React with modern features
- **📘 TypeScript 6** — Full TypeScript with strict configuration
- **🎨 Tailwind CSS v4** — Config-less, CSS-variable driven theme
- **🧩 shadcn/ui** — Beautiful, accessible UI components (new-york)
- **🧭 React Router v8** — Client-side routing with `createBrowserRouter`
- **📊 Recharts** — Composable charts for the admin dashboard
- **🌙 Dark Mode** — Built-in theme switching
- **🔔 Toasts** — Sonner notifications
- **🎯 ESLint** — Modern flat config

### Scripts

- `pnpm dev` — dev server (port 5173)
- `pnpm build` — `tsc -b && vite build`
- `pnpm preview` — serve the production build
- `pnpm lint` — ESLint

### Structure

```
my-app/
├── public/
├── src/
│   ├── components/
│   │   ├── ui/                    # shadcn/ui components
│   │   ├── home-page-components/
│   │   └── admin-page-components/
│   ├── lib/utils.ts
│   ├── pages/
│   │   ├── Homepage/
│   │   └── Dashboard/
│   ├── App.tsx                   # createBrowserRouter route shell
│   ├── main.tsx
│   └── global.css
├── components.json         # shadcn config (css → src/global.css)
├── vite.config.ts
└── eslint.config.js
```

### Routing

Routes live in `App.tsx` via `createBrowserRouter` from **react-router** v8 (not `react-router-dom`):

```typescript
import { createBrowserRouter } from "react-router"

const router = createBrowserRouter([
  { path: "/", element: <Homepage /> },
  { path: "/dashboard", element: <Dashboard /> },
])
```

---

## ▲ Template 2 — Next.js 16

A locale-scoped App Router boilerplate with a full data layer and tooling.

### Features

- **▲ Next.js 16** — App Router, `output: "standalone"`
- **🌍 i18n** — `app/[locale]` routing, lightweight `TranslationProvider` + `locales/*.json`
- **🔁 TanStack Query** — `QueryClientProvider` + Devtools
- **🔌 axios + orval** — typed API hooks generated from your OpenAPI schema
- **🐻 Zustand** — state stores (persisted `user-store`)
- **📝 react-hook-form + zod** — typed forms
- **🧪 Vitest + MSW** — unit tests with mocked network
- **🐶 husky** — pre-commit: lint + format + tests
- **🎨 Tailwind v4 + shadcn/ui**

### Scripts

- `pnpm dev` — dev server (port 3000, redirects `/` → `/az`)
- `pnpm build` — `next build`
- `pnpm test` / `pnpm test:run` — Vitest
- `pnpm generate:api` — orval codegen into `services/generated/`
- `pnpm lint` / `pnpm format`

### Structure

```
my-app/
├── app/
│   ├── layout.tsx              # root passthrough
│   ├── page.tsx                # redirects to /{DEFAULT_LOCALE}
│   ├── globals.css
│   ├── api/clear-session/
│   └── [locale]/
│       ├── layout.tsx          # html/body shell + providers
│       ├── locales.ts          # server-only dictionary loader
│       ├── page.tsx            # Home
│       ├── (public)/login/
│       └── (private)/dashboard/
├── components/ui/              # shadcn/ui
├── config/                     # env + constants (LOCALES)
├── contexts/                   # translation-context
├── hoc/                        # QueryProvider
├── lib/                        # utils, paramsSerializer
├── services/
│   ├── httpClient/             # axios + orval mutator
│   └── generated/              # orval output
├── store/                      # zustand
├── locales/                    # az.json, en.json
├── testing/msw/
└── orval.config.ts
```

### API codegen (orval)

1. Point `orval.config.ts` `input.target` at your OpenAPI schema (or set `OPENAPI_TARGET`).
2. `pnpm generate:api` → writes react-query hooks + models to `services/generated/`.

> The `@/` path alias maps to the **project root** in this template (not `src/`).

---

## 🦀 Template 3 — Rspack

A **React 19 + TypeScript** app on [Rspack](https://rspack.dev/) (Rust-based bundler, built-in SWC), themed as a Matrix/terminal hacker UI (canvas glyph rain, scanlines, neon glow, Orbitron / Share Tech Mono fonts).

### Features

- **🦀 Rspack** — fast Rust bundler with built-in SWC
- **⚛️ React 19 + TypeScript 6**
- **🎨 Tailwind v4** — via PostCSS (`@tailwindcss/postcss` + `postcss-loader`), not the Vite plugin
- **🧩 shadcn/ui** — full new-york component set vendored in `src/components/ui/`
- **🧭 React Router v7** — `react-router-dom` component API (`BrowserRouter`/`Routes`/`Route`)
- **🌧️ Matrix theme** — `MatrixRain` canvas, scanlines, `text-glow`; forced dark mode

### Scripts

- `pnpm dev` — dev server (port 5174)
- `pnpm build` — production build → `dist/`
- `pnpm preview` — serve the production build

### Structure

```
my-app/
├── index.html              # <html class="dark">, Google Fonts
├── rspack.config.mjs       # entry, swc loader, postcss-loader, @/ alias
├── postcss.config.mjs      # @tailwindcss/postcss
├── components.json         # shadcn config (css → src/index.css)
├── tsconfig.json           # @/ → src/
└── src/
    ├── main.tsx
    ├── App.tsx             # <Routes> route shell
    ├── index.css           # tailwind + oklch theme + effects
    ├── lib/utils.ts
    ├── hooks/use-mobile.ts
    ├── pages/              # home.tsx, about.tsx, contact.tsx
    └── components/
        ├── ui/             # shadcn/ui
        ├── layout.tsx      # nav + Outlet + MatrixRain + AuthorCredit
        ├── matrix-rain.tsx
        └── author-credit.tsx
```

### Routing

Routes live in `App.tsx` via the **`react-router-dom`** v7 component API (not the `createBrowserRouter` data router used by Template 1):

```tsx
import { BrowserRouter, Route, Routes } from "react-router-dom"

<BrowserRouter>
  <Routes>
    <Route element={<Layout />}>
      <Route index element={<Home />} />
      <Route path="about" element={<About />} />
      <Route path="contact" element={<Contact />} />
    </Route>
  </Routes>
</BrowserRouter>
```

---

## 🧰 Template 4 — UI Kit

Unlike the other three, this template is **not an app** — it is a component library you rebrand and publish. Scaffold it, restyle the design tokens, then ship it to npm or a private Nexus registry; your teammates install it and import components one at a time.

Installing the published kit adds **two packages** to your teammates' lock file: `radix-ui` and `tailwind-merge`. No icon library, no date library, no command palette, no toast package — every component is code inside the template that you own and can change.

```bash
npx create-reactivite my-ui -t uikit
cd my-ui
pnpm dev      # Storybook @ http://localhost:6006
```

### Features

- **📦 Per-component subpath exports** — `import { Button } from '@team/ui/button'`. Only what you import ends up in the consumer's bundle. The `exports` map is generated from the folder layout, never hand-written.
- **⚡ tsup** — ESM + CJS + `.d.ts`, React kept external, `'use client'` directives preserved so the kit works inside Next.js Server Components.
- **🎨 Prebuilt CSS** — consumers do **not** need Tailwind. `import '@team/ui/styles.css'` and you're done. Teams that do run Tailwind v4 can import `@team/ui/theme.css` for the tokens alone.
- **🎯 Token-driven theming** — every colour, radius, space and font lives in `src/styles/tokens.css`. Change that one file and the whole kit rebrands; components never hardcode a value.
- **🧩 39 components** — Radix carries the overlay/form primitives; the eight data-heavy widgets it doesn't cover are written locally: `data-table` (pinned columns, sticky header, expandable rows), `virtual-list`, `tree` (tri-state checkboxes), `tree-select`, `date-picker` (+ range, + its own date maths), `range-slider`, `upload` (abortable), `input-number`.
- **🪶 Two runtime dependencies** — `radix-ui` and `tailwind-merge`, nothing else. The icon set, the variant builder (`cva`), the class composer (`cx`), the command palette, the toaster, the drawer and the calendar all live under `src/`. `<pkg>/icons` ships the 19 icons the components draw, on one shared 24×24 chassis (geometry from Lucide, ISC — see `NOTICE`), so a consumer's icon library is a choice rather than a transitive install.
- **📖 Storybook 10** — the dev environment, with a11y checks and a live theme switcher.
- **♿ Accessibility is tested, not assumed** — jest-axe runs over every component in a realistic composition, and Storybook's a11y addon fails a story on a violation in a real browser.
- **🔒 The rules are enforced** — `pnpm lint` rejects a hardcoded colour or a raw primitive anywhere under `src/`, so a Figma re-sync can never be silently bypassed, and it blocks an import of any package the kit replaced (`clsx`, `class-variance-authority`, `lucide-react`, `cmdk`, `sonner`, `vaul`, `date-fns`, `rc-*`) so the dependency count stays at two. `pnpm size` holds each subpath to a bundle budget.
- **🚀 Publish scripts** — `pnpm release` walks you through version bump → build → verify → dry-run → registry choice (public npm or Nexus) → publish → tag. Nexus config ships as `.npmrc`. The kit ships a `LICENSE` template with your copyright left blank rather than ours — `pnpm release` blocks until you fill it in, because npm packs that file into every install.
- **🤖 Claude skills included** — the generated project carries `.claude/skills/`: `figma-sync` (pull Figma Variables through the Figma MCP straight into `tokens.css`), `ui-kit-component` (scaffold a new component), `release-kit` (guided publish).

### Publishing

```bash
# 1. set your scope in package.json  →  "name": "@team/ui"
# 2. fill in LICENSE                 →  replace __COPYRIGHT_HOLDER__ with your name
pnpm lint           # token + dependency rules, then ESLint
pnpm test           # component tests + jest-axe smoke suite
pnpm build          # dist/ — ESM + CJS + types + styles.css
pnpm verify         # export map current + publint + are-the-types-wrong
pnpm size           # per-subpath bundle budgets
pnpm release        # guided publish (npm public or Nexus)
```

### Consuming

```tsx
import '@team/ui/styles.css'
import { Button } from '@team/ui/button'
import { DataTable } from '@team/ui/data-table'
```

### Coming from a kit scaffolded with create-reactivite 3.x

Skip this on a fresh scaffold. **4.0.0 rewrote this template**: the runtime dependency count went from 17 to 2, and the widgets that used to wrap `rc-*`, `cmdk`, `sonner`, `vaul` and `date-fns` are now local code with their own props. `RangeSlider`, `CommandItem`, `Toaster`, `Drawer`, `DatePicker`, `DateRangePicker`, `TreeSelect` and `Tree` all changed shape.

The prop-by-prop migration, with before/after diffs, ships inside the template — **§9 of the generated project's own `README.md`**.

---

## 👤 Author

Templates 1–3 render a small credit linking to the author (the UI kit template does not — it ships under *your* name). Built by **Javid Salimov** —
[GitHub](https://github.com/javidselimov) ·
[LinkedIn](https://www.linkedin.com/in/javidsalim/) ·
[npm](https://www.npmjs.com/~ubuligan).

---

## 🎨 Adding shadcn/ui Components

Templates 1–3 use shadcn/ui (new-york, lucide icons) directly:

```bash
npx shadcn@latest add button
npx shadcn@latest add form
```

Template 4 is shadcn-derived but not shadcn-managed: a pasted component has to move into its own folder, be retokenised, and swap `lucide-react`/`clsx`/`cva` for the kit's local equivalents before `pnpm lint` passes. The bundled `/ui-kit-component` skill does that conversion for you.

## 🔄 Maintaining template versions

This repo ships a Claude Code skill that bumps every template's dependencies to their latest published versions in one shot — useful when keeping the scaffolds current.

```
/update-template-deps
```

It runs `npm-check-updates` inside `template/`, `template2/`, `template3/` and `template4/`, rewrites each `package.json` to the latest, and reports what changed — flagging **major** bumps that need a build check. The generator's own root `package.json` is left untouched.

You can also run the helper directly:

```bash
# all templates, latest (includes majors)
node .claude/skills/update-template-deps/update-deps.mjs

# safe — no major bumps
node .claude/skills/update-template-deps/update-deps.mjs --target minor

# a single template
node .claude/skills/update-template-deps/update-deps.mjs --template template2
```

After a major bump, verify the affected template still builds before publishing:

```bash
cd template2 && pnpm install && pnpm build
```

Two packages are deliberately held back and will never show up in the update list — each template dir carries a `.ncurc.json` that rejects them:

| Package | Where | Why |
| --- | --- | --- |
| `typescript` | all four | Pinned to 6. TS 7 (the native port) breaks Template 1's install, Template 2's build and Template 4's `.d.ts` step. |
| `lucide-react` | Template 4 | Exact-pinned. The kit draws its own icons and tests them against Lucide's geometry, so a floating range would fail a fresh scaffold's test suite. |

## 🤝 Contributing

Contributions welcome — open a PR.

Every push runs CI (`.github/workflows/ci.yml`): it syntax-checks the generator, scaffolds every template with `--no-install` and asserts the results, checks the `npm pack` file list for leaked build artifacts, then installs and builds each template. The UI Kit template is gated twice — under npm **and** pnpm, because a couple of its failure modes only reproduce in pnpm's isolated dependency tree.

## 📄 License

[MIT](./LICENSE) © Javid Salimov

The templates are scaffolding output — what you build from them is yours, with no attribution requirement. Template 4 additionally ships a `NOTICE` file crediting Lucide (ISC) for the icon geometry its local icon set is drawn from; keep that file if you publish a kit from it.

## 🔗 Links

- [React](https://react.dev/) · [Next.js](https://nextjs.org/) · [Vite](https://vite.dev/) · [Rspack](https://rspack.dev/)
- [Tailwind CSS](https://tailwindcss.com/) · [shadcn/ui](https://ui.shadcn.com/)
- [React Router](https://reactrouter.com/) · [TanStack Query](https://tanstack.com/query) · [orval](https://orval.dev/)
- [Zustand](https://zustand.docs.pmnd.rs/) · [Recharts](https://recharts.org/) · [TypeScript](https://www.typescriptlang.org/)

---

**Happy coding! 🎉**
