agentsclimarketplace

Nodejs documentation standards

Skill CowDogMoo/squad-agents/skills/nodejs-documentation-standards

JSDoc standards for Node.js and TypeScript — syntax by declaration type, the JSDoc tag reference, what to document, common mistakes, tooling, and a quality checklist. Use when writing or auditing JSDoc on exported declarations. Also loaded by the nodejs-doc-comments agent as its knowledge base.From its SKILL.md

Install
npx -y skills add CowDogMoo/squad-agents --skill nodejs-documentation-standards

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

13.1 KB, as published. Nobody here has run it

Node.js / TypeScript Documentation Standards

A comprehensive guide to JSDoc documentation comments following the JSDoc specification and TypeScript best practices. This document serves as the knowledge base for the nodejs-doc-comments pattern.

Table of Contents

  1. Core Principles
  2. Syntax by Declaration Type
  3. JSDoc Tags Reference
  4. What to Document
  5. Common Mistakes
  6. Quality Checklist

Core Principles

The Golden Rule

JSDoc blocks appear immediately before the export/declaration with no intervening blank lines. All exported names that carry non-obvious meaning should have JSDoc blocks. Trivial getters/setters and re-exports are intentionally left undocumented — a block that only restates the name is a defect, not a fix.

Philosophy

PrincipleDescription
Complete sentencesStart with an action verb or noun phrase
Explain whatNot how it works internally
User focusFocus on caller needs, not implementation
SearchableClear, explicit, searchable text
No redundancyAvoid "processData — processes the data"
Add valueProvide info beyond the function signature

Line Length

All comment lines should stay within 80 characters for readability.


Syntax by Declaration Type

Functions

/**
 * Fetches the user with the given ID from the database.
 *
 * @param id - The user's UUID
 * @returns The matching user object, or `null` if not found
 * @throws {DatabaseError} If the database is unreachable
 * @example
 * const user = await getUserById('abc-123');
 * if (!user) throw new NotFoundError('User not found');
 */
export async function getUserById(id: string): Promise<User | null> {
  // ...
}

Rules:

  • Start with an imperative verb: "Fetches...", "Creates...", "Returns...", "Validates..."
  • @param name - description (dash separator, not colon)
  • @returns describes what is returned and when null/undefined is possible
  • Omit TypeScript types in @param and @returns for .ts files — the type system is the source of truth

Classes

/**
 * Manages a pool of database connections for efficient reuse.
 *
 * All public methods are safe for concurrent use by multiple callers.
 * Call {@link ConnectionPool.close} when done to release all connections.
 */
export class ConnectionPool {
  /**
   * Creates a new connection pool with the given configuration.
   *
   * @param config - Pool settings. `maxConnections` defaults to 10.
   */
  constructor(private readonly config: PoolConfig) {}
}

Rules:

  • Use "Manages...", "Represents...", "Provides..."
  • Document concurrency safety explicitly when relevant
  • Document cleanup requirements (.close(), .destroy())

Interfaces and Type Aliases

/**
 * Configuration options for the HTTP client.
 */
export interface HttpClientOptions {
  /** Base URL prepended to all request paths. */
  baseUrl: string;

  /**
   * Request timeout in milliseconds. Defaults to 30 000.
   * Set to 0 to disable timeout.
   */
  timeout?: number;
}

/**
 * Represents a paginated response envelope from the API.
 */
export type PaginatedResponse<T> = {
  data: T[];
  /** Total number of items across all pages. */
  total: number;
  page: number;
};

Constants and Enums

/** Maximum number of retry attempts for transient failures. */
export const MAX_RETRIES = 3;

/** Retry delay in milliseconds between attempts. */
export const RETRY_DELAY_MS = 500;

/**
 * HTTP status codes used by the API.
 */
export enum HttpStatus {
  /** Request succeeded. */
  OK = 200,
  /** Resource was not found. */
  NotFound = 404,
  /** Internal server error. */
  InternalServerError = 500,
}

