Skip to content

Instantly share code, notes, and snippets.

@LayZeeDK
Created December 22, 2025 20:25
Show Gist options
  • Select an option

  • Save LayZeeDK/706d4652293a91a1affdc025da71d0ee to your computer and use it in GitHub Desktop.

Select an option

Save LayZeeDK/706d4652293a91a1affdc025da71d0ee to your computer and use it in GitHub Desktop.
Storybook 10 + Angular 21 Signals + Nx 22 autodocs compodoc setup

Storybook 10 Autodocs with Compodoc for Angular Signal Components

A guide for configuring Storybook 10 to automatically extract JSDoc documentation from Angular components that use signal-based inputs (input()) in an Nx workspace.

Overview

Storybook's Autodocs feature generates documentation pages automatically from your component code. For Angular, this requires Compodoc to extract JSDoc comments, component metadata, and input/output definitions.

Key Challenge: Angular's signal-based inputs (input(), output(), model()) require proper Compodoc configuration to extract JSDoc descriptions into Storybook's Controls panel.


Prerequisites

  • Nx workspace with Angular
  • Storybook 10+ configured for Angular
  • @storybook/addon-docs installed

Step 1: Install Dependencies

npm install -D @storybook/addon-docs @compodoc/compodoc

Step 2: Configure Storybook Addons

File: packages/your-library/.storybook/main.ts

import type { StorybookConfig } from '@storybook/angular';

const config: StorybookConfig = {
  stories: ['../**/*.@(mdx|stories.@(js|jsx|ts|tsx))'],
  addons: ['@storybook/addon-docs'],
  framework: {
    name: '@storybook/angular',
    options: {},
  },
};

export default config;

Step 3: Configure Compodoc in Nx Project

File: packages/your-library/project.json

The critical configuration is in compodocArgs. You MUST include the -p flag pointing to your library's tsconfig:

{
  "targets": {
    "storybook": {
      "executor": "@storybook/angular:start-storybook",
      "options": {
        "port": 4400,
        "configDir": "packages/your-library/.storybook",
        "browserTarget": "your-library:build-storybook",
        "compodoc": true,
        "compodocArgs": [
          "-p",
          "packages/your-library/tsconfig.lib.json",
          "-e",
          "json",
          "-d",
          "packages/your-library"
        ]
      }
    },
    "build-storybook": {
      "executor": "@storybook/angular:build-storybook",
      "outputs": ["{options.outputDir}", "{projectRoot}/documentation.json"],
      "options": {
        "outputDir": "dist/storybook/your-library",
        "configDir": "packages/your-library/.storybook",
        "browserTarget": "your-library:build-storybook",
        "compodoc": true,
        "compodocArgs": [
          "-p",
          "packages/your-library/tsconfig.lib.json",
          "-e",
          "json",
          "-d",
          "packages/your-library"
        ]
      }
    }
  }
}

Compodoc Arguments Explained

Argument Purpose
-p <tsconfig> Required. Points to the tsconfig that includes your component files. Without this, Compodoc won't find your components.
-e json Output format as JSON (required for Storybook integration)
-d <directory> Output directory for documentation.json

Important: Add to Nx Outputs

Add {projectRoot}/documentation.json to the outputs array of build-storybook to ensure Nx caching works correctly and doesn't serve stale documentation.


Step 4: Configure Storybook Preview

File: packages/your-library/.storybook/preview.ts

import type { Preview } from '@storybook/angular';
import { setCompodocJson } from '@storybook/addon-docs/angular';
import docJson from '../documentation.json';

// Load Compodoc documentation into Storybook
setCompodocJson(docJson);

const preview: Preview = {
  tags: ['autodocs'], // Enable autodocs for all stories
};

export default preview;

Step 5: Update TypeScript Configuration

File: packages/your-library/.storybook/tsconfig.json

