kramme-connect-workflow/skills/kramme:connect:modernize-angular/SKILL.md
Use this Skill when working in the Connect monorepo and needing to modernize legacy Angular components.
npx skillsauth add abildtoft/kramme-cc-workflow kramme:connect:modernize-angularInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When to use this skill:
FormComponent or BaseComponent@Select decorators for state managementFormNode instead of typed FormGroupChangeDetectionStrategy.OnPushContext: Connect's frontend is modernizing Angular components to use NgRx ComponentStore for state management, OnPush change detection, standalone components, and proper TypeScript typing. This provides better type safety, performance, and maintainability.
Read the guideline keyword glossary from references/guideline-keywords.md.
libs/connect/cms/qa/feature/src/lib/edit-topic/ - Edit topic component with form managementlibs/connect/cms/qa/feature/src/lib/settings-page/ - Settings page with conditional form logiclibs/connect/cms/qa/feature/src/lib/topics-page/ - Topics page with complex stateALWAYS read all component files before starting:
ALWAYS identify patterns to migrate:
extends FormComponent, extends BaseComponent)@Select decorators for stateFormNode usagesubscribe(), takeUntil())onInit() vs ngOnInit())ALWAYS identify business logic:
component-name.store.ts)initialState as a constantreadonly for immutability#privateFields for encapsulation(tuple): tuple is [void, DataType] => tuple[1] !== nullpipe() directly in effects: this.effect<Type>(pipe(...)) not this.effect<Type>((param$) => param$.pipe(...))EXAMPLE: See references/component-store.ts for a complete ComponentStore reference implementation.
ChangeDetectionStrategy.OnPushstandalone: trueproviders arrayinject() for dependency injectioninject() calls first in the class as readonly fields#privateField syntax for private memberspublic or private keywords in TypeScript@Select decoratorsDestroyRef and takeUntilDestroyed (ComponentStore handles cleanup)EXAMPLE: See references/component.ts for a complete component reference implementation.
@if, @for, @switch) instead of *ngIf, *ngFor, *ngSwitch*ngrxLet directive or ngrxPush pipe to handle Observables
ngrxPush pipe over async for one-off async bindings*ngrxLet or ngrxPush multiple times for the same Observable; instead assign it to a template variable using @letEXAMPLE: See references/template.html for native control flow and form binding examples.
afterClosed() and only proceed if confirmedEXAMPLE:
deleteItem(): void {
this.#dialog
.open(ConfirmDeleteModalComponent, {
data: { itemName: this.data$.value?.name },
})
.afterClosed()
.subscribe((confirmed) => {
if (confirmed) {
this.#componentStore.deleteItem();
}
});
}
successMessage in ApiAction definitions (not manual toasts in stores)CoSnackService only for local operations (cancel, info messages)EXAMPLE - Success Messages:
// ❌ WRONG - shows before API completes
readonly saveChanges = this.effect<void>(
pipe(
tap(() => {
this.#store.dispatch(updateAction.start(this.form.getRawValue()));
this.#snacks.success('Saved!'); // ← BAD
})
)
);
// ✅ CORRECT - shows only on actual success
export const updateAction = new ApiAction<State, Input, Output>(
'Entity',
'Update',
'Feature',
{
showErrors: true,
successMessage: 'Saved!', // ← GOOD
}
);
EXAMPLE:
<button
matSuffix
mat-icon-button
matTooltip="Copy to clipboard"
[cdkCopyToClipboard]="form.controls.id.value"
(cdkCopyToClipboardCopied)="onIdCopied($event)"
>
<fa-icon [icon]="copyIcon" />
</button>
corepack yarn nx lint <library-name>pipe() directlyany typesSee references/patterns.md for detailed examples of conditional field disabling and nonNullable form controls.
nonNullable: true to form controlsFormGroup and FormControl (not FormNode)pipe() directly: this.effect<Type>(pipe(...))this.effect<Type>((param$) => param$.pipe(...))DestroyRef and takeUntilDestroyed for ComponentStore subscriptionssuccessMessage in ApiAction definitionsCoSnackService only for local operationsany types
unknown when type is uncertain#privateField syntax for encapsulationpublic or private keywords in TypeScript class membersComponentStore.get()
See references/checklist.md for the full phase-by-phase migration checklist.
changeDetection: ChangeDetectionStrategy.OnPush in @Component decorator for new componentsinject() calls first in the class as readonly fields@Input and @Output properties second in the classclass bindings instead of ngClassstyle bindings instead of ngStyletw- prefix (enforced in libs/co/ui-tailwind-preset/tailwind.config.js)@apply directive@fortawesome/angular-fontawesome package<fa-icon> component, not <i> tags with CSS classes@fortawesome/pro-*-svg-icons (not free packages)yarn run format (from Connect/ng-app-monolith)yarn exec nx affected --targets=lint,test --skip-nx-cacheALWAYS refer to these files for complete examples:
libs/connect/cms/qa/feature/src/lib/edit-topic/cms-qa-edit-topic.store.tslibs/connect/cms/qa/feature/src/lib/settings-page/cms-qa-settings-page.store.tslibs/connect/cms/qa/feature/src/lib/topics-page/cms-qa-topics-page.store.tsAGENTS.md - Angular Development Patterns sectionSee the Instructions section.
development
Compare an existing PR's title and body against the actual branch diff and report drift — false claims, missing major changes, stale scope, missing risk callouts. Use after pushing changes to a branch with an open PR, or before requesting review. Read-only by default; add --fix to delegate to kramme:pr:generate-description for an updated description. Complements kramme:pr:code-review (which checks description accuracy as one signal among many code-quality checks) by being a fast, focused, single-purpose check that runs in seconds.
tools
Reviews plugin skills for focused scope, progressive disclosure, portability, safety, retry behavior, and documentation quality. Use when auditing a SKILL.md, skill directory, or proposed skill text against skill-authoring standards. Not for creating new skills, editing skills, or reviewing ordinary application code.
tools
Reviews recent agent session transcripts to find repeated manual workflows or repeated user asks, then proposes and optionally scaffolds only useful new skills or custom subagents. Use when the user asks to inspect recent sessions, find automation opportunities, or create reusable workflows from repeated work. Not for summarizing one session, general retrospectives, or codebase refactoring.
data-ai
Remove all DONE issues and renumber remaining issues within each prefix group. Not for editing live issue content, archiving still-open issues, or moving issues between prefix groups.