This tool automates the migration of components between design systems. Currently supports migration from Orbiter to Hopper, with extensible architecture for other design system migrations.
Key Features:
- ✅ Automated component migrations - Updates import statements and component names
- ✅ Property transformations - Maps old properties to new equivalents
- ✅ Migration analysis - Generates usage reports and migration guidance
- ✅ Extensible mappings - Support for multiple design system migrations
The easiest way to run migrations is using our CLI tool:
# Run directly with pnpx (no installation required)
pnpx "@workleap/migrations"@latestThe CLI automatically:
- Clones the latest migration repository
- Runs the migrations with your specified options
- Cleans up temporary files
For more CLI options:
pnpx "@workleap/migrations"@latest --helpBefore:
import { Div } from "@workleap/orbiter-ui";
export function App() {
return <Div width="100px"/>;
}After:
import { Div } from "@hopper-ui/components";
export function App() {
return <Div UNSAFE_width="100px"/>;
}The default mapping table is set for Orbiter to Hopper. If you want to run it for other mappings, you need to set it through the mappings parameter.
pnpx "@workleap/migrations"@latest# Migrate layout components (Flex, Grid, Div, etc.)
pnpx "@workleap/migrations"@latest -c layout
# Migrate button components
pnpx "@workleap/migrations"@latest -c buttons
# Other categories: visual, menu, overlay, tags, disclosure# Single component
pnpx "@workleap/migrations"@latest -c Div
# Multiple components
pnpx "@workleap/migrations"@latest -c Div,Text,ButtonRun the command in the desire path or pass the target path with the -t argument.
pnpx "@workleap/migrations"@latest -t /app/usersHandle custom component names that should be treated as specific design system components for migration. Aliases maintain their original imports while migrating their props according to the component mapping.
Create an aliases configuration file:
{
"Button": "PublicButton",
"Div": ["InfoCard", "WarningCard", "PrivateAlert"]
}Run migrations with aliases file:
pnpx "@workleap/migrations"@latest --aliases aliases.jsonPass aliases directly as a JSON string:
# Single alias
pnpx "@workleap/migrations"@latest --aliases '{"Button": "MyButton"}'
# Multiple aliases
pnpx "@workleap/migrations"@latest --aliases '{"Button": ["PublicButton", "PrivateButton"], "Div": "CustomDiv"}'Example transformation:
Before:
import { PublicButton } from "./components";
export function App() {
return <PublicButton width="120px" onClick={callback} />;
}After:
import { PublicButton } from "./components"; // Import unchanged
export function App() {
return <PublicButton UNSAFE_width="120px" onPress={callback} />; // Props migrated
}Generate usage reports to understand your migration scope:
# Basic analysis
pnpx "@workleap/migrations"@latest analyze
# Detailed analysis with file locations
pnpx "@workleap/migrations"@latest analyze --deep true
# Project-specific analysis
pnpx "@workleap/migrations"@latest analyze --project frontend-team
# Using hopper mappings for analysis
pnpx "@workleap/migrations"@latest analyze --mappings hopper
# Analyze unmapped components only
pnpx "@workleap/migrations"@latest analyze --filter-unmapped componentsKey Parameters:
| Parameter | Description | Example |
|---|---|---|
-c <components> |
Specify components to migrate | -c layout or -c Div,Text |
-t <path> |
Target specific path | -t /app/users |
--aliases <path> |
Path to JSON file containing component aliases mapping | --aliases aliases.json |
--project <name> |
Track usage by project/team. It is pretty useful when you analysis multiple repos and want to aggregate analysis results. | --project frontend-team |
--mappings <type> |
Specify mapping table (orbiter-to-hopper (default) or hopper) |
--mappings hopper |
--deep true |
Include file locations | --deep true |
--filter-unmapped <type> |
Show only unmapped items | --filter-unmapped props |
--usage-report-file <file> |
File to save usage report for analysis mode (defaults to usage-report.json) |
--usage-report-file custom-report.json |
analyze |
Pass it as first argument to analyze. Otherwise, it runs migrations | N/A |
Sample Analysis Output:
{
"overall": {
"usage": {
"components": 15,
"componentProps": 45,
"functions": 3,
"types": 8
}
},
"components": {
"Text": {
"usage": {
"total": 25,
"projects": {
"frontend-team": 15,
"mobile-app": 10
}
},
"props": {
"size": {
"usage": 20,
"values": {
"lg": { "usage": { "total": 12 } },
"md": { "usage": { "total": 8 } }
}
}
}
},
"Button": {
"usage": {
"total": 18,
"projects": { "frontend-team": 18 }
}
}
},
"functions": {
"useResponsive": {
"usage": {
"total": 8,
"projects": {
"frontend-team": 5,
"mobile-app": 3
}
},
"values": {
"useResponsive()": {
"usage": { "total": 8 }
}
}
}
},
"types": {
"ComponentProps": {
"usage": {
"total": 12,
"projects": {
"frontend-team": 8,
"mobile-app": 4
}
}
}
}
}If you encounter this error:
Error [ERR_REQUIRE_ESM]: require() of ES Module
You need to update your Node.js version to v24.0.0 or later. This error occurs when using an incompatible Node.js version with ES modules.
To update Node.js:
# Using nvm (recommended)
nvm install 24
nvm use 24
# Or download from nodejs.org
# https://nodejs.org/To add support for other design system migrations or contribute to existing ones, see CONTRIBUTING.md for detailed guidelines.