npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@frontfamily/cli

v0.18.1

Published

Eject production-ready UI pattern components across React, Vue, and Angular frameworks

Readme


$ npx @frontfamily/cli eject auth-login data-table -f react-mui

┌   FrontFamily Eject
│
◆  components/MuiLogin.tsx
│
◆  components/MuiLineage.tsx
│
◆  components/frontfamily-shared/…   (shared types & helpers the templates import)
│
└  2 ejected

$ npx @frontfamily/cli list -f react-eui

react-eui — 22 patterns:

  data-table               → EuiLineage.tsx
  auth-login               → EuiLogin.tsx
  kanban-board             → EuiKanbanBoard.tsx
  chat-ui                  → EuiChatUI.tsx
  ... 18 more

The problem

You're starting a new feature. You need a data table in MUI, an auth form in Chakra UI, a kanban board in Angular Material. You'll spend 2-4 hours writing boilerplate — imports, props, state management, responsive layout, dark mode, loading states, error handling — before you write a single line of business logic.

The fix

npx @frontfamily/cli eject kanban-board -f react-mui
# → ./components/KanbanBoardPattern.tsx (ready to use)
# → ./components/frontfamily-shared/    (shared types & helpers it imports)

npx @frontfamily/cli eject auth-login data-table -f react-chakra
# → ./components/ChakraLogin.tsx
# → ./components/ChakraLineage.tsx

198 templates across 9 frameworks. Each one is a typed, production-ready component with theme support, responsive layout, and loading/error states built in. No runtime dependency — the files are yours.

Honest fine print: react-eui, vue-quasar, and angular-material implement all 22 patterns natively. Of the other React kits, react-mui, react-chakra, react-antd, and react-mantine each build 10 patterns with their own library's components (data-table, modal-dialog, pricing-table, settings-panel, nav-bar, tabs, comments, and the 3 auth flows) and ship the same framework-agnostic React implementation for the remaining 12; react-bootstrap and react-tailwind build 6 natively (data-table, tabs, comments, and the 3 auth flows) and share the other 16.

All templates are bundled inside the package. No network requests, no API keys, no accounts. Works offline, works in CI.

Install

# Use directly (no install needed)
npx @frontfamily/cli eject

# Or install globally
npm i -g @frontfamily/cli
frontfamily eject

Usage

Interactive mode

$ npx @frontfamily/cli eject

┌  FrontFamily Eject
│
◆  Select the UI Pattern(s) you want to eject:   (space to select, enter to confirm)
│  ◻ Data Table
│  ◼ Login Form         ← pick one or more
│  ◻ Card Feed
│  ...
│
◆  Select the framework:
│  ○ React + Material UI    ← you pick
│  ○ React + Chakra UI
│  ○ React + Ant Design
│  ...
│
◇  Ejected successfully!
│
└  ✨ Your component is ready at ./components/MuiLogin.tsx

Direct mode

# Single pattern
npx @frontfamily/cli eject auth-login -f react-mui
npx @frontfamily/cli eject data-table -f react-chakra
npx @frontfamily/cli eject nav-bar -f react-antd

# Multiple patterns at once
npx @frontfamily/cli eject auth-login data-table nav-bar -f react-mui

# Custom output directory
npx @frontfamily/cli eject auth-login -f react-mui -o src/components/

# Print the template source to stdout without writing files
npx @frontfamily/cli eject kanban-board -f react-mui --preview

# See what would be written, without touching disk
npx @frontfamily/cli eject auth-login -f react-mui --dry-run

# Overwrite existing files without prompting
npx @frontfamily/cli eject auth-login -f react-mui --overwrite

Exit codes & CI. eject exits 0 when everything you asked for was written, or when you answered "no" to an overwrite prompt. It exits 1 — and writes nothing — for an unknown -f framework or pattern id (the valid ids are listed). Without a terminal (CI, pipes, agents: stdin is not a TTY, or CI is set) it never prompts: an existing file is kept, eject says to re-run with --overwrite, and the exit code is 1:

$ npx @frontfamily/cli eject data-table -f react-mui < /dev/null

┌   FrontFamily Eject
│
▲  components/MuiLineage.tsx already exists — not overwritten (no terminal to confirm). Re-run with --overwrite to replace it.
│
└  Nothing ejected.

$ echo $?
1

