---
name: library-scaffolder
description: This skill should be used when creating feature/data-access/ui/util libraries or user says "create library", "new library", "scaffold library". Creates new Angular libraries in ISA-Frontend monorepo with proper Nx configuration, Vitest setup, architectural tags, and path aliases.
---

# Library Scaffolder

## Overview

Automate the creation of new Angular libraries following ISA-Frontend conventions. This skill handles the complete scaffolding workflow including Nx generation, Vitest configuration with CI/CD integration, path alias verification, and initial validation.

## When to Use This Skill

Invoke this skill when:
- User requests creating a new library
- User mentions "new library", "scaffold library", or "create feature"
- User wants to add a new domain/layer/feature to the monorepo

## Required Parameters

User must provide:
- **domain**: Domain name (oms, remission, checkout, ui, core, shared, utils)
- **layer**: Layer type (feature, data-access, ui, util)
- **name**: Library name in kebab-case

## Scaffolding Workflow

### Step 1: Validate Input

1. **Verify Domain**
   - Use `docs-researcher` to check `docs/library-reference.md`
   - Ensure domain follows existing patterns

2. **Validate Layer**
   - Must be one of: feature, data-access, ui, util

3. **Check Name**
   - Must be kebab-case
   - Must not conflict with existing libraries

4. **Determine Path Depth**
   - 3 levels: `libs/domain/layer/name` → `../../../`
   - 4 levels: `libs/domain/type/layer/name` → `../../../../`

### Step 2: Run Dry-Run

Execute Nx generator with `--dry-run`:

```bash
npx nx generate @nx/angular:library \
  --name=[domain]-[layer]-[name] \
  --directory=libs/[domain]/[layer]/[name] \
  --importPath=@isa/[domain]/[layer]/[name] \
  --prefix=[domain] \
  --style=css \
  --unitTestRunner=vitest \
  --standalone=true \
  --skipTests=false \
  --dry-run
```

Review output with user before proceeding.

### Step 3: Generate Library

Execute without `--dry-run`:

```bash
npx nx generate @nx/angular:library \
  --name=[domain]-[layer]-[name] \
  --directory=libs/[domain]/[layer]/[name] \
  --importPath=@isa/[domain]/[layer]/[name] \
  --prefix=[domain] \
  --style=css \
  --unitTestRunner=vitest \
  --standalone=true \
  --skipTests=false
```

### Step 4: Add Architectural Tags

**CRITICAL**: Immediately after library generation, add proper tags to `project.json` for `@nx/enforce-module-boundaries`.

Run the tagging script:
```bash
node scripts/add-library-tags.js
```

Or manually add tags to `libs/[domain]/[layer]/[name]/project.json`:

```json
{
  "name": "[domain]-[layer]-[name]",
  "tags": [
    "scope:[domain]",
    "type:[layer]"
  ]
}
```

**Tag Rules:**
- **Scope tag**: `scope:[domain]` (e.g., `scope:oms`, `scope:crm`, `scope:ui`, `scope:shared`)
- **Type tag**: `type:[layer]` (e.g., `type:feature`, `type:data-access`, `type:ui`, `type:util`)

**Examples:**
- `libs/oms/feature/return-search` → `["scope:oms", "type:feature"]`
- `libs/ui/buttons` → `["scope:ui", "type:ui"]`
- `libs/shared/scanner` → `["scope:shared", "type:shared"]`
- `libs/core/auth` → `["scope:core", "type:core"]`

**Verification:**
```bash
# Check tags were added
cat libs/[domain]/[layer]/[name]/project.json | jq '.tags'

# Should output: ["scope:[domain]", "type:[layer]"]
```

### Step 5: Configure Vitest with JUnit and Cobertura

Update `libs/[path]/vite.config.mts`:

```typescript
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import angular from '@analogjs/vite-plugin-angular';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';

export default
// @ts-expect-error - Vitest reporter tuple types have complex inference issues
defineConfig(() => ({
  root: __dirname,
  cacheDir: '../../../node_modules/.vite/libs/[path]',
  plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
  test: {
    watch: false,
    globals: true,
    environment: 'jsdom',
    include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
    setupFiles: ['src/test-setup.ts'],
    reporters: [
      'default',
      ['junit', { outputFile: '../../../testresults/junit-[library-name].xml' }],
    ],
    coverage: {
      reportsDirectory: '../../../coverage/libs/[path]',
      provider: 'v8' as const,
      reporter: ['text', 'cobertura'],
    },
  },
}));
```

