https://github.com/anrouxel/storybook-addon-angular-manifest
https://github.com/anrouxel/storybook-addon-angular-manifest
Last synced: 5 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/anrouxel/storybook-addon-angular-manifest
- Owner: anrouxel
- License: mit
- Created: 2026-06-14T20:58:10.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-07-10T12:17:50.000Z (19 days ago)
- Last Synced: 2026-07-10T13:10:27.448Z (19 days ago)
- Language: TypeScript
- Size: 198 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-angular - storybook-addon-angular-manifest - A Storybook addon that builds an Angular component manifest from your stories and Compodoc documentation. (Development Utilities / Documentation Tools)
- fucking-awesome-angular - storybook-addon-angular-manifest - A Storybook addon that builds an Angular component manifest from your stories and Compodoc documentation. (Development Utilities / Documentation Tools)
README
# Storybook Addon Angular Manifest
[](https://www.npmjs.com/package/@anrouxel/storybook-addon-angular-manifest)
[](./LICENSE.md)
A Storybook addon that builds an **Angular component manifest** from your stories and [Compodoc](https://compodoc.app/) documentation. It plugs into Storybook's `experimental_manifests` API so tools like AI assistants and the [MCP](https://modelcontextprotocol.io/) server can understand your Angular component library: inputs, outputs, selectors, descriptions and ready-to-use template snippets.
## Features
- **Compodoc integration** — reads `documentation.json` and matches each story's component to its Compodoc entry to extract inputs, outputs, selector, standalone flag and change detection strategy.
- **Angular template snippets** — generates a `` snippet per story from the component's selector and args. When the selector has multiple comma-separated variants (e.g. `button[lib-btn], a[lib-btn]`), the first variant is used.
- **JSDoc tags** — parses `@summary`, `@describe`/`@desc` and other JSDoc tags from the story's `meta` or the story export itself.
- **`@useTemplate` opt-in** — use the story's `parameters.docs.source.code` (the same code Storybook's Docs "Show code" panel displays) as the snippet instead of the generated one, falling back to the story's `render` template if no `docs.source.code` is set.
- **Import statement resolution** — infers the import specifier for each component, preferring the nearest `package.json` name when the component belongs to a published package.
- **Works with `@storybook/angular` and `@storybook/angular-vite`.**
## Requirements
- Storybook `10.5.0` or later, with `experimental_manifests` support.
- [Compodoc](https://compodoc.app/) documentation generated for your Angular project. The easiest way is to enable it in your `angular.json` build target:
```json
{
"options": {
"compodoc": true
}
}
```
This produces a `documentation.json` file that the addon looks for at `documentation.json` or `.compodoc/documentation.json` relative to your Storybook working directory before Storybook starts.
Alternatively, generate it manually:
```bash
npx compodoc -p tsconfig.json
```
## Installation
```bash
npm install --save-dev @anrouxel/storybook-addon-angular-manifest
# or
pnpm add -D @anrouxel/storybook-addon-angular-manifest
# or
yarn add -D @anrouxel/storybook-addon-angular-manifest
```
Then register it in `.storybook/main.ts`, and enable Storybook's `componentsManifest` feature flag so the manifest is actually written out:
```ts
import type { StorybookConfig } from '@storybook/angular-vite';
const config: StorybookConfig = {
framework: '@storybook/angular-vite',
addons: ['@anrouxel/storybook-addon-angular-manifest'],
features: {
componentsManifest: true,
},
// ...
};
export default config;
```
Running `storybook build` then writes the manifest to `storybook-static/manifests/components.json`.
## How it works
For every story indexed by Storybook, the addon:
1. Resolves the story's `meta.component` and its import declaration to find the Angular component/directive class.
2. Looks it up in the Compodoc `documentation.json` (components, directives, pipes, injectables and classes are all searched).
3. Builds an Angular template snippet from the component's selector, its `inputsClass`/`outputsClass`, and the story's `args` — statically extracted from the story file's AST.
4. Extracts JSDoc metadata (`description`, `summary`, custom tags) from the story or component comment.
5. Assembles everything into a manifest entry served through Storybook's `experimental_manifests` mechanism.
When a component can't be resolved or isn't found in the Compodoc output, the entry still appears in the manifest with an `error` field explaining why (e.g. missing `meta.component`, or the class not covered by your `tsconfig.json`).
### Example output
Given this component and story:
```ts
@Component({
selector: 'app-button',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: '{{ label }}',
})
export class ButtonComponent {
/** Text displayed inside the button. */
@Input() label = 'Click me';
/** When true the button is non-interactive. */
@Input() disabled = false;
/** Emitted when the user clicks the button. */
@Output() clicked = new EventEmitter();
}
```
```ts
export const Primary: StoryObj = {
args: { label: 'Click me', disabled: false },
};
```
the addon generates a manifest entry like this (real output, generated by building this repo's own test Storybook against the snippet above):
```json
{
"id": "components-button",
"name": "ButtonComponent",
"path": "./src/button/button.stories.ts",
"stories": [
{
"id": "components-button--primary",
"name": "Primary",
"snippet": ""
}
],
"import": "import { ButtonComponent } from \"@my-org/my-lib\";",
"jsDocTags": {},
"description": "Primary UI component for user interaction.",
"compodoc": {
"name": "ButtonComponent",
"type": "component",
"selector": "app-button",
"standalone": true,
"changeDetection": "ChangeDetectionStrategy.OnPush",
"inputs": [
{ "name": "label", "type": "string", "optional": true, "defaultValue": "'Click me'", "description": "Text displayed inside the button." },
{ "name": "disabled", "type": "boolean", "optional": true, "defaultValue": "false", "description": "When true the button is non-interactive." }
],
"outputs": [
{ "name": "clicked", "type": "EventEmitter", "description": "Emitted when the user clicks the button." }
],
"description": "Primary UI component for user interaction."
},
"standalone": true,
"changeDetection": "ChangeDetectionStrategy.OnPush",
"selector": "app-button"
}
```
### Opting out of generated snippets
If a story already has the exact template you want exposed, tag it with `@useTemplate` and the addon will use that instead of generating one from the selector. It prefers `parameters.docs.source.code` — the same code Storybook's Docs "Show code" panel displays — and falls back to the story's `render` template when `docs.source.code` isn't set:
```ts
/**
* Uses the Docs "Show code" template instead of the Compodoc snippet.
* @useTemplate
*/
export const CustomTemplate: StoryObj = {
render: (_args) => ({
template: ``,
}),
parameters: {
docs: {
source: {
code: ``,
},
},
},
};
```
## API
The package also exposes its manifest type for consumers building on top of it:
```ts
import type { AngularComponentManifest } from '@anrouxel/storybook-addon-angular-manifest';
```
## Troubleshooting
**"No Compodoc documentation.json found"** — enable `compodoc: true` in your `angular.json` build options, or run `npx compodoc -p tsconfig.json` before starting Storybook.
**"We could not detect the component from your story file"** — make sure your story's default export sets `component` (e.g. `meta.component = ButtonComponent`).
**"\ was not found in the Compodoc documentation"** — check that the component's source file is included in the `tsconfig.json` used to generate Compodoc's documentation.
## Contributing
```bash
pnpm install
pnpm build # build the addon
pnpm test # run the test suite
pnpm check # lint with Biome
```
## License
[MIT](./LICENSE.md) © [Antonin Rouxel](https://github.com/anrouxel)