Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions skills/dev-skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The Angular skills are designed to help coding agents create applications aligne
## Available Skills

- **`angular-developer`**: Generates Angular code and provides architectural guidance. Useful for creating components, services, or obtaining best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling, testing, or CLI tooling.
- **`angular-library`**: Guides the creation, build, and publishing of Angular libraries. Covers ng-packagr, secondary entry points, public API surface, library testing, schematics (`ng add`, `ng generate`), and publishing to npm.
- **`angular-new-app`**: Creates a new Angular app using the Angular CLI. Provides important guidelines for effectively setting up and structuring a modern Angular application.

## Using Agent Skills
Expand Down
56 changes: 56 additions & 0 deletions skills/dev-skills/angular-library/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: angular-library
description: Guide for creating, building, and publishing Angular libraries. Trigger when working with ng-packagr, secondary entry points, public API surface, schematics, or publishing to npm.
license: MIT
metadata:
author: Copyright 2026 Google LLC
version: '1.0'
---

# Angular Library Guidelines

1. Always analyze the Angular version of the workspace before providing guidance, as library APIs and tooling may differ between versions.

2. Angular libraries are built with **ng-packagr** via the Angular CLI. Follow the Angular Package Format (APF) to ensure compatibility with downstream consumers.

3. After generating or modifying library code, run `ng build <library-name>` to confirm there are no build errors before proceeding.

4. Libraries must never import from the consuming application — they must be self-contained.

## Creating a New Library

When creating a new Angular library inside a workspace, consult the following reference:

- **Creating a Library**: Generating the library, workspace structure, and `ng-package.json`. Read [creating-library.md](references/creating-library.md)

## Public API Surface

Managing what consumers can import from your library is critical. Consult:

- **Public API**: Exporting symbols via `public-api.ts` and controlling the library's API surface. Read [public-api.md](references/public-api.md)

## Secondary Entry Points

When a library is large enough to benefit from tree-shakable sub-packages (e.g. `@my-lib/testing`), consult:

- **Secondary Entry Points**: Defining multiple entry points and their constraints. Read [secondary-entrypoints.md](references/secondary-entrypoints.md)

## Build and Packaging

For configuration of the build pipeline and output format:

- **ng-packagr**: Understanding `ng-package.json`, compilation output (ESM), and peer dependencies. Read [ng-packagr.md](references/ng-packagr.md)

## Publishing to npm

When preparing a library for distribution:

- **Publishing to npm**: Versioning, `peerDependencies`, `npm publish`, and automation. Read [publishing-npm.md](references/publishing-npm.md)

## Schematics

To provide `ng add` or `ng generate` commands for library consumers:

- **Schematics**: Adding Angular schematics to a library for code generation and automated setup. Read [schematics.md](references/schematics.md)