Error Variables / Sentinel Errors

/**
 * Thrown when a requested resource cannot be found.
 * Use `errors.is(err, ErrNotFound)` or `err instanceof NotFoundError` to check.
 */
export class NotFoundError extends Error {}

/**
 * Returned by database operations when a record does not exist.
 */
export const ErrNotFound = new Error('not found');

Boolean Functions

/**
 * Returns `true` if the email address passes RFC 5322 format validation.
 */
export function isValidEmail(email: string): boolean {}

/**
 * Returns `true` if the user account is active and not suspended.
 */
export function isActiveUser(user: User): boolean {}

JSDoc Tags Reference

Core Tags

TagUsageExample
@param name - descDocument a parameter@param id - The user UUID
@returns descDocument return value@returns The matching user or null
@throws {Type} descDocument thrown errors@throws {ValidationError} If input is invalid
@exampleCode example blockSee below
@deprecated descMark as deprecated@deprecated Use createClientV2 instead
@remarks descAdditional context@remarks Not safe for concurrent use
@seeCross-reference@see {@link getUserById}
@since versionVersion introduced@since 2.0.0

@example Tag

/**
 * Parses a JWT and returns its payload without verifying the signature.
 *
 * @param token - The encoded JWT string
 * @returns The decoded payload object
 * @throws {SyntaxError} If the token is malformed
 * @example
 * ```ts
 * const payload = decodeJwt(token);
 * console.log(payload.sub); // user ID
 * ```
 */
export function decodeJwt(token: string): JwtPayload {}

@deprecated Tag

/**
 * Creates an HTTP client using the legacy connection model.
 *
 * @deprecated Use {@link createHttpClientV2} which supports connection
 * pooling. This function will be removed in v3.0.0.
 */
export function createHttpClient(url: string): HttpClient {}

TypeScript-Specific Conventions

For .ts files, omit types from @param and @returns — they are redundant with the TypeScript signature:

// Good in TypeScript:
/**
 * @param userId - The target user's UUID
 * @returns The user record, or `null` if not found
 */
async function getUser(userId: string): Promise<User | null>

// Bad — redundant types in TypeScript:
/**
 * @param {string} userId - The target user's UUID
 * @returns {Promise<User|null>} The user record
 */
async function getUser(userId: string): Promise<User | null>

For .js files (no TypeScript), include types:

/**
 * @param {string} userId - The target user's UUID
 * @returns {Promise<User|null>} The user record, or null if not found
 */
async function getUser(userId) {}

What to Document

Async / Promise Behavior

Document when non-standard:

/**
 * Sends an email to the specified address.
 *
 * This function resolves as soon as the message is queued — delivery
 * is not guaranteed. Listen to the `'delivery'` event for confirmation.
 */
export async function sendEmail(to: string, subject: string): Promise<void> {}

Error Values

/**
 * Thrown when a rate limit is exceeded.
 *
 * The `retryAfter` property indicates when to retry (Unix timestamp in ms).
 */
export class RateLimitError extends Error {
  /** Unix timestamp (ms) after which the request may be retried. */
  retryAfter: number;
}

Cleanup Requirements

/**
 * Opens a connection to the message broker.
 *
 * Always call {@link BrokerClient.disconnect} when done to prevent
 * connection leaks, even if an error is thrown during use.
 */
export async function connect(url: string): Promise<BrokerClient> {}

Parameter Constraints

/**
 * Schedules a job to run at the specified interval.
 *
 * @param intervalMs - Polling interval in milliseconds. Must be ≥ 100.
 *   Values below 100 are rounded up to prevent CPU saturation.
 * @param fn - The async function to execute. Must resolve within `intervalMs`.
 */
export function schedule(intervalMs: number, fn: () => Promise<void>): Job {}

Return Value Semantics

/**
 * Searches for users matching the given filter.
 *
 * @returns A paginated result set. Returns an empty `data` array (not
 *   `null`) when no users match. The `total` field always reflects the
 *   full count across all pages.
 */
