# How to get better documentation from Cursor

- Tool: Cursor
- Difficulty: Beginner
- Time required: 10-15 min
- Compatibility: Cursor Free+, TypeScript/JavaScript/Python
- Last updated: March 2026

## TL;DR

Cursor can generate rich documentation with UML-like class diagrams, relationship descriptions, and architectural notes embedded in docstrings when given explicit documentation rules. By adding documentation standards to .cursorrules and prompting Cursor to include class relationships, method flows, and dependency descriptions, you get self-documenting code that serves as both reference and architectural guide.

## Getting better documentation from Cursor

Most Cursor-generated code includes minimal or no documentation. By configuring documentation rules and using specific prompts, you can make Cursor produce detailed docstrings that include class relationships, method call flows, and Mermaid-compatible diagrams. This creates self-documenting code that helps new team members understand architecture without separate documentation.

## Before you start

- Cursor installed with a project containing complex classes
- Understanding of JSDoc or Python docstring formats
- Familiarity with Cursor Chat (Cmd+L) and Cmd+K
- Optional: Mermaid diagram renderer for previewing diagrams

## Step-by-step guide

### 1. Add documentation rules to .cursor/rules

Create rules that define your documentation standards. These rules tell Cursor what to include in every docstring it generates, from simple function descriptions to architectural context.

```
---
description: Documentation standards
globs: "src/**/*.ts"
alwaysApply: true
---

## Documentation Rules
- Every class must have a docstring with:
  - One-line summary
  - @description with purpose and architectural role
  - @relationships listing dependent and dependency classes
  - @example with basic usage
- Every public method must have:
  - @param for each parameter with type and purpose
  - @returns with type and description
  - @throws for each possible error
- For complex classes, include a Mermaid classDiagram in the docstring
- Use @see to reference related classes and modules
```

**Expected result:** Cursor generates detailed documentation following your standards for every class and method.

### 2. Generate a documented class with Cursor

Ask Cursor to generate a class with full documentation including relationships and a Mermaid diagram. Reference your rules and any related classes for accurate relationship mapping.

```
// Cursor Chat prompt (Cmd+L):
// @src/services/OrderService.ts @src/repositories/OrderRepository.ts
// @.cursor/rules/documentation.mdc
// Generate a PaymentService class that processes payments for orders.
// Include full JSDoc with Mermaid class diagram showing relationships
// to OrderService, PaymentGateway, and NotificationService.

/**
 * PaymentService — processes payments for customer orders.
 *
 * @description Handles payment processing, refunds, and payment
 * status tracking. Coordinates between the order service and
 * external payment gateway.
 *
 * @relationships
 * - Depends on: OrderService (order lookup), PaymentGateway (processing)
 * - Depended on by: OrderController, WebhookHandler
 * - Notifies: NotificationService (payment events)
 *
 * ```mermaid
 * classDiagram
 *   OrderController --> PaymentService
 *   PaymentService --> OrderService
 *   PaymentService --> PaymentGateway
 *   PaymentService --> NotificationService
 *   class PaymentService {
 *     +processPayment(orderId, amount)
 *     +refundPayment(paymentId)
 *     +getPaymentStatus(paymentId)
 *   }
 * ```
 */
```

> Pro tip: Mermaid diagrams in JSDoc comments render in VS Code with the Mermaid extension and in GitHub markdown previews.

**Expected result:** A fully documented class with relationship diagram, method descriptions, and architectural context.

### 3. Add documentation to existing classes with Cmd+K

Select an undocumented class, press Cmd+K, and ask Cursor to add comprehensive documentation. Reference related files so Cursor can accurately describe relationships.

```
// Select the class declaration, press Cmd+K:
// @src/services/OrderService.ts @src/repositories/UserRepository.ts
// Add comprehensive JSDoc documentation to this class.
// Include: summary, description with architectural role,
// relationships (depends on, depended on by), Mermaid class
// diagram, and @example usage. Document all public methods
// with @param, @returns, and @throws.
```

**Expected result:** Existing class receives complete documentation without modifying the implementation.

### 4. Generate a module-level architecture document

Use Cursor Chat to generate an overview document for an entire module. This creates a README-style docstring at the top of an index file that maps the entire module structure.

```
// Cursor Chat prompt (Cmd+L):
// @src/services/ Generate a module-level JSDoc comment for
// src/services/index.ts that documents:
// - All services in this directory and their purposes
// - The dependency graph between services
// - A Mermaid flowchart showing the service layer architecture
// - Which services are entry points vs internal

/**
 * @module services
 *
 * Service layer handling business logic.
 *
 * ```mermaid
 * flowchart TD
 *   OrderController --> OrderService
 *   OrderService --> PaymentService
 *   OrderService --> InventoryService
 *   PaymentService --> NotificationService
 *   InventoryService --> NotificationService
 * ```
 *
 * Entry points: OrderService, UserService, AuthService
 * Internal: NotificationService, InventoryService
 */
```

**Expected result:** A module-level documentation block with architecture diagram and service inventory.

### 5. Keep documentation updated as code changes

After modifying a class, ask Cursor to update the documentation to reflect the changes. This prevents documentation drift, which is the most common reason teams abandon docstrings.