Enable resolveJsonModule to allow importing the Compodoc JSON:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "resolveJsonModule": true
  },
  "include": [
    "../src/**/*.stories.ts",
    "../documentation.json",
    "*.ts"
  ],
  "exclude": ["../**/*.spec.ts"]
}

Step 6: Add JSDoc to Component Inputs

File: your-component.ts

Add JSDoc comments directly above signal-based inputs:

import { Component, input, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'my-accordion',
  template: `...`,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyAccordion {
  /** Allow multiple panels to be expanded simultaneously */
  readonly multiExpandable = input(false);

  /** Disable all accordion interactions */
  readonly disabled = input(false);

  /** Animation duration in milliseconds for expand/collapse transitions */
  readonly slideSpeed = input(250);

  /** Link the location hash to the open pane */
  readonly deepLink = input(false);
}

Step 7: Configure Stories with Component Reference

File: your-component.stories.ts

The component property is required to connect Storybook with Compodoc documentation:

import type { Meta, StoryObj } from '@storybook/angular';
import { MyAccordion } from './accordion';

const meta: Meta<MyAccordion> = {
  title: 'Components/Accordion',
  component: MyAccordion,  // Required for Compodoc integration
  tags: ['autodocs'],
};

export default meta;
type Story = StoryObj<MyAccordion>;

export const Default: Story = {
  args: {
    multiExpandable: false,
    disabled: false,
    slideSpeed: 250,
  },
};

Key Points

  1. Use Meta<YourComponent> - Reference the component class, not an interface
  2. Include component: YourComponent - This tells Storybook which component to look up in Compodoc's JSON

Step 8: Add documentation.json to .gitignore

File: .gitignore

# Compodoc generated documentation
**/documentation.json

This file is generated on every Storybook build and should not be committed.


Verification

  1. Delete any existing documentation.json to ensure fresh generation
  2. Run Storybook: npm run storybook
  3. Check the Controls panel - JSDoc descriptions should appear in the Description column
  4. Verify documentation.json contains your component with inputsClass populated:
{
  "components": [
    {
      "name": "MyAccordion",
      "inputsClass": [
        {
          "name": "multiExpandable",
          "description": "<p>Allow multiple panels to be expanded simultaneously</p>\n",
          "defaultValue": "false"
        }
      ]
    }
  ]
}

Troubleshooting

Problem: Empty "components": [] in documentation.json

Cause: Compodoc can't find your component files.

Solution: Ensure -p flag points to the correct tsconfig that includes your source files:

"compodocArgs": [
  "-p",
  "packages/your-library/tsconfig.lib.json",  // Must include src/**/*.ts
  "-e",
  "json",
  "-d",
  "packages/your-library"
]

Problem: Descriptions show only types (e.g., "boolean") not JSDoc text

Cause: Missing component property in story meta.

Solution: Add component: YourComponent to the meta object:

const meta: Meta<MyComponent> = {
  title: 'Components/MyComponent',
  component: MyComponent,  // Add this line
  // ...
};

Problem: Stale documentation after code changes

Cause: Nx caching serving old documentation.json.

Solution: Add to outputs in build-storybook target:

"outputs": ["{options.outputDir}", "{projectRoot}/documentation.json"]

Problem: Cannot find module '../documentation.json'

Cause: resolveJsonModule not enabled or file not in include.

Solution: Update .storybook/tsconfig.json:

{
  "compilerOptions": {
    "resolveJsonModule": true
  },
  "include": ["../documentation.json"]
}

Summary

The key configuration points for Storybook 10 + Compodoc + Angular Signal Inputs:

Configuration Location Purpose
-p <tsconfig> compodocArgs in project.json Tells Compodoc where to find components
setCompodocJson() preview.ts Loads documentation into Storybook
component: X Story meta Links story to Compodoc component entry
resolveJsonModule .storybook/tsconfig.json Allows JSON import
outputs array build-storybook target Prevents Nx cache issues

With these configurations, JSDoc comments on input(), output(), and model() signal-based APIs will automatically appear in Storybook's Controls panel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment