AI-Assisted Development
Registry
Governance
Components
Search for a command to run or a page to navigate to.
The @strongtie/design-system package is the recommended path for teams that want pre-built, versioned components without owning the primitive code. If you already have a shadcn/ui app with vendored @/components/ui/* primitives, the codemod migrates it to the package for you — rewriting imports, swapping dependencies, and modularizing your CSS in one pass.
This tool migrates you toward the package. It requires Azure Artifacts access; environments without feed credentials should use the public Strongtie registry for new component installs.
The codemod finds imports of your vendored shadcn primitives and points them at the published package instead. At a glance:
- import { Button } from "@/components/ui/button"
- import { Card, CardContent } from "@/components/ui/card"
+ import { Button } from "@strongtie/design-system/button"
+ import { Card, CardContent } from "@strongtie/design-system/card"In the same run it updates package.json, rewrites your CSS entry to the modular Tailwind imports, deletes the now-migrated ui/ primitives, and leaves // TODO markers on anything it can't safely convert.
@/components/ui/* (the standard shadcn alias).Commit or stash your work first. A live run rewrites files on disk. The
tool refuses to run on a dirty git tree unless you pass --yes (or run with
--dry, which writes nothing), so committing first is both a safety net and
the smoothest path.
@/components/ui/* imports (and relative ui/* imports and re-exports) to @strongtie/design-system/*.@strongtie/design-system to your dependencies — or to peerDependencies if your package.json looks like a publishable library.sonner and lucide-react.sonner to ^2.0.5, tw-animate-css to ^1.4.0), so npm install doesn't fail with a peer-dependency (ERESOLVE) conflict. A peer already at or above the floor — or pinned to a non-semver value like latest or a tarball URL — is left untouched.styles/tokens + tailwindcss + styles/theme + styles/scan), removing the duplicated shadcn token ramp while preserving your app-specific tokens.TabNav usage: converts clearly state-only usages to Tabs / TabsList variant="line" under --tab-nav convert, and flags route-driven usages.CollapsibleItem alias to Collapsible, fixes the import, and leaves a // TODO for you to verify.ui/ primitives while keeping your custom composites and lib/utils.ts.@/ aliases are not auto-detected. Only the @/components/ui/* alias form and relative ui/* forms are rewritten. If your project uses a different alias, those imports are left untouched (see Troubleshooting).@base-ui/react-based combobox. If your local ui/combobox.tsx is built on @base-ui/react, the package combobox is API-incompatible, so yours is kept and marked with a // TODO. A plain shadcn combobox is rewritten normally.TabNav off the deprecated tab-nav. Route-driven usage is kept and flagged with a // TODO.confirm-dialog, etc.) — anything that isn't a plain vendored primitive stays in your project.Run the migration against your source directory:
The default command is migrate, so npx @strongtie/design-system-codemod@latest ./src works too.
Projects whose @/ alias maps to the repo root (rather than src/) spread
their imports across the whole tree, so scoping to ./src would miss most of
them. Point the codemod at the root instead — migrate . is supported. If the
repo keeps sibling copies of the app in-tree (vendored snapshots, nested git
worktrees, an agent's .claude/worktrees), exclude each one so it stays out of
every scan: migrate . --ignore-pattern archived-contexts --ignore-pattern .claude.
Pass a real path. If you point the codemod at a directory with no matching files, it reports 0 files and prints a "check your path" hint rather than failing silently. If you see 0 files, double-check the path.
| Flag | Applies to | Description |
|---|---|---|
--dry | global | Preview only — writes nothing. Exempt from the clean-git-tree guard. |
--print | global | Print the changed file contents to stdout (works with or without --dry). |
--yes | global | Skip prompts and the clean-git-tree guard. |
--verbose | global | Per-file and per-dependency change detail. |
--extensions <list> | global | File extensions to scan. Default: tsx,ts,jsx,js. |
--ignore-pattern <glob> | global | Glob of paths to skip. Repeatable — pass the flag more than once to skip several. Applies to every scan (rewrite, deletion, and dependency), so excluding a vendored app copy or a nested git worktree keeps it out of all of them. |
--no-css | migrate | Skip the CSS transform. |
--no-deps | migrate | Skip the dependency transform. |
--no-delete-ui | migrate | Keep the vendored ui/ primitives instead of deleting them. |
--tab-nav <mode> | migrate | flag (default, conservative — keep on tab-nav + TODO) or convert (convert state-only usages to Tabs / TabsList variant="line"). |
--global | setup-registry | Write ~/.npmrc instead of the project .npmrc. |
Start from a clean git tree so you can diff and roll back:
git statusSee exactly what would change without writing anything:
Read the printed diffs and the list of files the codemod would touch. Confirm the import rewrites, dependency changes, and CSS rewrite look right.
Review the changes and address every marker the codemod left behind:
git diffSearch for // TODO: @strongtie/design-system-codemod and resolve each one (combobox, route-driven TabNav, CollapsibleItem, etc.).
Once the build and tests pass, commit the migration as its own change.
- import { Button } from "@/components/ui/button"
- import { Input } from "@/components/ui/input"
+ import { Button } from "@strongtie/design-system/button"
+ import { Input } from "@strongtie/design-system/input" "dependencies": {
+ "@strongtie/design-system": "latest",
- "@radix-ui/react-dialog": "^1.1.0",
- "@radix-ui/react-slot": "^1.1.0",
- "class-variance-authority": "^0.7.0",
"lucide-react": "^0.400.0",
"sonner": "^1.5.0"
}The codemod adds @strongtie/design-system as "latest" — review and pin the version after installing. Radix primitives, class-variance-authority, and other shadcn-only dependencies are removed only when nothing outside the deleted ui/ layer still imports them; sonner and lucide-react are always kept.
+ @import "@strongtie/design-system/styles/tokens";
@import "tailwindcss";
+ @import "@strongtie/design-system/styles/theme";
@import "tw-animate-css";
+ @import "@strongtie/design-system/styles/scan";
:root {
- --background: oklch(1 0 0);
- --foreground: oklch(0.145 0 0);
--brand: oklch(0.62 0.21 259); /* your app-specific tokens are preserved */
}Only the duplicated shadcn token ramp is removed; your app-specific tokens stay in place. A ramp token whose value differs from the design-system default (a deliberate override, e.g. a custom --primary) is also kept in place and flagged with a TODO, rather than silently dropped — percentage/degree spellings (oklch(100% 0 0deg)) are compared equal to their decimal form (oklch(1 0 0)), so only genuine overrides are preserved. The @strongtie/design-system/styles/scan import registers the package's compiled components for Tailwind scanning. On older package versions that predate that export, the codemod falls back to a relative @source "../node_modules/@strongtie/design-system/dist"; line instead.
The codemod is safe to re-run. A second pass over an already-migrated project is a no-op: nothing is rewritten and no new markers are added.
After the codemod finishes, a few steps are yours to complete:
Install the package. The codemod updates package.json but doesn't run npm install. Configure Azure Artifacts and install — the setup-registry command below scaffolds the .npmrc for you, then follow the Package Installation guide.
Resolve every // TODO marker. Search for // TODO: @strongtie/design-system-codemod and address each one.
Type-check the project.
Verify the combobox and TabNav. These are intentionally left in place — confirm the local combobox still works and decide how to handle any route-driven TabNav.
The package is published to the Azure Artifacts Simpson feed, so npm needs a scoped registry entry. The setup-registry command writes that .npmrc for you:
Pass --global to write ~/.npmrc instead of the project .npmrc. This command scaffolds the scoped registry configuration only — it never writes a PAT or secret. Complete authentication by following the Azure Artifacts npm guide, covered in the Package Installation guide.
The codemod scanned your path and matched nothing. Confirm you passed the directory that contains your components (usually ./src), and that your files use the extensions it scans (tsx,ts,jsx,js by default — override with --extensions).
The codemod only rewrites the @/components/ui/* alias form and relative ui/* forms. If your project uses a different alias (for example ~/components/ui/*), those imports are not auto-detected. Rewrite them manually, or temporarily normalize your alias to @/ before running.
Some package components have a slightly different API than the vendored primitives (API drift). Run npx tsc --noEmit to surface these and adjust the call sites. A @base-ui/react-based combobox in particular is intentionally left local because that package version is API-incompatible; a plain shadcn combobox is migrated normally.
If your app renders a full-width header above the sidebar (rather than the
standard shadcn shell where the header sits inside the content, to the right of a
full-height sidebar), the package sidebar — which is fixed and anchored to the
viewport top — will overlap that header, hiding anything on its left (e.g. a logo)
and drawing a seam across it. Tell the sidebar how tall your top bar is by setting
--header-height on the SidebarProvider; the fixed sidebar then starts below the
bar. It defaults to 0px, so the standard shell is unaffected.
<SidebarProvider style={{ "--header-height": "3.5rem" } as React.CSSProperties}>If package components render unstyled, your Tailwind build isn't scanning the package dist. Confirm the CSS rewrite added @import "@strongtie/design-system/styles/scan"; (or, on older package versions, the fallback @source ".../node_modules/@strongtie/design-system/dist";). See Using with Tailwind CSS.
Installing the package requires access to the Simpson feed. Run setup-registry to scaffold the scoped .npmrc, then complete PAT authentication as described in the Package Installation guide.
@studs/react package.