kramme-connect-workflow/skills/kramme:connect:extract-nx-libs/SKILL.md
Use this Skill when working in the Connect monorepo and needing to extract app code into proper Nx libraries.
npx skillsauth add abildtoft/kramme-cc-workflow kramme:connect:extract-nx-libsInstall 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.
Migrate code from the Connect app folder (apps/connect/) into proper Nx libraries following established conventions.
apps/connect/src/app/ to libs/Follow the naming convention: libs/<product>/<application>/<domain>/<type>
Products: academy, coaching, connect, shared
Applications: cms, shared, ufa (User-Facing Application)
Types: assets, data-access, domain, feature, styles, test-util, ui, util
For a feature like "certification-rubrics", create:
libs/connect/
├── shared/<domain>/domain/ # Shared types used by both CMS and UFA
├── cms/<domain>/
│ ├── domain/ # CMS-specific models/types
│ ├── data-access/ # CMS store, API clients
│ └── feature/ # CMS components
└── ufa/<domain>/
├── domain/ # UFA-specific models/types
├── data-access/ # UFA store, API clients
└── feature/ # UFA components
Before planning the migration, discover ALL code related to the feature and confirm scope with the user.
Search the entire codebase for code related to the feature:
# Find all files with the feature name
find Connect/ng-app-monolith -type f -name "*<feature>*" | grep -v node_modules
# Search for feature-related imports and references
grep -r "<FeatureName>" Connect/ng-app-monolith --include="*.ts" --include="*.html" | grep -v node_modules
# Check for related types, interfaces, enums
grep -r "interface.*<Feature>\|type.*<Feature>\|enum.*<Feature>" Connect/ng-app-monolith --include="*.ts" | grep -v node_modules
Organize findings into categories:
apps/connect/src/app/)
ALWAYS ask the user to confirm what should be moved:
Present a summary like:
## Found Feature-Related Code
### Components (X files)
- `apps/connect/src/app/site/event/components/<feature>/` (UFA)
- `apps/connect/src/app/cms/cms/components/<feature>/` (CMS)
### Stores/Services (X files)
- `libs/connect/cms/<related>/data-access/` - contains <feature> store actions
### Types (X files)
- `libs/connect/cms/<related>/data-access/src/lib/<feature>.model.ts`
### Routes referencing feature
- `apps/connect/src/app/site/event/event.routes.ts`
- `apps/connect/src/app/cms/client/client-cms.routes.ts`
### Related but potentially separate
- `apps/connect/src/app/cms/event/components/reporting/<feature>-reporting/`
(reporting feature - may stay separate)
**Questions:**
1. Should all components be moved to new libraries?
2. Should the store be extracted or stay in existing library?
3. Should reporting components be included or remain separate?
Ask user to confirm the domain name for the new libraries:
<feature> or <feature>-<qualifier>libs/connect/Structure commits in logical, reviewable chunks. Each commit should be atomic and build on the previous.
Extract shared types first
Extract shared <Domain> types to shared domain library
libs/connect/shared/<domain>/domain/Create domain libraries for CMS/UFA-specific types
Add <Domain> domain libraries for CMS and UFA
libs/connect/cms/<domain>/domain/libs/connect/ufa/<domain>/domain/Move stores and API clients
Move <Domain> stores to Nx data-access libraries
Move components
Move <Domain> components to Nx feature libraries
Rename files and selectors to match conventions
Rename <Domain> files, components, and selectors
my-component.ts → ufa-<domain>-my-component.tsco-my-component → co-ufa-<domain>-my-componentAdd metadata and cleanup
Add tech-debt tags to <Domain> libraries
project.jsonfeat:, fix:, etc.)Based on discovery phase, identify what code moves where:
libs/connect/shared/<domain>/domain/libs/connect/cms/<domain>/feature/libs/connect/cms/<domain>/data-access/libs/connect/ufa/<domain>/feature/libs/connect/ufa/<domain>/data-access/cd Connect/ng-app-monolith
# Create domain libraries for types
yarn exec nx g @consensus/nx:angular-library --product=connect --application=shared --domain=<domain> --type=domain
yarn exec nx g @consensus/nx:angular-library --product=connect --application=cms --domain=<domain> --type=domain
yarn exec nx g @consensus/nx:angular-library --product=connect --application=ufa --domain=<domain> --type=domain
# Create data-access libraries for stores/clients
yarn exec nx g @consensus/nx:angular-library --product=connect --application=cms --domain=<domain> --type=data-access
yarn exec nx g @consensus/nx:angular-library --product=connect --application=ufa --domain=<domain> --type=data-access
# Create feature libraries for components
yarn exec nx g @consensus/nx:angular-library --product=connect --application=cms --domain=<domain> --type=feature
yarn exec nx g @consensus/nx:angular-library --product=connect --application=ufa --domain=<domain> --type=feature
Naming conventions:
cms-<domain>-<name>.component.tsufa-<domain>-<name>.component.ts<application>-<domain>.store.ts<application>-<domain>.client.ts<application>-<domain>.model.ts or shared-<domain>.types.tsSelector prefixes:
co-cms-<domain>-co-ufa-<domain>-Shared types (in shared/<domain>/domain/):
CMS-specific types (in cms/<domain>/domain/):
locked, distribution)UFA-specific types (in ufa/<domain>/domain/):
Omit<SharedType, 'adminField'> to hide admin-only fieldsExample type separation:
// shared-certification-rubrics.types.ts
export interface CertificationsQuestionnaire {
id: string;
title: string;
locked: boolean; // Admin-only concept
// ...
}
// ufa-certification-rubrics.model.ts
import { CertificationsQuestionnaire } from '@consensus/connect/shared/certification-rubrics/domain';
// Hide 'locked' from UFA consumers
export type ClientCertificationQuestionnaire = Omit<CertificationsQuestionnaire, 'locked'>;
In each library's index.ts:
// Only export public API
export * from './lib/<domain>.model';
export { MyComponent } from './lib/my-component/my-component.component';
Update consuming code:
// Before (relative import from app)
import { MyComponent } from './components/my-component/my-component.component';
// After (library import)
import { MyComponent } from '@consensus/connect/ufa/<domain>/feature';
Update route imports to use the new library paths:
// apps/connect/src/app/site/event/event.routes.ts
import {
ComponentA,
ComponentB,
} from '@consensus/connect/ufa/<domain>/feature';
If migrating legacy code with known issues, add appropriate tags in project.json:
{
"tags": [
"product:connect",
"application:ufa",
"domain:<domain>",
"type:feature",
"tech-debt:default-change-detection",
"tech-debt:lax-typing"
]
}
After migration:
apps/connect/Confirm tsconfig.base.json has the new path aliases:
{
"@consensus/connect/shared/<domain>/domain": ["libs/connect/shared/<domain>/domain/src/index.ts"],
"@consensus/connect/cms/<domain>/data-access": ["libs/connect/cms/<domain>/data-access/src/index.ts"],
"@consensus/connect/cms/<domain>/domain": ["libs/connect/cms/<domain>/domain/src/index.ts"],
"@consensus/connect/cms/<domain>/feature": ["libs/connect/cms/<domain>/feature/src/index.ts"],
"@consensus/connect/ufa/<domain>/data-access": ["libs/connect/ufa/<domain>/data-access/src/index.ts"],
"@consensus/connect/ufa/<domain>/domain": ["libs/connect/ufa/<domain>/domain/src/index.ts"],
"@consensus/connect/ufa/<domain>/feature": ["libs/connect/ufa/<domain>/feature/src/index.ts"]
}
# Build affected projects
yarn exec nx affected --targets=build --base=master
# Lint affected projects
yarn exec nx affected --targets=lint --base=master
# Run affected tests
yarn exec nx affected --targets=test --base=master
# Check for remaining feature code in app folder
find Connect/ng-app-monolith/apps/connect -type d -name "*<domain>*"
find Connect/ng-app-monolith/apps/connect -type f -name "*<domain>*"
# Check for old import paths still in use
grep -r "from '\.\./.*<domain>" Connect/ng-app-monolith/apps/connect --include="*.ts"
See branch Abildtoft/wan-148-impl for a complete example of migrating Certification Rubrics from apps/connect/ into proper Nx libraries.
tools
Requires Linear MCP. Implements one Linear issue end to end, selects applicable code-review, convention, and PR-refactor gates, runs them to bounded convergence, verifies, and optionally opens the PR and iterates on CI and review feedback until green. Use when the user wants a single Linear issue taken from implementation through a clean Pull Request. Not for implementation-only work, SIW-tracked issues, stacked PRs, existing PR updates, or post-merge rollout.
development
Reviews PR and local changes for convention drift and overcaution against documented rules and mined peer-file practice. Use for new patterns, dependencies, abstractions, or defensive complexity that departs from established practice; every finding cites evidence. Supports --inline. Not for general code quality (use kramme:pr:code-review) or spec review (use kramme:siw:spec-audit --team).
testing
Charts huge or foggy initiatives into a local `.context` decision map and resolves one typed frontier ticket per session until the work is ready for SIW or another execution workflow. Use when the route to a destination cannot fit in one agent session or parallel workspaces need coordinated planning state. Not for clear specs, ordinary issue decomposition, implementation, or Linear-native tracking.
development
Investigates a question against primary sources and saves one cited Markdown artifact. Use for reading legwork: official docs/API facts, source-code or spec checks, standards, and first-party service behavior before planning or implementation. Not for making product or architecture decisions, implementing code, broad web search, secondary blog summaries, or uncited answers.