export async function searchUsers(filter: UserFilter): Promise<PaginatedResult<User>> {}

Common Mistakes

Redundant Comments

Bad:

/** Gets the user. */
export function getUser(id: string): Promise<User> {}

Good:

/**
 * Fetches the user with the given ID, including their profile and roles.
 *
 * @param id - The user's UUID
 * @returns The full user object with profile data populated
 * @throws {NotFoundError} If no user exists with the given ID
 */
export function getUser(id: string): Promise<User> {}

Best (when the name already says it all): add no block. For trivial getters/setters or re-exports, leaving the declaration undocumented is correct — list it as trivial in the skipped table. A lateral rewrite of an already-adequate block is not an improvement either; leave it alone.

Implementation Details

Bad:

/** Queries the users table with a prepared statement and maps rows. */
export function getUser(id: string): Promise<User> {}

Good:

/** Fetches the user with the given ID. */
export function getUser(id: string): Promise<User> {}

Blank Line Between JSDoc and Declaration

Bad:

/**
 * Fetches a user by ID.
 */

export function getUser(id: string): Promise<User> {} // blank line = JSDoc not attached!

Good:

/**
 * Fetches a user by ID.
 */
export function getUser(id: string): Promise<User> {} // no blank line

Missing @throws

Bad:

/**
 * Parses a JSON string and returns the result.
 */
export function parseJson(raw: string): unknown {}

Good:

/**
 * Parses a JSON string and returns the typed result.
 *
 * @param raw - The JSON string to parse
 * @returns The parsed value
 * @throws {SyntaxError} If `raw` is not valid JSON
 */
export function parseJson(raw: string): unknown {}

Special Syntax

Deprecation

/**
 * @deprecated Use {@link createClientV2} instead. This method does not
 * support retries and will be removed in v3.0.0.
 */
export function createClient(): Client {}

Doc Links (TypeDoc / TSDoc)

/**
 * Creates a new {@link Session} from the given token.
 *
 * @see {@link SessionOptions} for available configuration options
 */
export function createSession(token: string): Session {}

Module-Level Documentation

/**
 * @module auth
 *
 * Provides authentication utilities including JWT parsing, session
 * management, and permission checks.
 *
 * @example
 * ```ts
 * import { createSession, checkPermission } from './auth';
 * ```
 */

Tools and Automation

TypeDoc

Generate HTML docs from JSDoc + TypeScript types:

npm install --save-dev typedoc
npx typedoc --entryPoints src/index.ts --out docs

TSDoc Linter

npm install --save-dev @microsoft/tsdoc @microsoft/tsdoc-config

ESLint JSDoc Plugin

npm install --save-dev eslint-plugin-jsdoc

# .eslintrc.js
module.exports = {
  plugins: ['jsdoc'],
  rules: {
    'jsdoc/require-jsdoc': ['warn', { publicOnly: true }],
    'jsdoc/require-param-description': 'warn',
    'jsdoc/require-returns-description': 'warn',
  },
};

Quality Checklist

Before Submitting

  • All exported names with non-obvious meaning have JSDoc blocks (trivial getters/setters/re-exports left undocumented)
  • Comments start with an action verb or noun phrase
  • Complete sentences with proper punctuation
  • No blank line between JSDoc block and declaration
  • Lines within 80 characters
  • @param for all non-obvious parameters
  • @returns describing the return value semantics
  • @throws for known/documented error types
  • Async behavior documented when non-obvious
  • Cleanup requirements documented
  • Deprecated exports marked with @deprecated

Common Patterns

DeclarationPattern
async function returning value"Fetches...", "Creates...", "Resolves..."
function returning bool"Returns true if [condition]"
function with side effects"[Action]s [object]..."
class"Manages...", "Represents...", "Provides..."
Error class/constant"[Name] is thrown when..."
Constant"[Name] is the [purpose]..."
Type alias"Represents..."

References


Last updated: 2026-05-25

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.