Claude-skill-registry kramme:connect-extract-to-nx-libraries
Use this Skill when working in the Connect monorepo and needing to extract app code into proper Nx libraries.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/kramme-connect-extract-to-nx-libraries" ~/.claude/skills/majiayu000-claude-skill-registry-kramme-connect-extract-to-nx-libraries-283f49 && rm -rf "$T"
skills/data/kramme-connect-extract-to-nx-libraries/SKILL.mdExtract Connect App Code to Nx Libraries
Migrate code from the Connect app folder (
apps/connect/) into proper Nx libraries following established conventions.
When to Use
- Moving feature code from
toapps/connect/src/app/libs/ - Extracting shared types, components, or services into reusable libraries
- Refactoring monolithic app code into domain-driven library structure
Library Structure
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
Typical Feature Migration Structure
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
Discovery Phase (Required First Step)
Before planning the migration, discover ALL code related to the feature and confirm scope with the user.
1. Search for Feature-Related Code
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
2. Categorize Discovered Code
Organize findings into categories:
- Components (in
)apps/connect/src/app/- CMS components (admin-facing)
- UFA components (user-facing)
- Stores/Services (state management, API clients)
- Types/Models (interfaces, enums, DTOs)
- Routes (route definitions referencing components)
- Related but separate features (may share types but shouldn't be moved)
3. Present Findings and Ask User
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?
4. Confirm Domain Name
Ask user to confirm the domain name for the new libraries:
- Suggested:
or<feature><feature>-<qualifier> - Confirm it matches existing naming patterns in
libs/connect/
Git Commit Strategy
Structure commits in logical, reviewable chunks. Each commit should be atomic and build on the previous.
Recommended Commit Sequence
-
Extract shared types first
Extract shared <Domain> types to shared domain library- Create
libs/connect/shared/<domain>/domain/ - Move enums and base interfaces used by both CMS and UFA
- Update imports in existing code to use new library path
- Create
-
Create domain libraries for CMS/UFA-specific types
Add <Domain> domain libraries for CMS and UFA- Create
libs/connect/cms/<domain>/domain/ - Create
libs/connect/ufa/<domain>/domain/ - Move application-specific models and re-export shared types
- Create
-
Move stores and API clients
Move <Domain> stores to Nx data-access libraries- Create data-access libraries
- Move store files and API clients
- Update imports
-
Move components
Move <Domain> components to Nx feature libraries- Create feature libraries
- Move component files
- Update route imports
- Delete old component folders from app
-
Rename files and selectors to match conventions
Rename <Domain> files, components, and selectors- Rename files:
→my-component.tsufa-<domain>-my-component.ts - Update component selectors:
→co-my-componentco-ufa-<domain>-my-component - Update template references
- Rename files:
-
Add metadata and cleanup
Add tech-debt tags to <Domain> libraries- Add appropriate tech-debt tags to
project.json - Clean up any remaining old imports or exports
- Add appropriate tech-debt tags to
Commit Message Guidelines
- Use imperative mood: "Move components" not "Moved components"
- Keep first line short and descriptive
- No conventional commit prefixes (
,feat:
, etc.)fix: - No issue numbers in commit messages
Why This Order?
- Types first - Other code depends on types; moving them first prevents broken imports
- Data-access before feature - Components often depend on stores
- Rename last - Renaming is cosmetic; do functional moves first
- Metadata last - Tags and cleanup don't affect functionality
Migration Steps
1. Plan Library Structure
Based on discovery phase, identify what code moves where:
- Shared types →
libs/connect/shared/<domain>/domain/ - CMS components →
libs/connect/cms/<domain>/feature/ - CMS stores/clients →
libs/connect/cms/<domain>/data-access/ - UFA components →
libs/connect/ufa/<domain>/feature/ - UFA stores/clients →
libs/connect/ufa/<domain>/data-access/
2. Create Libraries Using Custom Generators
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
3. Move and Rename Files
Naming conventions:
- CMS components:
cms-<domain>-<name>.component.ts - UFA components:
ufa-<domain>-<name>.component.ts - Stores:
<application>-<domain>.store.ts - Clients:
<application>-<domain>.client.ts - Types:
or<application>-<domain>.model.tsshared-<domain>.types.ts
Selector prefixes:
- CMS:
co-cms-<domain>- - UFA:
co-ufa-<domain>-
4. Type Separation Best Practices
Shared types (in
shared/<domain>/domain/):
- Enums used by both CMS and UFA
- Base interfaces/types for entities
- Types that mirror backend DTOs
CMS-specific types (in
cms/<domain>/domain/):
- Admin-only fields (e.g.,
,locked
)distribution - CMS action models (Create, Update, Delete)
- Re-export shared types for convenience
UFA-specific types (in
ufa/<domain>/domain/):
- Use
to hide admin-only fieldsOmit<SharedType, 'adminField'> - Client-specific view models
- User-facing answer/response types
Example 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'>;
5. Update Imports and Exports
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';
6. Update Route Files
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';
7. Add Tech-Debt Tags
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" ] }
8. Clean Up Old Location
After migration:
- Delete the old component folders from
apps/connect/ - Remove old exports from app-level barrel files
- Update any remaining imports in the app
9. Verify Path Aliases
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"] }
Post-Migration Verification
1. Build and Test
# 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
2. Verify No Leftover Code
# 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"
3. Verify Routes Work
- Test CMS routes that use the migrated components
- Test UFA routes that use the migrated components
- Confirm lazy loading still works
Common Pitfalls
- Don't break circular dependencies - Ensure domain libs don't import from feature libs
- Don't duplicate types - Use re-exports in CMS/UFA domain libs for shared types
- Don't forget route updates - App routes must import from new library locations
- Don't mix concerns - Keep stores in data-access, components in feature, types in domain
- Don't over-export - Only export public API from library index.ts
- Don't move related but separate features - Reporting, analytics, etc. may share types but stay separate
Reference
See branch
Abildtoft/wan-148-impl for a complete example of migrating Certification Rubrics from apps/connect/ into proper Nx libraries.