@frontfamily/cli
v0.18.1
Published
Eject production-ready UI pattern components across React, Vue, and Angular frameworks
Maintainers
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 moreThe 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.tsx198 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 ejectUsage
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.tsxDirect 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 --overwriteExit 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 $?
1In 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 Modal1,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 --jsonThe 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.0Install 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@^4If 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), skippingnode_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 detectionanalyzeuses — imports in comments, strings andimport typedon't count). If files import more than one kit, or none (e.g. Tailwind-only code —react-tailwindhas no kit package),--fromis 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 (Snackbarabove), 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,--yesis 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-quasaroutput is a draft: component tags become Quasar template markup, but the React function, hooks and JSX expressions stay — valid in neither framework. So--writeis refused for it; preview it, or use--outto write<file>.vue-draft.txtdrafts to port by hand into a.vueSFC. There are no conversion paths to Angular. - Exit codes.
0success ·1invalid arguments, unknown framework, no files, or a refused write ·2with--strictwhen 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 --jsonPatterns
| 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 tokensFAQ
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
- Web Converter — convert code between frameworks online
- Migration Guides — 17 guides with 794 searchable component mappings
- CLI Documentation — full docs with examples
- Community & Issues — bug reports, feature requests, mapping corrections
License
Apache 2.0
