Angular - Set up Compodoc for Storybook on Nx

Last updated: July 8, 2026

Compodoc is a documentation tool for Angular applications. When used with Storybook, Compodoc can automatically generate documentation for your Angular components by analyzing their TypeScript code, decorators, and JSDoc comments.

What is compodoc?

Compodoc automatically generates documentation by:

  • Analyzing TypeScript interfaces and classes
  • Reading Angular decorators (@Input, @Output, etc.)
  • Parsing JSDoc comments
  • Generating argTypes for Storybook controls

Setting up Compodoc with Storybook

Prerequisites

You need to have Storybook already configured for your Angular project. If you haven't set up Storybook yet, follow the Angular Storybook setup guide.

Install compodoc

Install Compodoc as a dev dependency:

npm install --save-dev @compodoc/compodoc

Configure Compodoc in your Storybook

Add Compodoc configuration to your Storybook's main.ts file:

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

const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
  addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'],
  framework: {
    name: '@storybook/angular',
    options: {},
  },
  typescript: {
    check: false,
    checkOptions: {},
    reactDocgen: 'react-docgen-typescript',
    reactDocgenTypescriptOptions: {
      shouldExtractLiteralValuesFromEnum: true,
      propFilter: (prop) =>
        prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
      compilerOptions: {
        allowSyntheticDefaultImports: false,
        esModuleInterop: false,
      },
    },
  },
  docs: {
    autodocs: true,
  },
};

export default config;

Generate compodoc documentation

Add a script to your package.json to generate Compodoc documentation:

// package.json
{
  "scripts": {
    "docs:json": "compodoc -p tsconfig.json -e json -d .",
    "storybook": "npm run docs:json && nx storybook your-project"
  }
}

Configure your Angular component for better documentation

Add JSDoc comments and use TypeScript interfaces for better documentation generation:

// button.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

export interface ButtonProps {
  /** The button label */
  label: string;
  /** Primary or secondary styling */
  primary?: boolean;
  /** Disabled state */
  disabled?: boolean;
  /** Button size */
  size?: 'small' | 'medium' | 'large';
}

/**
 * A customizable button component
 */
@Component({
  selector: 'app-button',
  template: `
    <button
      [class]="classes"
      [disabled]="disabled"
      (click)="onClick.emit($event)"
    >
      {{ label }}
    </button>
  `,
  styleUrls: ['./button.component.css'],
})
export class ButtonComponent implements ButtonProps {
  /** The button label */
  @Input() label: string = '';

  /** Primary or secondary styling */
  @Input() primary: boolean = false;

  /** Disabled state */
  @Input() disabled: boolean = false;

  /** Button size */
  @Input() size: 'small' | 'medium' | 'large' = 'medium';

  /** Click event handler */
  @Output() onClick = new EventEmitter<Event>();

  get classes(): string {
    return [
      'btn',
      this.primary ? 'btn-primary' : 'btn-secondary',
      `btn-${this.size}`,
    ].join(' ');
  }
}

Enhanced story with Compodoc integration

Create a story that leverages the Compodoc-generated documentation:

// button.stories.ts
import type { Meta, StoryObj } from '@storybook/angular';
import { ButtonComponent } from './button.component';

const meta: Meta<ButtonComponent> = {
  title: 'Components/Button',
  component: ButtonComponent,
  parameters: {
    docs: {
      description: {
        component:
          'A customizable button component with multiple variants and sizes.',
      },
    },
  },
  argTypes: {
    size: {
      control: { type: 'select' },
      options: ['small', 'medium', 'large'],
    },
    onClick: { action: 'clicked' },
  },
};

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

export const Primary: Story = {
  args: {
    primary: true,
    label: 'Primary Button',
    size: 'medium',
  },
};

export const Secondary: Story = {
  args: {
    primary: false,
    label: 'Secondary Button',
    size: 'medium',
  },
};

export const Large: Story = {
  args: {
    label: 'Large Button',
    size: 'large',
  },
};

export const Small: Story = {
  args: {
    label: 'Small Button',
    size: 'small',
  },
};

export const Disabled: Story = {
  args: {
    label: 'Disabled Button',
    disabled: true,
  },
};

Benefits of using Compodoc with Storybook

  1. Automatic Documentation: Compodoc generates component documentation automatically from your TypeScript code
  2. Better Controls: Enhanced Storybook controls based on your component's @Input properties
  3. Type Safety: Leverages TypeScript types for accurate documentation
  4. JSDoc Integration: Uses JSDoc comments for rich descriptions
  5. Less Maintenance: Documentation stays in sync with your code

Running Storybook with compodoc

With the setup complete, run your Storybook:

npm run storybook

This will generate the Compodoc documentation and then start Storybook with enhanced documentation for your Angular components.