In CI, always pass the pattern(s) and -f (the interactive pickers need a terminal too), plus --overwrite when re-ejecting.

Compare component mappings

# Overview — all components between two frameworks
$ npx @frontfamily/cli diff react-mui react-chakra

  React + Material UI → React + Chakra UI v2  (42 components)

  Button           → Button      7 props 4 renamed
  TextField        → Input       8 props 3 renamed
  Card             → Card        2 props 1 dropped ! 1 behavioral note
  Typography       → Text        3 props 2 renamed
  Dialog           → Modal       2 props 1 renamed ! 2 behavioral notes
  ...

  Tip: frontfamily diff react-mui react-chakra Button for detailed prop mapping

# Detail — specific component prop mapping
$ npx @frontfamily/cli diff react-mui react-chakra Button

  Button (React + Material UI → React + Chakra UI v2)

  Component:  Button  →  Button
  Import:     @chakra-ui/react

  Props:
    · transformed variant    (unchanged) (value transformed)
    → transformed color      →  colorScheme (value transformed)
    → mapped      disabled   →  isDisabled
    · mapped      onClick    (unchanged)
    · mapped      size       (unchanged)
    → mapped      startIcon  →  leftIcon
    → mapped      endIcon    →  rightIcon
    · passthrough any other prop — copied unchanged, not verified against the target

# Conversion report for a real file — same statuses and score as the web converter
$ npx @frontfamily/cli diff react-mui react-chakra --file src/Card.tsx

  Confidence: 27% mapped
  Counts:     1 mapped · 0 transformed · 1 passthrough · 1 dropped · 1 dynamic · 2 converted · 1 skipped

  L4    Card → Card
        dropped     elevation  no equivalent in target — removed
        passthrough raised     not in mapping table — copied unchanged
  L5    Button → Button 1 prop ok
        dynamic     variant    expression value not transformed — verify manually

  Not converted:
  L6    <Foo> not in the mapping table

# JSON output for tooling
npx @frontfamily/cli diff react-mui react-chakra --json
npx @frontfamily/cli diff react-mui react-chakra Button --json
npx @frontfamily/cli diff react-mui react-chakra --file src/Card.tsx --json

# Chakra UI v2 → v3 upgrade (react-chakra-v3 is a target-only id)
npx @frontfamily/cli diff react-chakra react-chakra-v3 Modal

1,668 component mappings across 51 framework pairs. react-chakra is the Chakra UI v2 API; react-chakra-v3 (Chakra UI v3) is a conversion target reachable from every React source.

Check component availability

compat answers "what is this component called in each of the 9 UI kits?" from a curated component concept index — 57 UI concepts × 9 frameworks with the real component names, import lines, and gotcha notes, verified against the installed kits. Any vendor spelling resolves to the same concept: compat Modal, compat Dialog, compat q-dialog, and compat MatDialog all give the same answer. Angular Material gets real answers too (it has no conversion paths, but the concept index covers it).

$ npx @frontfamily/cli compat Dialog

┌   FrontFamily Compat

  Modal dialog (matched "Dialog")
  A blocking dialog layered over the page.

  ✓ React + Material UI  Dialog + DialogTitle + DialogContent + DialogActions
                         import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
                         MUI's Modal is the unstyled primitive underneath Dialog.
  ✓ React + Chakra UI    Modal + ModalOverlay + ModalContent + ModalBody
                         import { Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
                         AlertDialog for confirmations.
  ✓ React + Ant Design   Modal
                         import { Modal } from 'antd';
                         Modal.confirm() / App.useApp() for imperative dialogs.
  ✓ React + Mantine      Modal
                         import { Modal } from '@mantine/core';
  ✓ React + Bootstrap    Modal
                         import { Modal } from 'react-bootstrap';
  ✓ React + Elastic EUI  EuiModal + EuiConfirmModal
                         import { EuiModal, EuiConfirmModal } from '@elastic/eui';
                         EuiConfirmModal is the pre-built confirm/cancel variant.
  ✓ Vue 3 + Quasar       QDialog
                         import { QDialog } from 'quasar';
                         The Dialog plugin ($q.dialog()) opens one imperatively.
  ✓ Angular + Material   MatDialog + MatDialogTitle + MatDialogContent + MatDialogActions
                         import { MatDialogModule } from '@angular/material/dialog';
                         Opened imperatively: inject(MatDialog).open(MyComponent).
  ~ React + TailwindCSS  <dialog>
                         Tailwind CSS ships no components — style <dialog> with utility classes (fixed inset-0, backdrop:*). Headless UI's Dialog (@headlessui/react, external) adds the accessible behavior.

  8/9 frameworks ship a modal dialog component. (~ 1 via plain HTML + styling)
  Tip: frontfamily diff react-mui react-chakra Dialog shows the prop mapping
  Details: https://www.frontfamily.com/components/modal
│
└  Modal dialog — 8/9 frameworks

✓ = the kit ships a component, ~ = plain HTML plus that kit's styling (Tailwind always, plus real gaps like Bootstrap's date input), ✗ = no equivalent, with the closest workaround in the note. Separate packages are flagged — for a date picker, MUI answers DatePicker from @mui/x-date-pickers (separate package), Mantine from @mantine/dates, and Chakra v2 is an honest ✗ No component ("community packages (e.g. chakra-dayzed-datepicker) or <Input type="date">"):

