Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Migrate codebases between frameworks, languages, and API versions. Use when a user asks to convert JavaScript to TypeScript, migrate React class components to hooks, upgrade Vue 2 to Vue 3, migrate Python 2 to 3, update deprecated APIs, switch ORMs, convert Express to Fastify, or modernize legacy code. Handles incremental migration with backward compatibility.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 27% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 207% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 78% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 36% | 0% |
Migrate codebases between frameworks, languages, and API versions with automated, incremental transformations. This skill handles JavaScript-to-TypeScript conversions, framework upgrades, deprecated API replacements, and ORM migrations while preserving functionality and maintaining backward compatibility.
When a user asks to migrate or modernize their code, follow these steps:
Analyze the codebase to understand:
bash# Count affected files find src -name "*.js" | wc -l # JS→TS migration grep -rl "React.Component" src/ # Class→hooks migration grep -rl "Vue.component" src/ # Vue 2 patterns
Before changing code, produce a migration plan:
markdown## Migration Plan: JS → TypeScript **Files to migrate:** 47 **Estimated effort:** ~2 hours with AI assistance ### Phase 1: Setup (non-breaking) - Add tsconfig.json with allowJs: true - Install TypeScript and type packages - Rename entry point to .ts ### Phase 2: Incremental conversion (file by file) - Rename .js → .ts/.tsx - Add type annotations to function signatures - Replace `any` with proper types - Fix type errors ### Phase 3: Strict mode - Enable strict: true in tsconfig - Resolve remaining `any` types - Add return type annotations
Process files incrementally, verifying each change:
JavaScript → TypeScript:
typescript// BEFORE: src/utils/api.js const fetchUser = async (id) => { const response = await fetch(`/api/users/${id}`); if (!response.ok) throw new Error('User not found'); return response.json(); }; module.exports = { fetchUser }; // AFTER: src/utils/api.ts interface User { id: string; email: string; name: string; createdAt: string; } export const fetchUser = async (id: string): Promise<User> => { const response = await fetch(`/api/users/${id}`); if (!response.ok) throw new Error('User not found'); return response.json() as Promise<User>; };
React class → hooks:
tsx// BEFORE class UserProfile extends React.Component { state = { user: null, loading: true }; componentDidMount() { fetchUser(this.props.id).then(user => this.setState({ user, loading: false }) ); } componentDidUpdate(prevProps) { if (prevProps.id !== this.props.id) { this.setState({ loading: true }); fetchUser(this.props.id).then(user => this.setState({ user, loading: false }) ); } } render() { if (this.state.loading) return <Spinner />; return <div>{this.state.user.name}</div>; } } // AFTER function UserProfile({ id }: { id: string }) { const [user, setUser] = useState<User | null>(null); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); fetchUser(id).then(user => { setUser(user); setLoading(false); }); }, [id]); if (loading) return <Spinner />; return <div>{user?.name}</div>; }
Vue 2 → Vue 3 (Options → Composition API):
vue<!-- BEFORE: Vue 2 Options API --> <script> export default { data() { return { count: 0, items: [] }; }, computed: { total() { return this.items.reduce((s, i) => s + i.price, 0); } }, mounted() { this.fetchItems(); }, methods: { async fetchItems() { this.items = await api.getItems(); } } }; </script> <!-- AFTER: Vue 3 Composition API --> <script setup lang="ts"> import { ref, computed, onMounted } from 'vue'; const count = ref(0); const items = ref<Item[]>([]); const total = computed(() => items.value.reduce((s, i) => s + i.price, 0)); async function fetchItems() { items.value = await api.getItems(); } onMounted(fetchItems); </script>
bash# For JS→TS npm install -D typescript @types/node @types/react npx tsc --init # For Vue 2→3 npm install vue@3 @vue/compiler-sfc npm uninstall vue-template-compiler # Update import paths, build config (vite/webpack), and aliases
After each file or batch:
npx tsc --noEmitnpm testnpx eslint src/npm run buildReport any errors and fix them before proceeding.
User request: "Convert my Express app from JS to TS"
Actions taken:
@types/express, @types/node, ts-nodetsconfig.json with allowJs: true for incremental migration.js → .ts starting from leaf modules (utils, models)require → import, module.exports → exportResult:
Files migrated: 23/23
Type errors fixed: 41
New interfaces created: 8 (User, Product, Order, ApiError, etc.)
Build: ✅ passing
Tests: ✅ 34/34 passingUser request: "Upgrade our app from React Router 5 to 6"
Actions taken:
<Switch> → <Routes><Route component={X}> → <Route element={<X />}>useHistory() → useNavigate()<Redirect to="/"> → <Navigate to="/" replace><Outlet />react-router-dom to v6.20Before/After:
tsx// v5 <Switch> <Route exact path="/" component={Home} /> <Route path="/users/:id" component={UserProfile} /> <Redirect to="/" /> </Switch> // v6 <Routes> <Route path="/" element={<Home />} /> <Route path="/users/:id" element={<UserProfile />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes>
Result: 12 files updated, 0 type errors, all 28 tests passing.
strict: false and allowJs: true, then tighten after all files are converted.require/import style consistent within each file during migration — don't mix.Other measured skills in the registry, with their headline benchmark lift.