If you need deeper documentation, refer to the [official Angular Libraries guide](https://angular.dev/tools/libraries).
164 changes: 164 additions & 0 deletions skills/dev-skills/angular-library/references/creating-library.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Creating an Angular Library

## Overview

An Angular library is a reusable Angular project that can be shared across multiple Angular applications or published to npm.

Libraries are created inside an Angular **workspace** (a project created with `ng new`).

---

## Generating a Library

Use the Angular CLI to generate a library. It is common to create a dedicated workspace without an initial application:

```bash
ng new my-workspace --no-create-application
cd my-workspace
ng generate library my-lib
```

Or with a scope:

```bash
ng generate library @my-org/my-lib
```

This creates the following structure in the workspace:

```
my-workspace/
├── projects/
│ └── my-lib/
│ ├── src/
│ │ ├── lib/
│ │ │ ├── my-lib.ts
│ │ │ ├── my-lib.service.ts
│ │ │ └── my-lib.spec.ts
│ │ └── public-api.ts ← controls what consumers can import
│ ├── ng-package.json ← ng-packagr configuration
│ ├── package.json
│ └── tsconfig.lib.json
├── angular.json
└── tsconfig.json
```

---

## Building the Library

Build the library before using it locally or publishing:

```bash
ng build my-lib
```

The output is placed in `dist/my-lib/` by default.

> **Path Mapping Warning:** An application that depends on a library should only use TypeScript path mappings that point to the _built library_ in the `dist/` folder. Path mappings should **not** point to the library source `.ts` files, because the build systems are different (`esbuild` for applications vs `ng-packagr` for libraries).

---

## Using the Library in the Same Workspace

After building, Angular automatically configures path mappings in `tsconfig.json` so the consuming app can import from the library by name:

```ts
import {MyLib} from 'my-lib';
```

For **development without rebuilding on every change**, use the `--watch` flag:

```bash
ng build my-lib --watch
```

---

## Key Files Explained

### `ng-package.json`

Configures the ng-packagr build:

```json
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "src/public-api.ts"
}
}
```

### `public-api.ts`

The single entry point defining the library's public surface. See [public-api.md](public-api.md).

### `package.json`

Defines the library's name, version, and `peerDependencies`. See [publishing-npm.md](publishing-npm.md).

---

## Scaffolding Inside the Library

After generating the library, use the CLI to add components, services, and other artifacts scoped to it:

```bash
ng generate component my-component --project=my-lib
ng generate service my-service --project=my-lib
ng generate directive my-directive --project=my-lib
ng generate pipe my-pipe --project=my-lib
```

> **Note:** By default in modern Angular versions, `ng generate component` creates **standalone** components. This is the recommended pattern for libraries as well, avoiding the need for internal `NgModule`s.

---

> Libraries cannot use browser-specific APIs directly in their module code if you intend to support SSR consumers. Use `isPlatformBrowser` or inject `PLATFORM_ID` where needed.

---

## Refactoring Applications into Libraries

When moving application code into a library to make it reusable:

- **Stateless Components:** Components and pipes should be stateless. Avoid relying on external application-specific state.
- **Tree-Shakable Providers:** Services should use `providedIn: 'root'` instead of being declared in `NgModule` providers so they can be tree-shaken by consumers.
- **Lightweight Tokens:** For optional services, use the lightweight injection token pattern to ensure the library doesn't drag in unnecessary dependencies.

---

## Linking Libraries for Local Development

To test a standalone library with an external application during local development (without publishing to npm or using a monorepo), use `npm link` or `pnpm link`.

You must configure the **consuming application's** `angular.json` to properly handle the symlinks:

```json
{
"projects": {
"your-app": {
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"preserveSymlinks": true
}
},
"serve": {
"builder": "@angular/build:dev-server",
"options": {
"prebundle": {
"exclude": ["my-lib"]
}
}
}
}
}
}
}
```

- `preserveSymlinks: true` prevents multiple copies of dependencies.
- `prebundle.exclude` ensures Vite does not cache the linked library, allowing it to be rebuilt when changes occur.
129 changes: 129 additions & 0 deletions skills/dev-skills/angular-library/references/ng-packagr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# ng-packagr and the Angular Package Format

## Overview

**ng-packagr** is the build tool used by the Angular CLI to compile Angular libraries into the **Angular Package Format (APF)**, which is the standard format for distributing Angular libraries on npm.

---

## `ng-package.json`

The `ng-package.json` file at the root of your library configures the ng-packagr build:

```json
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "src/public-api.ts"
},
"assets": ["./styles/**/*.scss", "./themes/**/*.css"]
}
```

### Key Options

| Option | Description |
| ---------------- | -------------------------------------------------------------------- |
| `lib.entryFile` | Path to the public API file (required) |
| `assets` | Files to copy to the dist folder (e.g. styles, themes) |
| `deleteDestPath` | Whether to clean the output directory before build (default: `true`) |
| `dest` | Custom output directory (defaults to `dist/<library-name>`) |

---

## Angular Package Format (APF)

ng-packagr produces an output conforming to the APF. The key outputs are:

| File / Folder | Purpose |
| -------------- | -------------------------------------------- |
| `esm2022/` | ES Modules (tree-shakable, used by bundlers) |
| `fesm2022/` | Flattened ESM (single file, fewer imports) |
| `*.d.ts` | TypeScript type declarations |
| `*.d.ts.map` | Declaration source maps |
| `package.json` | npm package descriptor with `exports` field |

Modern bundlers (Webpack, esbuild, Rollup) resolve the `exports` field in `package.json` to pick the right format automatically.

---

## `peerDependencies`

Libraries should **not** bundle Angular itself. Instead, declare Angular as a peer dependency in the library's `package.json`:

```json
{
"name": "my-lib",
"version": "1.0.0",
"peerDependencies": {
"@angular/core": ">=19.0.0",
"@angular/common": ">=19.0.0"
},
"dependencies": {}
}
```

### Rules for `peerDependencies`

- Declare all `@angular/*` packages your library imports as `peerDependencies`.
- Use `>=` version ranges to stay compatible with future Angular versions.
- Only add to `dependencies` packages that are not expected to be installed by the consumer (rare for Angular libs).
- Never put `@angular/core` or `rxjs` in `dependencies`.

---

## Enabling CSS / SCSS Compilation

For libraries that ship styles, ng-packagr can compile SCSS to CSS. Reference them in component metadata:

```ts
@Component({
selector: 'my-button',
templateUrl: './my-button.html',
styleUrl: './my-button.component.scss',
})
export class MyButton {}
```

To ship **global styles or themes** (not scoped to a component), list them in `ng-package.json` under `assets`.

### Exposing Assets via Package Exports

When including additional assets like Sass mixins or pre-compiled CSS, you must manually add these to the conditional `"exports"` in the primary `package.json` of your library.

`ng-packagr` merges these handwritten `"exports"` with the auto-generated ones, allowing you to configure custom export subpaths:

```json
"exports": {
".": {
"sass": "./_index.scss",
},
"./theming": {
"sass": "./_theming.scss"
},
"./prebuilt-themes/indigo-pink.css": {
"style": "./prebuilt-themes/indigo-pink.css"
}
}
```

---

## Preserving Comments for API Documentation

ng-packagr strips most comments by default. To preserve JSDoc comments for API documentation tools (e.g., Compodoc, TypeDoc), they must be attached directly above exported symbols and follow the JSDoc format:

```ts
/**
* A button component with Angular Aria support.
*
* @example
* <my-button variant="primary">Click me</my-button>
*/
@Component({...})
export class MyButtonComponent {}
```

---

> Do not manually edit the files inside `dist/`. They are generated artifacts and will be overwritten on every build.
Loading
Loading