$ npx @frontfamily/cli compat DatePicker

  Date picker
  Pick a calendar date from a popup or inline calendar.

  ✓ React + Material UI  DatePicker
                         import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; (separate package)
                         Separate package @mui/x-date-pickers (MIT) — also needs LocalizationProvider and a date adapter (dayjs, date-fns…). DateRangePicker is Pro.
  ✓ React + Ant Design   DatePicker
  ✓ React + Mantine      DatePickerInput + DatePicker
  ✓ React + Elastic EUI  EuiDatePicker + EuiDatePickerRange
  ✓ Vue 3 + Quasar       QDate
  ✓ Angular + Material   MatDatepicker + MatDatepickerInput + MatDatepickerToggle
  ~ React + Bootstrap    Form.Control type="date"
  ~ React + TailwindCSS  <input type="date">
  ✗ React + Chakra UI    No component
                         Chakra v2 has no DatePicker — community packages (e.g. chakra-dayzed-datepicker) or <Input type="date">.

  6/9 frameworks ship a date picker component. (~ 2 via plain HTML + styling)

Unknown names exit 1 with suggestions:

$ npx @frontfamily/cli compat Datepickr

■  Unknown component "Datepickr".
●  Did you mean: date-picker, MatTimepicker, file-picker?
●  Browse all 57 components: https://www.frontfamily.com/components

$ echo $?
1
# Any component, any vendor alias
npx @frontfamily/cli compat Button       # 8/9 — Tailwind is ~ (a styled native <button>)
npx @frontfamily/cli compat MatTabGroup  # resolves to the tabs concept

# JSON output (no banner, pipes to jq): concept, aliases, available/html/missing
# rows with components, import lines and notes, and the coverage ratio
npx @frontfamily/cli compat Dialog --json

The same index powers the component pages: https://www.frontfamily.com/components

Check project readiness

doctor reads your package.json (dependencies + devDependencies) and tells you, per framework, whether an ejected template would have everything it needs. Fully offline — it never touches the network, installs nothing, and writes nothing. The "known-good" ranges are captured at build time from the exact workspace manifests the templates are developed against.

$ npx @frontfamily/cli doctor

┌   FrontFamily Doctor

  Checking /Users/you/my-app/package.json

  ✓ React + Material UI  READY  (react-mui)
  ◐ React + Chakra UI    PARTIAL  (react-chakra)
      missing @chakra-ui/react (known-good: ^2.8.2)
      missing framer-motion (known-good: ^11.3.31)
  ◐ React + Ant Design   PARTIAL  (react-antd)
      missing antd (known-good: ^5.13.0)
      missing @ant-design/icons (known-good: ^5.6.1)
  ◐ Vue 3 + Quasar       PARTIAL  (vue-quasar)
      missing vue (known-good: ^3.5.0)
      missing quasar (known-good: ^2.28.0)
  ...

  1/9 frameworks ready to eject into this project.
  Install what a framework is missing, e.g.: npm i @chakra-ui/react framer-motion

│
└  Offline check — nothing was installed or written.

# Scope to one framework
$ npx @frontfamily/cli doctor -f react-mui

  ✓ React + Material UI  READY  (react-mui)

  1/1 framework ready to eject into this project.

# Check a different directory
npx @frontfamily/cli doctor --dir ./my-app

