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

cra-vite-migrate

v0.2.0

Published

Codemod tool for migrating create-react-app codebases to Vite + React 19

Readme

cra-vite-migrate

cra-vite-migrate — a migration orchestrator that takes a react-scripts / Create React App (CRA) codebase ~80% of the way to a Vite + React 19 target stack, then hands off a precise, verified burndown list for the judgment-heavy remainder.

It is not a one-shot magic rewriter. The product is "80% migrated + a ranked, verified burndown list." The CLI only applies deterministic transforms; non-deterministic fixes are sliced into briefs that a human or agent must satisfy against the same gates.

What it does

  1. Audit a repo and score its migration difficulty (easy/medium/hard/blocked).
  2. Run idempotent, re-runnable phases, each owning a narrow set of files.
  3. Checkpoint with git so every phase has a clean rollback (--dry-run uses a throwaway worktree).
  4. Verify after each phase — install, tsc, biome, unit tests, Vite build — with structured error parsing.
  5. Emit a resumable manifest (.cra-vite-migrate/manifest.json) and an agent/human burndown loop for the residual 20%.

Requirements

  • Node.js >= 20.0.0
  • The target repo must be a git working tree (checkpoints/rollback rely on git) with a package.json at its root.
  • The target repo's own install, typecheck, and build commands must work — gates shell out to the workspace's real toolchain.

Install

npm install
npm run build      # emits ./dist (tsc)

Run locally without building:

npm run dev <command> [args]      # = tsx src/cli/index.ts

Usage

cra-vite-migrate <command> [args]

Core workflow

# 1. Score and inventory one or more CRA repos
cra-vite-migrate audit path/to/repo            # styled report
cra-vite-migrate audit ./repos/* --json \
  --out reports/audit.json                      # machine-readable

# 2. Execute migration phases
cra-vite-migrate run path/to/repo               # all phases
cra-vite-migrate run path/to/repo --phase 05-cjs-to-esm
cra-vite-migrate run path/to/repo --from 02-vite-scaffold --to 11-vitest
cra-vite-migrate run path/to/repo --continue    # resume from first non-terminal phase
cra-vite-migrate run path/to-repo --dry-run     # detached worktree, no commits

# 3. Re-run verification gates
cra-vite-migrate verify path/to/repo --gate typecheck
cra-vite-migrate verify path/to/repo --all      # install, typecheck, biome, unit, build, e2e

Phases that finish red but are marked recoverable are recorded as needs_burndown rather than failing the run; the summary prints them.

Batch operations

# Audit many repos into an inventory (easiest-first)
cra-vite-migrate batch audit ./repos/* --out inventory.json

# Migrate across the inventory
cra-vite-migrate batch run \
  --from-audit inventory.json \
  --strategy easiest-first \
  --max-parallel 3 \
  --stop-on-fail \
  --out batch-report.md

Commit message prefixes

By default every phase commits with migrate(<phaseId>): apply phase. Many remotes enforce their own subject policy (JIRA ticket prefixes, Conventional Commits types, signing trailers) and reject pushes that don't match. Pass a prefix header and it's prepended to each phase commit, joined with exactly one space (a trailing space in the value is collapsed, so JIRA-1234 and JIRA-1234 produce the same subject).

# Single repo: one prefix for every phase in the run
cra-vite-migrate run path/to/repo --commit-prefix "JIRA-1234"
# → "JIRA-1234 migrate(02-vite-scaffold): apply phase"

For batch migrations, supply a JSON map keyed by the absolute repoRoot values that appear in inventory.json. Repos absent from the map get no prefix.

cra-vite-migrate batch run \
  --from-audit inventory.json \
  --commit-prefixes prefixes.json
// prefixes.json — keys must match inventory.json `repoRoot` (absolute paths)
{
  "/abs/path/repo-a": "JIRA-1234",
  "/abs/path/repo-b": "PROJ-456"
}

The map is resolved once at batch start and threaded to each repo's run invocation. Keys are absolute paths because that's how the inventory already identifies repos (see AuditReport.repoRoot); the file is an ops artifact that travels with inventory.json and is machine-specific by design.

Agent-assisted burndown

When a gate stays red, slice its errors into model-sized briefs and either review them by hand or drive an automated loop:

# Emit one burndown brief (prints, or writes to --out)
cra-vite-migrate agent next path/to/repo \
  --gate tsc --max-files 5 --max-errors 25 --out task.md

# Drive iterative burndown against a gate
cra-vite-migrate agent loop path/to/repo \
  --gate tsc --max-iterations 10 --provider local-command

Providers: local-command (default), noop. The loop only accepts diffs that pass the gate; the summary reports accepted / stuck / remaining.

Migration phases

Executed in this order (governed by PHASE_ORDER in src/core/phase.ts):

| ID | Phase | | ---------------------------- | ----------------------------------------- | | 00-preflight | preflight checks | | 01-package-upgrades | bump deps to React-19-compatible versions | | 02-vite-scaffold | add Vite config + entry | | 03-craco-webpack-translate | translate craco/webpack overrides | | 04-env-migration | process.env.*import.meta.env.* | | 05-cjs-to-esm | CommonJS → ESM | | 06-reactdom-root | ReactDOM.rendercreateRoot | | 07-react19-codemods | React 19 codemods | | 08-jsx-extension-migration | .js.jsx / .tsx where needed | | 09-mui-codemods | Material UI React-19 codemods | | 10-biome | scaffold Biome | | 11-vitest | Jest → Vitest | | 12-playwright | scaffold Playwright | | 13-typescript-strict | tighten TS config | | 14-zod-boundaries | Zod boundaries | | 15-lefthook-cleanup | Lefthook pre-push gate + CRA cleanup | | 16-final-report | emit final report |

Each phase implements detect / isSatisfied / run, so phases are skipped when they don't apply and are safe to re-run.

State

Progress is persisted in <repo>/.cra-vite-migrate/manifest.json (a Zod-validated manifest of phase records, audit snapshot, and burndown items). Delete it to start fresh.

Command status

Implemented: audit, run, verify, batch audit, batch run, agent next, agent loop.

Stubbed (print "not yet implemented"): plan, status, rollback.

Development

npm run build        # tsc → ./dist
npm run typecheck    # tsc --noEmit
npm test             # vitest run
npm run test:watch   # vitest

Pre-push (Lefthook): typecheck, lint, unit (test:run) must be green.

License

MIT