```
// After adding a new method to PaymentService, press Cmd+K:
// "Update the JSDoc for this class to include the new
// refundPartial() method. Update the Mermaid diagram
// if any new relationships were added. Keep all existing
// documentation intact."
```

**Expected result:** Documentation updated to reflect new methods and relationships without losing existing content.

## Complete code example

File: `src/services/PaymentService.ts`

```typescript
/**
 * PaymentService — processes payments and manages refunds.
 *
 * @description Coordinates between order management, external payment
 * gateways, and notification delivery. Handles the full payment
 * lifecycle: authorization, capture, and refund.
 *
 * @relationships
 * - Depends on: IOrderService, IPaymentGateway, INotificationService
 * - Depended on by: OrderController, WebhookHandler, AdminPanel
 *
 * ```mermaid
 * classDiagram
 *   class PaymentService {
 *     -orderService: IOrderService
 *     -gateway: IPaymentGateway
 *     -notifications: INotificationService
 *     +processPayment(orderId, amount) Promise~Payment~
 *     +refundPayment(paymentId) Promise~Refund~
 *     +getStatus(paymentId) Promise~PaymentStatus~
 *   }
 *   PaymentService --> IOrderService
 *   PaymentService --> IPaymentGateway
 *   PaymentService --> INotificationService
 * ```
 *
 * @example
 * const payment = await paymentService.processPayment('order-123', 99.99);
 * console.log(payment.status); // 'captured'
 */

import type { IOrderService } from '@/types/interfaces';
import type { IPaymentGateway, INotificationService } from '@/types/interfaces';

export class PaymentService {
  constructor(
    private readonly orderService: IOrderService,
    private readonly gateway: IPaymentGateway,
    private readonly notifications: INotificationService
  ) {}

  /**
   * Process a payment for an order.
   * @param orderId - The order to charge
   * @param amount - Payment amount in dollars
   * @returns The created payment record
   * @throws {Error} If order not found or gateway rejects
   */
  async processPayment(orderId: string, amount: number) {
    const order = await this.orderService.getOrder(orderId);
    const payment = await this.gateway.charge(amount, order.currency);
    await this.notifications.send(order.userId, 'payment_success');
    return payment;
  }

  /**
   * Refund a previous payment.
   * @param paymentId - The payment to refund
   * @returns The refund record
   * @throws {Error} If payment not found or already refunded
   */
  async refundPayment(paymentId: string) {
    return this.gateway.refund(paymentId);
  }
}
```

## Common mistakes

- **Generating documentation that does not match the actual code** — Cursor may describe methods that do not exist or omit methods that do when generating documentation separately from code. Fix: Always select the actual class code and use Cmd+K to add documentation. Never generate documentation in a separate Chat session without referencing the file.
- **Including implementation details in architectural documentation** — Docstrings that describe how the code works internally become outdated quickly. Focus on what the class does and its relationships. Fix: Add to .cursorrules: 'Docstrings describe WHAT and WHY, not HOW. Implementation details belong in inline comments.'
- **Creating overly verbose documentation on simple functions** — A one-line utility function does not need a Mermaid diagram. Over-documenting simple code adds noise. Fix: Add a rule: 'Full documentation for classes and complex methods only. Simple utility functions need only a one-line @description.'

## Best practices

- Add documentation rules to .cursor/rules so Cursor generates docs consistently
- Include Mermaid diagrams for classes with 3+ relationships
- Use @see references to link related classes in docstrings
- Update documentation with Cmd+K after every significant code change
- Focus documentation on WHAT and WHY, not implementation details
- Use @example blocks with realistic usage patterns
- Keep module-level documentation in index.ts barrel files

## Frequently asked questions

### Will Mermaid diagrams in JSDoc render anywhere?

Mermaid diagrams render in GitHub markdown, GitLab, Notion, and VS Code with the Mermaid extension. In JSDoc comments, they serve as readable ASCII documentation even without rendering.

### Should I document every function?

Document all public/exported functions and classes. Private helper functions with clear names rarely need full JSDoc. Add a threshold rule to .cursorrules.

### Can Cursor generate Swagger/OpenAPI documentation?

Yes. Ask Cursor to add decorators like @ApiProperty (NestJS) or generate OpenAPI YAML from your route handlers. Reference your API types for accurate schemas.

### How do I prevent documentation from going stale?

Update docs with every code change using Cmd+K. Add a .cursor/rules directive: 'When modifying a function, update its JSDoc to reflect the changes.' Consider adding a CI lint check for JSDoc coverage.

### Is there a maximum useful documentation length?

Class docstrings should be under 30 lines including the diagram. Method docstrings should be under 10 lines. Beyond that, documentation becomes noise rather than signal.

---

Source: https://www.rapidevelopers.com/cursor-tutorial/how-to-direct-cursor-ai-to-embed-uml-like-descriptions-in-docstrings-for-complex-classes
© RapidDev — https://www.rapidevelopers.com/cursor-tutorial/how-to-direct-cursor-ai-to-embed-uml-like-descriptions-in-docstrings-for-complex-classes