# JSON output for tooling (no banner, pipes to jq)
npx @frontfamily/cli doctor -f react-chakra --json
{
  "react-chakra": {
    "ready": false,
    "missing": [
      { "pkg": "@chakra-ui/react", "wantedRange": "^2.8.2" },
      { "pkg": "framer-motion", "wantedRange": "^11.3.31" }
    ]
  }
}

A dependency that is installed but outside the known-good range still counts as present — readiness is presence-based — but gets flagged:

  ✓ React + Material UI  READY  (react-mui)
      ! react installed ^17.0.2 — known-good range is ^18.2.0

Install a framework's missing deps

add runs the same dependency diff as doctor for one framework, then installs only what's missing — pinned to the known-good ranges doctor advertises (e.g. @mui/material@^5.15.0). Your package manager is auto-detected: the packageManager field in package.json wins, then lockfiles (pnpm-lock.yaml → pnpm, yarn.lock → yarn, bun.lockb/bun.lock → bun, package-lock.json → npm), then pnpm-workspace.yaml → pnpm, with npm as the fallback. Inside a monorepo package, detection walks up from the package directory — the nearest directory with evidence wins — and stops at the workspace root (pnpm-workspace.yaml, or a package.json with "workspaces"), the repository root (.git), or your home directory. The install still runs in the package directory, so pnpm add / yarn add put the deps in that package's package.json, not the root's. It always shows the exact command and asks before running it (skip the prompt with --yes in CI).

$ npx @frontfamily/cli add react-chakra --dry-run

┌   FrontFamily Add

  Project: /Users/you/my-app/package.json
  ◐ React + Chakra UI (react-chakra) is missing 4 packages:
      missing @chakra-ui/react (known-good: ^2.8.2)
      missing @emotion/react (known-good: ^11.14.0)
      missing @emotion/styled (known-good: ^11.13.0)
      missing framer-motion (known-good: ^11.3.31)

  Detected package manager: pnpm (pnpm-lock.yaml)
  Will run: pnpm add @chakra-ui/react@^2.8.2 @emotion/react@^11.14.0 @emotion/styled@^11.13.0 framer-motion@^11.3.31

│
└  Dry run — nothing was installed or written.

# Actually install (prompts for confirmation first)
npx @frontfamily/cli add react-chakra

# No prompt — for CI
npx @frontfamily/cli add react-chakra --yes

# Point at another project
npx @frontfamily/cli add vue-quasar --dir ./my-app

# Machine-readable plan — implies --dry-run: never prompts, never installs
npx @frontfamily/cli add react-chakra --json
{
  "framework": "react-chakra",
  "pm": "pnpm",
  "pmDetectedFrom": { "reason": "pnpm-lock.yaml", "dir": "/Users/you/my-app" },
  "cwd": "/Users/you/my-app",
  "missing": [
    { "pkg": "@chakra-ui/react", "range": "^2.8.2" },
    { "pkg": "@emotion/react", "range": "^11.14.0" },
    { "pkg": "@emotion/styled", "range": "^11.13.0" },
    { "pkg": "framer-motion", "range": "^11.3.31" }
  ],
  "command": "pnpm add @chakra-ui/react@^2.8.2 @emotion/react@^11.14.0 @emotion/styled@^11.13.0 framer-motion@^11.3.31"
}

From a package inside a pnpm workspace (lockfile at the root), the detection line names where it found the evidence:

$ cd my-monorepo/packages/web && npx @frontfamily/cli add react-tailwind --dry-run
  ...
  Detected package manager: pnpm (pnpm-lock.yaml in /Users/you/my-monorepo)
  Will run: pnpm add react@^18.2.0 react-dom@^18.2.0 tailwindcss@^4

