1. Why Migrate from Vue to React?

Every engineering team reaches an inflection point where the frontend framework chosen years ago no longer aligns with the direction of the product, the team's hiring pipeline, or the ecosystem they depend on. For many teams, that means moving from Vue.js to React.

The motivations are real and consistent across companies of all sizes:

From a technical standpoint, both frameworks are capable. The decision to migrate is strategic: React offers wider community contributions, better SSR tooling via Next.js, and stronger TypeScript integration out of the box. React Server Components represent a fundamental shift in how frontend architecture works — an innovation with no direct Vue equivalent at scale.

"The question isn't whether Vue can do what React does. It's whether your team, your hiring pipeline, and your AI toolchain are better served by React. For most organizations in 2026, the answer is yes."

2. The Problem with Manual Migration

Manual Vue-to-React migrations are notoriously painful. The two frameworks share the same conceptual model (reactive components, props-down/events-up) but differ in almost every syntactic and structural detail. What looks like a straightforward rewrite quickly becomes a multi-month project filled with regressions and invisible bugs.

The core translation challenges

Every Vue component carries patterns that don't translate mechanically to React:

The true cost

Beyond the technical complexity, manual migration carries organizational risk:

3. Automated vs Manual Migration: A Comparison

Dimension Manual Migration Automated (Don Cheli /dc:migrate)
Typical timeline (100 components)6–12 weeks1–2 weeks
Test coverage before mergeDepends on team disciplineEnforced by TDD Iron Law
Component conversionManual, one by oneAutomated analysis + generation
State management migrationRewrite from scratchVuex/Pinia → Zustand plan generated
Routing migrationManual route-by-routeVue Router → React Router mapping
Risk of regressionsHigh (no automated diff)Low (behavior diff at each step)
Feature freeze windowWeeks to monthsIncremental, component-by-component
Documentation generatedRarely, post-hocMigration report + ADR auto-generated
Rollback capabilityManual git revertCheckpoint-based rollback at each phase
CostHigh (senior dev hours)Framework is open source

4. How Don Cheli's /dc:migrate Works

Don Cheli's /dc:migrate command is a structured 4-phase migration process that treats the stack migration as a first-class engineering problem — with the same rigor applied to any feature built under the SDD framework. It doesn't blindly convert files; it analyzes, plans, executes incrementally, and verifies at every step.

Phase 1: Analyze

The migration begins with a full codebase analysis. The framework scans your Vue project and produces a migration inventory:

bash # Start the migration analyzer /dc:migrate --from vue --to react --analyze # Output: migration-report.md # - 87 components found # - 12 Vuex modules (3 with side effects) # - 6 Vue Router route guards # - 4 custom directives requiring manual review # - 2 render functions (complex, flagged) # - Estimated migration effort: 9 days

This analysis phase classifies each component by complexity: simple (pure template + props), medium (local state, lifecycle hooks), and complex (render functions, custom directives, deep Vuex integration). This classification drives the execution strategy in Phase 3.

Phase 2: Plan

Based on the analysis, the framework generates a detailed migration plan with dependency ordering. Components with no dependencies are migrated first. Leaf nodes before parent nodes. Shared utilities before components that consume them.

bash # Generate ordered migration plan /dc:migrate --from vue --to react --plan # Creates: migration-plan.json # { # "batches": [ # { "batch": 1, "type": "utils", "items": ["dateUtils", "validators"] }, # { "batch": 2, "type": "atoms", "items": ["Button", "Input", "Badge"] }, # { "batch": 3, "type": "molecules", "items": ["SearchBar", "UserCard"] }, # { "batch": 4, "type": "state", "items": ["authStore", "cartStore"] }, # { "batch": 5, "type": "pages", "items": ["HomePage", "CheckoutPage"] } # ] # }

The plan also maps third-party Vue dependencies to their React equivalents and flags any that have no direct substitute, requiring manual attention.

Phase 3: Execute

Execution is incremental and test-gated. For each component in the migration plan, the framework follows the TDD Iron Law: write the React test first (RED), generate the React component (GREEN), then verify behavior parity (REFACTOR). No component advances to the next batch until its tests pass.

bash # Execute migration batch by batch /dc:migrate --from vue --to react --execute --batch 1 # Per-component flow: # 1. Generate React equivalent of Vue component # 2. Write behavior-parity tests (RED) # 3. Confirm test passes against new component (GREEN) # 4. Run behavior diff vs. original (VERIFY) # 5. Checkpoint saved — rollback available if needed

Phase 4: Verify

After all batches complete, a full verification pass runs: integration tests, route coverage, accessibility audit, and a side-by-side behavioral diff of critical user flows. Only a clean verification report triggers the final migration commit.

bash # Final verification /dc:migrate --from vue --to react --verify # Checks: # [PASS] 87/87 components converted # [PASS] 312 tests passing # [PASS] All routes reachable # [PASS] No OWASP regressions # [WARN] 1 custom directive requires manual review # Migration ready for PR.

5. TDD Safety Nets During Migration

The biggest risk in any large-scale migration is the absence of a safety net. You make changes, you think things work, and three weeks later a QA engineer finds a checkout flow regression that was introduced in week one. By then, the diff is enormous and the root cause is hard to isolate.

Don Cheli's TDD Iron Law prevents this by making tests the precondition for migration advancement, not an afterthought. The law is simple and non-negotiable:

"No component is considered migrated until its behavior is proven by a passing test. RED first, then GREEN, then REFACTOR. No exceptions."

Behavior-parity tests

For each Vue component being migrated, the framework generates behavior-parity tests — tests that describe what the component does (not how it does it) and can run against both the Vue original and the React replacement. This creates a shared behavioral contract across the migration boundary.

