Goal
Successfully migrate a Taiga UI project to the next major version while:
- Preserving runtime behavior, template output, styles, and build tooling
- Handling post-schematics TODOs safely and systematically
- Identifying and resolving common migration issues
- Minimizing breaking changes through careful verification
Step 0: Gather Context Before Acting
CRITICAL: Before executing any command or editing any file, collect and confirm the following:
| Question | Where to find it |
|---|
| Source and target major versions | Ask the user if not stated |
| Package manager (npm / yarn / pnpm) | → field or lock-file presence |
| Build system (Angular CLI / Nx) | Presence of or |
| Monorepo: how many apps/libs affected | → , or → |
| Custom webpack / ESBuild config | → field |
If the Taiga UI MCP server is available, use
now to load the
{CURRENT_MAJOR} → {NEXT_MAJOR} migration notes before proceeding. This gives you
authoritative breaking-change information for the entire session.
Do not proceed to Phase 1 until every item in the table is resolved.
Before You Start - Prerequisites Checklist
⛔ NEVER use , , or any flag that bypasses dependency resolution.
These flags hide real version conflicts that will break at runtime. Resolve conflicts explicitly instead.
Migration Workflow
Phase 1: Run Migration Schematics
For Angular CLI projects:
For Nx projects:
bash
nx migrate @taiga-ui/cdk
nx migrate --run-migrations=migrations.json
Phase 2: Review Changed Code
After schematics complete:
-
Review all changed code lines - Some changes contain new code comments (like
// TODO: (Taiga UI migration)
). These comments typically contain instructions for manually migrating deleted entities with new alternatives.
-
Check for @taiga-ui/legacy imports - You may find new imports from
. This is a transitional package for outdated entities before their full removal:
- Everything in this package in v{NEXT_MAJOR} will be removed in v{NEXT_MAJOR+1}
- You can continue using them temporarily
- Most deprecated entities have modern alternatives marked with tag (IDEs display these as stricken-through)
- Strongly recommended: Replace with modern alternatives as soon as possible
Phase 3: Handle Migration TODOs
Handle post-schematics TODOs without breaking runtime behavior, template output, styles, or build tooling.
Core Rules for TODOs
- TODOs are not permission to guess. They are a prompt to verify what is actually safe to change.
- Fix all actionable TODOs in scope, but only after proving each fix from nearby code and usage.
- Prefer the smallest possible change that preserves current behavior.
- Never remove a deprecated package, import, or utility just because a TODO suggests it unless the codebase proves it is unused.
- If a fix could change logic, generated markup, CSS application, or script behavior, validate the surrounding usage first.
- If the safe fix is unclear, ask the user instead of inventing code.
TODO Processing Order
Process TODOs starting from shared modules and barrel files (
,
) to unblock consumers, then move to services, components, and finally style entry points. Complete all TODOs in a file before moving to the next one. If a file cannot be completed, add a Quick Entry to MIGRATION_ISSUES.md and continue.
TODO Classification → Required Question Template
| Category | Stop condition | Question to ask |
|---|
| Template/DI (high priority) | Direct replacement exists | Usually safe to fix without asking |
| Style package removal | Any class from that package found in templates | "I found used in . Should I keep the old style package until these are migrated?" |
| No direct replacement | TODO explicitly says so | "The migration notes say was removed with no direct replacement. What behavior should replace it?" |
| Dynamic binding | where expr is runtime value | "The binding uses a runtime value. Should the new API accept the same values?" |
| Multiple valid paths | More than one replacement exists in docs | "Two replacements exist: and . Which one matches your intended behavior?" |
| Warning-only | TODO indicates manual decision needed | "This TODO requires your decision: . What is your preferred approach?" |
Classification examples:
TODO: replace TuiButtonModule with TuiButton
→ Template/DI (high priority, usually safe)
TODO: remove @taiga-ui/styles import
→ Style package (STOP, check usage first)
TODO: migrate to standalone component API
→ TypeScript (medium priority, check consumers)
TODO: this API was removed, no direct replacement
→ Warning-only (ask user)
TODO Workflow
- Identify and classify the TODO using the table above
- Look up the replacement using MCP (if available):
- For component replacements: call with the new component name
- For architectural changes: call or
- Skip this step only if the replacement is unambiguous from local code context alone
- Trace real usage before editing anything:
- Search the current component, template, styles, and nearby files for direct references
- For style-related TODOs, follow the Style Package Removal algorithm below
- Confirm whether the TODO targets one site or a broader pattern
- Decide whether the TODO is safely actionable:
- If there is a one-to-one replacement and it preserves behavior, apply it
- If a deprecated package is mentioned, check whether any runtime, template, or style usage still depends on it before deleting it
- If multiple replacements are plausible, or the fix depends on dynamic bindings or generated output, stop and ask the user using the question template
- Apply the smallest safe fix:
- Keep changes localized
- Avoid broad refactors unless they are required to preserve behavior
- Do not remove imports, packages, or scripts unless the surrounding evidence supports that removal
- Verify the result:
- Re-read the touched area to make sure logic, classes, and selectors still line up
- Run the narrowest available check for the affected slice when possible
- If the change still feels ambiguous after verification, do not expand the patch; ask the user
Phase 4: Troubleshooting
Problem: TypeScript errors TS6133 - variable is declared but its value is never read
Solution: Migration schematics don't include code formatting on purpose (it would slow down execution). Use your IDE or linter:
- WebStorm: Right-click on root folder → "Optimize imports" (removes all unused imports recursively)
- Visual Studio Code: Use "Organize Imports" folder source action across all files recursively
- ESLint/Prettier: Run well-optimized rules to clean up unused imports
Problem: Yarn users or legacy-peer-deps workaround needed
Solution: Taiga UI depends on many Taiga Family packages. Yarn and pnpm do not automatically install transitive peer dependencies. Manually check each Taiga UI package's
and install missing peer dependencies.
Problem: Cannot resolve dependency for ng-web-apis, maskito, ng-polymorpheus, or ng-event-plugins
Solution: Same as above - manually install transitive peer dependencies by checking each Taiga UI package's
Problem: Cannot find module 'ts-morph'
error after nx migrate --run-migrations
Solution: This is an Nx issue with the ng migrate command. Either:
- Bump Nx version, or
- Run followed by re-running the migration
Problem: FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Solution: Migration schematics recursively traverse every file and directory, which can be memory-intensive. Increase the memory limit for the Node.js process:
bash
NODE_OPTIONS="--max-old-space-size=4096" ng update @taiga-ui/cdk
Problem: Basic / command fails, need to execute schematics manually
Solution:
- Manually update all Taiga UI packages to v{NEXT_MAJOR} in (change versions without console commands, then run )
- Verify
node_modules/@taiga-ui/cdk/package.json
contains the v{NEXT_MAJOR} version
- Execute:
Angular CLI:
bash
ng update @taiga-ui/cdk --from=@taiga-ui/cdk@<old-version> --to=@taiga-ui/cdk@<new-version>
Nx:
bash
nx migrate @taiga-ui/cdk --from=@taiga-ui/cdk@<old-version>
nx migrate --run-migrations=migrations.json
Documenting Uncertain or Broken Migration Points
When encountering migration issues that cannot be resolved immediately, create and maintain a dedicated file
(e.g.,
or
) to track all uncertain or potentially broken areas.
Two-tier Documentation Format
Quick entry (for straightforward blockers):
markdown
- [ ] `src/app/button.component.html:34` — `TuiButtonModule` TODO,
blocked: dynamic `[appearance]` binding, need user input
Use quick entries for:
- Single-file issues with clear blocking reason
- Cases where the question to ask is obvious from the TODO
- Minor style package usage that needs user decision
Full entry (only when multiple files affected or behavior change is possible):
Use the 7-field format below for:
- Issues spanning multiple files
- Potential behavior changes
- Complex style package dependencies
- Cases requiring detailed explanation
Required Format for Full Entry
Each documented issue must include:
- File path - Full relative path to the affected file (or list of files)
- Line number - Exact line where the issue occurs
- Original code - The code snippet before your attempted fix
- Issue description - Clear explanation of what is uncertain or broken
- Attempted solutions - What migration approaches you considered and why they may not work
- Potential impact - What could break if the wrong fix is applied (runtime, template, styles, build)
- Migration version - Which Taiga UI version migration this relates to (if known)
Example Full Entry Format
markdown
## Issue #<number>: <Brief description>
**Files:**
- `path/to/component.ts`
- `path/to/component.html`
**Lines:** 42, 15
**Migration:** v4 -> v5
**Original code:**
```typescript
// TODO: migrate to new button API
@Input() mode: 'accent' | 'primary' = 'primary';
```
```html
<button [mode]="mode">Click me</button>
```
**Issue:**
The old `mode` input was replaced with a new directive-based API, but this component
uses dynamic binding that may not be compatible with the new approach.
**Attempted solutions:**
- Direct replacement with `tuiAppearance` - unclear if dynamic values work
- Keeping old API temporarily - requires deprecated module import
**Potential impact:**
- Runtime error if binding fails
- Visual regression if styling is not applied correctly
Workflow Integration
- During initial scan: Create the migration issues file at the start of the migration session
- When blocked: Add a Quick Entry before moving to the next TODO
- Before asking user: Reference the documented entry in your question
- After resolution: Mark the entry as resolved with a brief note about the applied fix
Definition of Done
The migration session is complete when ALL of the following are true:
Do not refactor, rename, or improve code beyond what migration requires.
When to Ask the User
Use the question templates from the TODO Classification table for all TODO-related decisions.
Additionally, ask when:
- Migration schematics failed or produced unexpected errors
- The project has custom configurations that may affect migration
- Step 0 context cannot be determined automatically
- A peer-dependency conflict cannot be resolved by aligning Taiga UI package versions
What Not to Do
- Do not use , , or any flag that bypasses dependency resolution, and do not add to if it was not already there — these hide real version conflicts that will break the migration at runtime; resolve conflicts explicitly instead
- Do not hardcode a fix based only on the TODO text
- Do not delete deprecated dependencies first and discover breakage later
- Do not rewrite unrelated code while chasing a migration TODO
- Do not suppress TODOs with a new warning if the actual fix is already known and safe
- Do not continue if you cannot explain why the change is safe from the local code context
- Do not skip the prerequisites checklist - ensure environment is properly prepared
- Do not skip Step 0 (Gather Context) - know your environment before acting