If the framework is already READY, add is a friendly no-op (everything's installed, exit 0). If the underlying install fails, its exit code is propagated.

Analyze migration feasibility

analyze scans a codebase for UI-kit imports (import/require of @mui/material, @chakra-ui/react, antd, @elastic/eui, @mantine/core, react-bootstrap, quasar), auto-detects the source framework, and reports — per migration target — how many of the components you import and render have a conversion mapping. Fully offline, read-only, no parser dependency.

$ npx @frontfamily/cli analyze ./my-app

┌   FrontFamily Analyze

  Scanned 3 source files in /Users/you/my-app

  ✓ React + Material UI (react-mui) — 14 components across 3 files

  Components rendered (14, by usage):
    Button       4 uses   3 files
    Chip         2 uses   1 file
    TextField    2 uses   1 file
    AppBar       1 use    1 file
    Card         1 use    1 file
    CardContent  1 use    1 file
    Checkbox     1 use    1 file
    Dialog       1 use    1 file
    DialogTitle  1 use    1 file
    IconButton   1 use    1 file
    Snackbar     1 use    1 file
    Toolbar      1 use    1 file
    Tooltip      1 use    1 file
    Typography   1 use    1 file

  Not counted — providers / theme setup: CssBaseline, ThemeProvider
  Not counted — imported but never rendered as a tag (types, helpers): ButtonProps

  Migration targets (React + Material UI →):

  → React + Chakra UI    64%   9/14 components mapped, 74% of usages  (react-chakra)
      unmapped: AppBar, CardContent, DialogTitle, Snackbar, Toolbar
      ! 3 components carry behavioral-difference notes — review them: frontfamily diff react-mui react-chakra <Component>
  → React + Ant Design   57%   8/14 components mapped, 68% of usages  (react-antd)
      unmapped: AppBar, CardContent, DialogTitle, IconButton, Snackbar, Toolbar
  → React + Elastic EUI  57%   8/14 components mapped, 68% of usages  (react-eui)
      unmapped: AppBar, CardContent, DialogTitle, IconButton, Snackbar, Toolbar
  → React + Mantine      57%   8/14 components mapped, 68% of usages  (react-mantine)
      unmapped: AppBar, CardContent, DialogTitle, IconButton, Snackbar, Toolbar
  → React + TailwindCSS  57%   8/14 components mapped, 68% of usages  (react-tailwind)
      unmapped: AppBar, CardContent, DialogTitle, IconButton, Snackbar, Toolbar
  → Vue 3 + Quasar       50%   7/14 components mapped, 63% of usages  (vue-quasar)
      unmapped: AppBar, CardContent, DialogTitle, IconButton, Snackbar, Toolbar, Typography

│
└  Import coverage only — mapped imports ≠ a finished conversion. Prop usage, styling, and app logic still need review.

# Scan the current directory
npx @frontfamily/cli analyze

# One target only
npx @frontfamily/cli analyze --to react-chakra

# Override the auto-detected source
npx @frontfamily/cli analyze --from react-mui

# JSON output for tooling (no banner, pipes to jq)
npx @frontfamily/cli analyze --json
{
  "detected": ["react-mui"],
  "from": "react-mui",
  "targets": {
    "react-chakra": {
      "total": 14,
      "mapped": 9,
      "coverage": 64,
      "unmapped": ["AppBar", "CardContent", "DialogTitle", "Snackbar", "Toolbar"],
      "withNotes": 3,
      "usageCoverage": 74
    }
  },
  "files": 3,
  "components": { "Button": { "files": 3, "uses": 4 }, "Chip": { "files": 1, "uses": 2 } },
  "excluded": { "nonVisual": ["CssBaseline", "ThemeProvider"], "unused": ["ButtonProps"] }
}

coverage is per distinct component; usageCoverage weights each component by how often it is rendered (uses).

Honest fine print: this measures import coverage — which of the components you import have a mapping — not conversion completeness. Detection is import-based only (node_modules, dist, build, .next, and out are skipped; scans cap at 5,000 files with a note), so Tailwind-only codebases aren't auto-detected — pass --from react-tailwind explicitly. What counts: named PascalCase imports, renamed imports (Modal as Dialog), deep imports (@mui/material/Typography) and namespace imports (<Mui.Button>) — but only when the component is actually rendered as a tag (<Button, <Menu.Item, or kebab-case <q-btn> in Vue templates) in the file that imports it. What doesn't: imports inside comments or string/template literals (a commented-out antd import no longer "detects" antd), import type and inline type specifiers, *Props/Theme types, names imported but never rendered, and providers / theme setup per kit (e.g. ThemeProvider, CssBaseline, ChakraProvider, MantineProvider, EuiProvider, antd ConfigProvider/App) — those are listed under excluded instead.

Convert files in your codebase

convert runs the same conversion engine as the web converter over files or whole directories. The default is a dry run: a unified diff per file plus counts (components converted, skipped, warnings, behavioral notes). Nothing is written unless you pass --write (in place) or --out <dir> (copies).

$ npx @frontfamily/cli convert src --to react-chakra

┌   FrontFamily Convert

  React + Material UI (react-mui) → React + Chakra UI (react-chakra) (auto-detected from imports in 1 file)

src/components/InviteDialog.tsx  3 converted · 1 skipped · 2 warnings · 2 notes
--- a/src/components/InviteDialog.tsx
+++ b/src/components/InviteDialog.tsx
@@ -1,13 +1,14 @@
 import { useState } from 'react';
-import { Button, Dialog, TextField, Snackbar } from '@mui/material';
+import { Button, Input, Modal } from '@chakra-ui/react';
+import { Snackbar } from '@mui/material';

 export function InviteDialog({ open, onClose }) {
   const [email, setEmail] = useState('');
   return (
-    <Dialog open={open} onClose={onClose}>
-      <TextField label="Email" value={email} onChange={(e) => setEmail(e.target.value)} />
-      <Button variant="contained" disabled={!email}>Send invite</Button>
+    <Modal isOpen={open} onClose={onClose}>
+      <Input placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} />
+      <Button variant="solid" isDisabled={!email}>Send invite</Button>
       <Snackbar open={false} message="Invite sent" />
-    </Dialog>
+    </Modal>
   );
 }
  ! Kept 1 unconverted import from @mui/material (Snackbar) — the file mixes kits until these are replaced by hand.
  ! 1 component not converted (no react-chakra mapping, or a tag the converter could not parse): Snackbar
  ⚑ Chakra's Modal onClose fires on overlay click and Esc by default; MUI's Dialog onClose fires on backdrop click and Esc too, but you often disable it — verify your close behavior.
  ⚑ Chakra Modal needs explicit <ModalOverlay>, <ModalContent>, <ModalHeader/Body/Footer> children; MUI Dialog uses DialogTitle/DialogContent/DialogActions.

  Summary: 1 file (1 changed, 0 unchanged) · 3 components converted · 1 skipped · 2 warnings · 2 behavioral notes