**Critical**: Adjust path depth based on library location.

### Step 6: Verify Configuration

1. **Check Path Alias**
   - Verify `tsconfig.base.json` was updated
   - Should have: `"@isa/[domain]/[layer]/[name]": ["libs/[domain]/[layer]/[name]/src/index.ts"]`

2. **Run Initial Test**
   ```bash
   npx nx test [library-name] --coverage.enabled=true --skip-nx-cache
   ```

3. **Verify CI/CD Files Created**
   - JUnit XML: `testresults/junit-[library-name].xml`
   - Cobertura XML: `coverage/libs/[path]/cobertura-coverage.xml`

### Step 7: Create Library README

Use `docs-researcher` to find similar library READMEs, then create comprehensive documentation including:
- Overview and purpose
- Installation/import instructions
- API documentation
- Usage examples
- Testing information (Vitest + Angular Testing Utilities)

### Step 8: Update Library Reference

Add entry to `docs/library-reference.md` under appropriate domain:

```markdown
#### `@isa/[domain]/[layer]/[name]`
**Path:** `libs/[domain]/[layer]/[name]`
**Type:** [Feature/Data Access/UI/Util]
**Testing:** Vitest

[Brief description]
```

### Step 9: Run Full Validation

```bash
# Lint (includes boundary checks)
npx nx lint [library-name]

# Test with coverage
npx nx test [library-name] --coverage.enabled=true --skip-nx-cache

# Build (if buildable)
npx nx build [library-name]

# Dependency graph
npx nx graph --focus=[library-name]
```

### Step 10: Generate Creation Report

```
Library Created Successfully
============================

Library Name: [domain]-[layer]-[name]
Path: libs/[domain]/[layer]/[name]
Import Alias: @isa/[domain]/[layer]/[name]

✅ Configuration
----------------
Test Framework: Vitest with Angular Testing Utilities
Style: CSS
Standalone: Yes
Tags: scope:[domain], type:[layer]
JUnit Reporter: ✅ testresults/junit-[library-name].xml
Cobertura Coverage: ✅ coverage/libs/[path]/cobertura-coverage.xml

📦 Import Statement
-------------------
import { Component } from '@isa/[domain]/[layer]/[name]';

🧪 Test Commands
----------------
npx nx test [library-name] --skip-nx-cache
npx nx test [library-name] --coverage.enabled=true --skip-nx-cache

🏗️ Architecture Compliance
--------------------------
Tags enforce module boundaries via @nx/enforce-module-boundaries
Run lint to check for violations: npx nx lint [library-name]

📝 Next Steps
-------------
1. Develop library features
2. Write tests using Vitest + Angular Testing Utilities
3. Add E2E attributes (data-what, data-which) to templates
4. Update README with usage examples
5. Follow architecture rules (see eslint.config.js for constraints)
```

## Error Handling

**Issue: Path depth mismatch**
- Count directory levels from workspace root
- Adjust `../` in outputFile and reportsDirectory

**Issue: TypeScript errors in vite.config.mts**
- Add `// @ts-expect-error` before `defineConfig()`

**Issue: Path alias not working**
- Check tsconfig.base.json
- Run `npx nx reset`
- Restart TypeScript server

## References

- docs/guidelines/testing.md (Vitest, JUnit, Cobertura sections)
- docs/library-reference.md (domain patterns)
- CLAUDE.md (Library Organization, Testing Framework sections)
- eslint.config.js (@nx/enforce-module-boundaries configuration)
- scripts/add-library-tags.js (automatic tagging script)
- .claude/skills/architecture-enforcer (boundary validation)
- Nx Angular Library Generator: https://nx.dev/nx-api/angular/generators/library
- Nx Enforce Module Boundaries: https://nx.dev/nx-api/eslint-plugin/documents/enforce-module-boundaries