jsx // Vue original: UserCard.vue // React target: UserCard.tsx // Shared behavior-parity test: describe('UserCard behavior parity', () => { it('renders user name and avatar', () => { render(<UserCard name="Ana" avatar="/ana.jpg" />) expect(screen.getByText('Ana')).toBeInTheDocument() expect(screen.getByRole('img')).toHaveAttribute('src', '/ana.jpg') }) it('emits/calls onEdit when edit button is clicked', async () => { const onEdit = jest.fn() render(<UserCard name="Ana" onEdit={onEdit} />) await userEvent.click(screen.getByRole('button', { name: /edit/i })) expect(onEdit).toHaveBeenCalledTimes(1) }) })

Incremental checkpoints

Each migration batch creates a git checkpoint with a complete test suite snapshot. If a later batch introduces a regression, the framework can roll back to the last clean checkpoint without losing completed work. This turns a potentially catastrophic all-or-nothing migration into a safe, incremental operation.

The TDD Iron Law also forces developers to understand what each component does before converting it. You cannot write a behavior test for a component you don't understand. This incidental documentation of component behavior is one of the most valuable byproducts of the migration process.

6. Beyond Vue to React: Other Supported Migrations

The /dc:migrate command is not limited to Vue-to-React. It applies the same Analyze → Plan → Execute → Verify methodology to any stack migration where the source and target are well-defined:

Each migration type has a dedicated profile in the framework that understands the semantic differences between source and target, not just the syntactic ones.

7. Step-by-Step: Migrating a Vue App to React

Here's a practical walkthrough of what the migration looks like in practice, using a real-world component as an example.

The Vue source component

vue <!-- ProductCard.vue --> <template> <div class="product-card" @click="handleClick"> <img :src="product.image" :alt="product.name" /> <h3>{{ product.name }}</h3> <p class="price">{{ formattedPrice }}</p> <button v-if="inStock" @click.stop="addToCart">Add to Cart</button> <span v-else class="out-of-stock">Out of Stock</span> </div> </template> <script setup> import { computed } from 'vue' import { useCartStore } from '@/stores/cart' const props = defineProps({ product: { type: Object, required: true }, inStock: { type: Boolean, default: true } }) const emit = defineEmits(['select']) const cart = useCartStore() const formattedPrice = computed(() => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }) .format(props.product.price) ) function handleClick() { emit('select', props.product) } function addToCart() { cart.add(props.product) } </script>

The React equivalent generated by /dc:migrate

jsx // ProductCard.tsx import { useCallback } from 'react' import { useCartStore } from '@/stores/cart' interface Product { id: string name: string image: string price: number } interface ProductCardProps { product: Product inStock?: boolean onSelect?: (product: Product) => void } export function ProductCard({ product, inStock = true, onSelect }: ProductCardProps) { const addToCart = useCartStore((s) => s.add) const formattedPrice = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(product.price) const handleClick = useCallback(() => { onSelect?.(product) }, [product, onSelect]) const handleAddToCart = useCallback((e: React.MouseEvent) => { e.stopPropagation() addToCart(product) }, [product, addToCart]) return ( <div className="product-card" onClick={handleClick}> <img src={product.image} alt={product.name} /> <h3>{product.name}</h3> <p className="price">{formattedPrice}</p> {inStock ? <button onClick={handleAddToCart}>Add to Cart</button> : <span className="out-of-stock">Out of Stock</span> } </div> ) }

What /dc:migrate handled automatically

Running the full migration sequence

bash # 1. Install Don Cheli and initialize in your Vue project npx don-cheli-sdd init # 2. Analyze the Vue codebase /dc:migrate --from vue --to react --analyze # 3. Review the generated migration-report.md # Make note of flagged items requiring manual review # 4. Generate the ordered migration plan /dc:migrate --from vue --to react --plan # 5. Execute batch 1 (utilities and atoms) /dc:migrate --from vue --to react --execute --batch 1 # 6. Verify batch 1 before continuing /dc:migrate --from vue --to react --verify --batch 1 # 7. Continue through remaining batches /dc:migrate --from vue --to react --execute --batch 2 /dc:migrate --from vue --to react --verify --batch 2 # ... repeat for each batch # 8. Final full verification /dc:migrate --from vue --to react --verify --all # 9. Generate migration ADR and PR description /dc:migrate --from vue --to react --report

Each --verify step is a hard gate. The framework refuses to advance to the next batch if any test is failing or if the behavioral diff shows a divergence. This is the TDD Iron Law in action: discipline enforced by tooling, not by individuals.

8. Getting Started

Don Cheli SDD is free, open source, and Apache 2.0 licensed. Installation takes under a minute. The migration commands work with Claude Code (full command support), Cursor IDE (via .cursorrules), and any AI agent that reads AGENTS.md.

bash # Install globally via npx npx don-cheli-sdd init # Or clone and install manually git clone https://github.com/doncheli/don-cheli-sdd.git cd don-cheli-sdd && bash scripts/instalar.sh --global # Initialize in your existing Vue project cd /path/to/your-vue-app /dc:init --type frontend --stack vue # Start the migration analysis /dc:migrate --from vue --to react --analyze

If you're evaluating whether migration makes sense for your specific codebase before committing, the --analyze flag runs in read-only mode and produces an effort estimate with no side effects. It's a free sanity check before you make any decisions.

The full documentation for /dc:migrate, including migration profiles for all supported stack transitions, is available in the GitHub repository.

Stop dreading your stack migration.

Don Cheli's /dc:migrate turns a 3-month manual rewrite into a structured, test-gated, incremental process. Vue to React. Angular to React. JS to TS. Open source, free, and built for teams that can't afford regressions.

Get Don Cheli on GitHub →