│
└  Dry run — nothing was written. Apply with --write (in place) or --out <dir>.
# One file, explicit source
npx @frontfamily/cli convert src/Form.tsx --from react-mui --to react-mantine

# Apply in place — lists the files and asks first
npx @frontfamily/cli convert src --to react-chakra --write

# Write converted copies to ./converted/, preserving relative paths
npx @frontfamily/cli convert src --to react-chakra --out converted

# CI gate: JSON per-file results, exit 2 if anything was skipped or warned about
npx @frontfamily/cli convert src --to react-antd --json --strict

# Skip paths (globs; also read from ./.frontfamilyignore, one pattern per line)
npx @frontfamily/cli convert src --to react-chakra --ignore '*.test.tsx' 'src/legacy'

How it behaves:

  • Inputs. Files or directories. Directories are scanned recursively for .tsx/.jsx/.ts/.js (not .d.ts), skipping node_modules, dist, build, out, and every dot-directory (.next, .git, …). In a directory, only files that import the source kit are converted; files you name explicitly are always converted.
  • Source detection. Without --from, the source is detected from imports (the same detection analyze uses — imports in comments, strings and import type don't count). If files import more than one kit, or none (e.g. Tailwind-only code — react-tailwind has no kit package), --from is required. Framework IDs are validated against the converter's paths, with the valid values in the error.
  • Imports are never silently dropped. The engine regenerates imports for the components it converted; anything else imported from those packages — hooks (useTheme), types, unmapped components (Snackbar above), aliased imports — is kept, with a warning that the file now mixes kits. 'use client' stays first, and the file keeps its trailing newline.
  • Git safety for --write. It lists the files and asks for confirmation (skip with --yes; without a TTY or with --json, --yes is required). It refuses to overwrite a file with uncommitted changes or one git doesn't track — so the conversion is always a clean, revertible diff — unless you pass --force. Outside a git repository it warns that the write can't be undone with git.
  • Vue targets. vue-quasar output is a draft: component tags become Quasar template markup, but the React function, hooks and JSX expressions stay — valid in neither framework. So --write is refused for it; preview it, or use --out to write <file>.vue-draft.txt drafts to port by hand into a .vue SFC. There are no conversion paths to Angular.
  • Exit codes. 0 success · 1 invalid arguments, unknown framework, no files, or a refused write · 2 with --strict when any file had skipped components or warnings.

--json prints one document: {from, to, fromDetected, mode, draft, files: [{file, status, componentsConverted, skipped, warnings, notes, diff, output}], summary}.

Fine print: this is regex-based tag-and-prop conversion, not an AST codemod — app logic, styling (sx, className), compound-component restructuring and types are yours to review. The behavioral notes (⚑) point at the runtime differences the prop mapping can't show.

List available templates

# Show all frameworks and patterns
npx @frontfamily/cli list

# Filter by framework
npx @frontfamily/cli list -f react-eui

# JSON output (for tooling, VS Code extensions, AI agents)
npx @frontfamily/cli list --json
npx @frontfamily/cli list -f react-mui --json

Patterns

| ID | Name | What you get | |---|---|---| | data-table | Data Table | Sortable, paginated table with status badges and a11y scores | | card-feed | Card Feed | Responsive grid of profile cards with avatars, badges, hover effects | | dashboard-stats | Dashboard Stats | 4 KPI cards with progress bars, trend indicators, department breakdown | | modal-dialog | Modal Dialog | Confirmation, form, and alert dialogs with overlay and keyboard dismiss | | nav-bar | Navigation Bar | Top nav with links, dropdown menu, search input, mobile hamburger drawer | | notification-center | Notifications | Toast stack with auto-dismiss, progress bars, and notification history | | settings-panel | Settings Panel | Toggles, sliders, radio groups, selects with save/reset actions | | file-upload | File Upload | Drag-and-drop zone, file list, progress bars, and validation | | date-picker | Date Picker | Calendar selector with range mode, time input, and locale support | | sidebar-layout | Sidebar Layout | Collapsible sidebar with nested nav, icons, and responsive drawer | | data-grid | Data Grid | Editable table with inline editing, column reorder, and virtualization | | command-palette | Command Palette | Cmd+K search overlay with fuzzy matching and keyboard navigation | | pricing-table | Pricing Table | Tier cards with feature comparison, toggle billing cycle, and CTAs | | stepper-wizard | Stepper Wizard | Multi-step form with validation, progress indicator, and back/next | | autocomplete | Autocomplete | Search input with async suggestions, multi-select, and custom rendering | | kanban-board | Kanban Board | Draggable cards across columns with add, edit, and status filtering | | chat-ui | Chat UI | Message bubbles, input with send, timestamps, and typing indicator | | tabs | Tabs | Tabbed interface with content panels, icons, badges, and lazy loading | | comments | Comments | Threaded comment list with reply, edit, like, avatars, and timestamps | | auth-login | Login Form | Email/password login with social buttons, remember me, forgot password | | auth-signup | Signup Form | Registration with password strength meter, terms checkbox, validation | | auth-password-reset | Password Reset | Forgot password flow with email input and success confirmation |

Frameworks

| Flag | ID | Framework | Output | |---|---|---|---| | ⚛️ | react-mui | Material UI (MUI) | .tsx | | ⚛️ | react-chakra | Chakra UI | .tsx | | ⚛️ | react-antd | Ant Design | .tsx | | ⚛️ | react-eui | Elastic EUI — all 22 patterns use native @elastic/eui | .tsx | | ⚛️ | react-mantine | Mantine | .tsx | | ⚛️ | react-bootstrap | Bootstrap | .tsx | | ⚛️ | react-tailwind | Tailwind + Headless UI | .tsx | | 💚 | vue-quasar | Quasar (Vue 3) — native Quasar components | .vue | | 🔺 | angular-material | Angular Material — native Material components | .ts |

22 patterns × 9 frameworks = 198 templates

What you get

Each ejected pattern is a single component file (plus a small frontfamily-shared/ support folder with the types and helpers it imports) with:

  • Framework-native imports (@mui/material, @chakra-ui/react, @elastic/eui, antd, quasar, @angular/material)
  • Proper TypeScript types
  • Theme support (dark/light)
  • Density support (compact/comfortable)
  • Loading and error states
  • Responsive layout

The file is yours — modify it however you want. No dependency on @frontfamily/cli at runtime.

Roadmap commands — not yet implemented

The following commands are registered in the CLI but are stubs: running them prints a "not implemented yet — coming soon" notice and exits without doing anything.

| Command | What it will do (roadmap) | |---|---| | init | Scaffold a Next.js or Vite project with selected components | | theme | Generate design theme tokens (stripe, linear, vercel, notion) |

The commands documented above (eject, list, doctor, add, analyze, convert, diff, compat) are fully implemented.

Commands

frontfamily eject                                    Interactive mode (multi-select patterns)
frontfamily eject <pattern> -f <framework>           Direct eject
frontfamily eject <p1> <p2> <p3> -f <framework>      Multi-eject
frontfamily eject <pattern> -f <fw> -o src/ui/        Custom output dir
frontfamily eject <pattern> -f <fw> --preview          Print template source to stdout (no files)
frontfamily eject <pattern> -f <fw> --dry-run          Show what would be written (no files)
frontfamily eject <pattern> -f <fw> --overwrite        Skip overwrite prompt (required to replace files in CI)
frontfamily list                                     Show all templates
frontfamily list -f <framework>                      Filter by framework
frontfamily list --json                              JSON output (for tooling)
frontfamily doctor                                   Check your package.json for each framework's deps (offline)
frontfamily doctor -f <framework>                    Check deps for one framework only
frontfamily doctor --dir <dir>                       Check a different project directory
frontfamily doctor --json                            JSON report {framework: {ready, missing, warnings?}}
frontfamily add <framework>                          Install the framework's missing deps (asks first)
frontfamily add <framework> --dry-run                Print the exact install command, change nothing
frontfamily add <framework> --yes                    Skip the confirmation prompt (CI)
frontfamily add <framework> --dir <dir>              Install into a different project directory
frontfamily add <framework> --json                   Install plan as JSON (implies --dry-run, never installs)
frontfamily analyze [dir]                            Migration feasibility report (auto-detects the UI kit)
frontfamily analyze --to <framework>                 Coverage against one target framework only
frontfamily analyze --from <framework>               Override the auto-detected source framework
frontfamily analyze --json                           JSON report {detected, from, targets, files, components, excluded}
frontfamily convert <paths...> --to <framework>      Dry-run conversion: unified diff + counts per file (auto-detects the source)
frontfamily convert <paths...> --to <fw> --write     Convert in place (asks first; refuses uncommitted/untracked files)
frontfamily convert <paths...> --to <fw> --out <dir> Write converted copies, preserving relative paths
frontfamily convert ... --from <framework>           Source framework (required when imports are ambiguous)
frontfamily convert ... --json                       Per-file JSON results {files, summary}
frontfamily convert ... --strict                     Exit 2 if any file had skipped components or warnings
frontfamily convert ... --yes / --force              Skip the prompt / write over uncommitted git changes
frontfamily diff <source> <target>                    Show all component mappings between two frameworks
frontfamily diff <source> <target> <Component>       Detailed prop mapping for one component
frontfamily diff <source> <target> --file <path>     Conversion report: per-prop status by line + confidence score
frontfamily diff <source> <target> --json            JSON output for tooling
frontfamily compat <component>                       Check if a component exists across all 9 frameworks
frontfamily compat <component> --json                JSON with coverage ratio and import paths
frontfamily --version                                Print version
frontfamily --help                                   Show help

# Not yet implemented (roadmap) — currently print a "coming soon" notice:
frontfamily init [name]                              Scaffold project (Next.js or Vite)
frontfamily theme <preset>                           Generate theme tokens

FAQ

Does it need internet? No. All 198 templates are bundled in the npm package. Fully offline.

Does it touch my existing files? eject only creates new files. If a component file already exists, it asks before overwriting (unless --overwrite is used); without a terminal (CI) it keeps the file and exits 1. Support files the templates import (frontfamily-shared/, bridge.service.ts) are written next to the component but never overwritten if already present. convert --write is the one command that edits your source files — it asks first and refuses files with uncommitted git changes unless --force; without --write it only prints a diff.

Can I change the output directory? Yes: frontfamily eject auth-login -f react-mui -o src/components/

Is this like shadcn/ui? Similar concept — you own the code. The difference: FrontFamily covers 9 frameworks (React, Vue, Angular), not just React + Tailwind. And it includes complex patterns (Kanban, Chat UI, Command Palette) not just primitives.

Can I use the output commercially? Yes. Apache 2.0 license. No restrictions.

Links

License

Apache 2.0