# Docusaurus OpenAPI Docs Administrator & Developer Guide

## 1. Architecture Overview

Docusaurus OpenAPI Docs is a monorepo containing three npm packages that extend Docusaurus with OpenAPI documentation capabilities. The plugin reads OpenAPI spec files (2.0/3.0/3.1), resolves `$ref` pointers and circular references, converts the specification into MDX pages with compressed API metadata, and generates sidebar navigation. The theme renders those pages with an interactive API explorer powered by Redux state management, Postman code generators, and React form components.

### Architecture Diagram

```text
┌─────────────────────────────────────────────────────────────────────┐
│                        docusaurus.config.ts                         │
│  plugins: [docusaurus-plugin-openapi-docs]                          │
│  themes:  [docusaurus-theme-openapi-docs]                           │
└──────────┬──────────────────────────────────┬───────────────────────┘
           │                                  │
           ▼                                  ▼
┌─────────────────────────┐     ┌──────────────────────────────────┐
│  Plugin (Build-time)     │     │  Theme (Runtime / Client-side)    │
│                          │     │                                    │
│  OpenAPI Spec ──►        │     │  ApiItem ──► ApiExplorer           │
│    loadAndResolveSpec    │     │    ├── Authorization (Redux)       │
│    ├── Redocly bundle    │     │    ├── ParamOptions (Redux)        │
│    ├── $RefParser deref  │     │    ├── Body (Redux)                │
│    └── swagger2openapi   │     │    ├── Server selector             │
│                          │     │    ├── CodeSnippets (Postman)      │
│  processOpenapiFiles     │     │    ├── Request + Response          │
│    ├── markdown/*        │     │    └── SchemaItem / StatusCodes    │
│    └── sidebars/*        │     │                                    │
│                          │     │  Styling: SCSS + CSS modules       │
│  Output:                 │     │  State: @reduxjs/toolkit           │
│    *.api.mdx             │     │  Persistence: sessionStorage /     │
│    *.info.mdx            │     │    localStorage middleware         │
│    *.tag.mdx             │     └──────────────────────────────────┘
│    schemas/*.schema.mdx  │
│    sidebar.ts            │
│    versions.json         │
│    *.json (externalized) │
└─────────────────────────┘

┌──────────────────────────────┐
│  create-docusaurus-openapi   │
│  (Scaffolder CLI)            │
│  npx create-docusaurus-      │
│    openapi-docs <name>       │
│  Copies template + installs  │
└──────────────────────────────┘
```

### Component Inventory

| Component | Package | Path | Role |
|---|---|---|---|
| Plugin entry | `docusaurus-plugin-openapi-docs` | `packages/docusaurus-plugin-openapi-docs/src/index.ts` | Registers CLI commands, orchestrates generation |
| Options validation | same | `src/options.ts` | Joi schema for all plugin options |
| Type definitions | same | `src/types.d.ts` | TypeScript interfaces for metadata, options, sidebar |
| OpenAPI loader | same | `src/openapi/index.ts` | `readOpenapiFiles` + `processOpenapiFiles` |
| Spec resolver | same | `src/openapi/utils/loadAndResolveSpec.ts` | Redocly bundling, `$RefParser` deref, Swagger 2→3 |
| OpenAPI parser | same | `src/openapi/utils/services/OpenAPIParser.ts` | Schema traversal, `$ref` resolution, circular handling |
| Redoc options | same | `src/openapi/utils/services/RedocNormalizedOptions.ts` | Redocly-compatible normalization |
| JSON pointer | same | `src/openapi/utils/utils/JsonPointer.ts` | JSON Pointer (RFC 6901) implementation |
| OpenAPI utils | same | `src/openapi/utils/utils/openapi.ts` | HTTP code validation, field checking |
| Markdown generators | same | `src/markdown/*.ts` | 20+ functions generating MDX sections |
| Sidebar generator | same | `src/sidebars/index.ts` | Tag/tagGroup-based sidebar slice generation |
| Sidebar utils | same | `src/sidebars/utils.ts` | `versionSelector` + `versionCrumb` HTML generators |
| Example generators | same | `src/openapi/createRequestExample.ts`, `createResponseExample.ts`, `createSchemaExample.ts` | Build sample JSON from schemas |
| Theme entry | `docusaurus-theme-openapi-docs` | `packages/docusaurus-theme-openapi-docs/src/index.ts` | Webpack config, SCSS loader, theme path |
| ApiItem | same | `src/theme/ApiItem/index.tsx` | Page wrapper for API doc pages |
| ApiItem store | same | `src/theme/ApiItem/store.ts` | Redux store factory per API page |
| ApiExplorer | same | `src/theme/ApiExplorer/index.tsx` | Main interactive explorer component |
| Authorization | same | `src/theme/ApiExplorer/Authorization/` | Auth form with slice (apiKey, http, oauth2, openIdConnect) |
| Body | same | `src/theme/ApiExplorer/Body/` | Request body editor with schema resolution |
| CodeSnippets | same | `src/theme/ApiExplorer/CodeSnippets/` | Postman code-gen integration (18 languages) |
| Request / Response | same | `src/theme/ApiExplorer/Request/`, `Response/` | HTTP execution + response display |
| Server selector | same | `src/theme/ApiExplorer/Server/` | Server URL dropdown from spec's `servers[]` |
| ParamOptions | same | `src/theme/ApiExplorer/ParamOptions/` | Form items for query/path/header/cookie params |
| Persistence | same | `src/theme/ApiExplorer/persistenceMiddleware.ts` | Redux middleware for auth credential storage |
| Schema components | same | `src/theme/Schema/`, `SchemaItem/`, `SchemaTabs/` | Recursive schema rendering |
| Scaffolder | `create-docusaurus-openapi-docs` | `packages/create-docusaurus-openapi-docs/src/index.ts` | CLI scaffolder (`init()` function) |
| Demo site | — | `demo/` | Full working example with 9 API configs |

> [!NOTE]
> The plugin operates exclusively at **build time** — it reads spec files and writes MDX/JSON. The theme operates at **runtime** — it renders the interactive explorer in the browser. There is no server-side component; API requests are made directly from the user's browser.

### Technology Stack

| Layer | Technology |
|---|---|
| Build platform | Docusaurus 3.10.0+ |
| Language | TypeScript (strict mode via `tsconfig.base.json`) |
| Package management | Yarn 1.22 workspaces + Lerna 9 |
| OpenAPI parsing | `@redocly/openapi-core` (bundling), `@apidevtools/json-schema-ref-parser` (deref) |
| Swagger 2→3 | `swagger2openapi` |
| Template rendering | Mustache |
| Markdown generation | Custom TypeScript functions (20+ `create*.ts` modules) |
| State management | `@reduxjs/toolkit` + `react-redux` |
| Code generation | `postman-code-generators` + `postman-collection` |
| Form handling | `react-hook-form` |
| Markdown rendering | `react-markdown` + `rehype-raw` + `remark-gfm` |
| Live code editing | `react-live` |
| Styling | SCSS + CSS modules |
| Compression | Node.js `zlib` (deflate for API JSON in frontmatter) |
| Testing | Jest + Cypress |
| Linting | ESLint + Prettier |

### Data Flow: Spec → MDX → Interactive Page

1. **Spec Loading**: `readOpenapiFiles()` reads the spec from file or URL
2. **Bundling**: `@redocly/openapi-core` bundles and resolves external `$ref`s
3. **Dereferencing**: `@apidevtools/json-schema-ref-parser` fully dereferences all `$ref` pointers
4. **Circular Handling**: Custom `serializer()` replaces circular references with `circular()` markers
5. **Swagger Conversion**: If the spec has a `swagger` field, `swagger2openapi` converts it to OpenAPI 3.0
6. **Processing**: `processOpenapiFiles()` splits into API, Info, Tag, and Schema page metadata
7. **Markdown Generation**: Each page type gets its markdown from `create*PageMD()` functions
8. **Externalization**: When `externalJsonProps` is enabled, large JSON is written to separate `.json` files
9. **MDX Rendering**: Mustache renders the final MDX with frontmatter (including compressed API JSON)
10. **Sidebar Generation**: `generateSidebarSlice()` produces the `sidebar.ts` TypeScript file
11. **Build**: Docusaurus compiles MDX → React components
12. **Runtime**: `ApiItem` creates a Redux store per page, `ApiExplorer` renders the interactive UI

---

## 2. System Requirements

| Requirement | Version | Notes |
|---|---|---|
| Node.js | >= 18 (plugin), >= 14 (engine field) | Node 18+ recommended for full compatibility |
| Docusaurus | 3.10.0+ | Peer dependency of both plugin and theme |
| React | 16.8.4, 17, 18, or 19 | Broad compatibility range |
| react-dom | 16.8.4, 17, 18, or 19 | Must match React version |
| `@docusaurus/plugin-content-docs` | ^3.10.0 | Peer dep of plugin |
| `@docusaurus/theme-common` | ^3.10.0 | Peer dep of theme |
| `@docusaurus/utils` | ^3.10.0 | Peer dep of plugin |
| `@docusaurus/utils-validation` | ^3.10.0 | Peer dep of plugin |
| `docusaurus-plugin-sass` | ^0.2.3 | Peer dep of theme (SCSS compilation) |
| Package manager | Yarn 1.x (dev), npm/pnpm/bun (users) | Monorepo uses Yarn workspaces |

---

## 3. Configuration Reference

### Plugin-Level Options

| Option | Type | Default | Required | Description |
|---|---|---|---|---|
| `id` | `string` | — | Yes | Unique plugin instance identifier |
| `docsPlugin` | `string` | `"@docusaurus/plugin-content-docs"` | No | Content docs plugin to integrate with |
| `docsPluginId` | `string` | — | Yes | ID of the docs plugin instance (e.g., `"classic"`) |
| `config` | `object` | — | Yes | Map of API config entries (keys are API IDs) |

### Per-API Config Options (under `config.<id>`)

| Option | Type | Default | Required | Description |
|---|---|---|---|---|
| `specPath` | `string` | — | Yes | Path to OpenAPI spec (file or URL) |
| `outputDir` | `string` | — | Yes | Output directory for generated MDX files |
| `proxy` | `string` | — | No | CORS proxy URL for API requests |
| `template` | `string` | — | No | Path to custom Mustache template for API pages |
| `infoTemplate` | `string` | — | No | Path to custom Mustache template for info pages |
| `tagTemplate` | `string` | — | No | Path to custom Mustache template for tag pages |
| `schemaTemplate` | `string` | — | No | Path to custom Mustache template for schema pages |
| `downloadUrl` | `string` | — | No | URL or relative path for spec download link |
| `hideSendButton` | `boolean` | `false` | No | Hide the API explorer send button |
| `showExtensions` | `boolean` | `false` | No | Display vendor extensions (`x-*`) in docs |
| `showSchemas` | `boolean` | `false` | No | Generate dedicated schema documentation pages |
| `showInfoPage` | `boolean` | `true` (implicit) | No | Generate API info page; set `false` to skip |
| `schemasOnly` | `boolean` | `false` | No | Only generate schema pages, skip endpoint pages |
| `disableCompression` | `boolean` | `false` | No | Store API JSON uncompressed in MDX frontmatter |
| `maskCredentials` | `boolean` | `false` | No | Mask credential input fields in API explorer |
| `externalJsonProps` | `boolean` | `true` | No | Externalize large JSON to separate files for MDX performance |
| `sidebarOptions` | `object` | — | No | Sidebar generation configuration (see below) |
| `markdownGenerators` | `object` | — | No | Custom markdown generator functions |
| `version` | `string` | — | Required if `versions` | Current version identifier |
| `label` | `string` | — | Required if `versions` | Display label for current version |
| `baseUrl` | `string` | — | Required if `versions` | Base URL path for current version |
| `versions` | `object` | — | No | Map of version configs (see Versioning below) |

> [!IMPORTANT]
> `specPath` and `outputDir` are the only truly required fields per API. All other options have sensible defaults. Note that `outputDir` should **not** have a trailing slash — the plugin strips it but consistent formatting avoids confusion.

### Sidebar Options (under `sidebarOptions`)

| Option | Type | Default | Valid Values | Description |
|---|---|---|---|---|
| `groupPathsBy` | `string` | — | `"tag"`, `"tagGroup"` | Grouping strategy for sidebar categories |
| `categoryLinkSource` | `string` | — | `"tag"`, `"info"`, `"auto"` | What category headers link to |
| `customProps` | `object` | — | any | Custom props passed to sidebar items |
| `sidebarCollapsible` | `boolean` | — | — | Allow collapsing sidebar categories |
| `sidebarCollapsed` | `boolean` | — | — | Start with categories collapsed |
| `sidebarGenerators` | `object` | — | — | Custom sidebar item generator (`createDocItem` function) |

### Markdown Generator Options (under `markdownGenerators`)

| Generator | Signature | Description |
|---|---|---|
| `createApiPageMD` | `(pageData: ApiPageMetadata) => string` | Generate markdown for API endpoint pages |
| `createInfoPageMD` | `(pageData: InfoPageMetadata) => string` | Generate markdown for API info pages |
| `createTagPageMD` | `(pageData: TagPageMetadata) => string` | Generate markdown for tag category pages |
| `createSchemaPageMD` | `(pageData: SchemaPageMetadata) => string` | Generate markdown for schema pages |

### Version Config Options (under `versions.<versionId>`)

| Option | Type | Required | Description |
|---|---|---|---|
| `specPath` | `string` | Yes | Path to the versioned spec file |
| `outputDir` | `string` | Yes | Output directory for this version's docs |
| `label` | `string` | Yes | Display label (e.g., `"v1.0.0"`) |
| `baseUrl` | `string` | Yes | Base URL for this version |
| `downloadUrl` | `string` | No | Download URL for this version's spec |

> [!WARNING]
> The version key `"all"` is reserved and cannot be used as a version identifier. The plugin will emit an error: `Can't use id 'all' for OpenAPI docs versions configuration key.`

### Theme Configuration (in `themeConfig`)

| Option | Type | Default | Description |
|---|---|---|---|
| `api.proxy` | `string` | — | Global CORS proxy URL |
| `api.authPersistence` | `false \| "sessionStorage" \| "localStorage"` | `"sessionStorage"` | How auth credentials are persisted |
| `api.requestTimeout` | `number` | `30000` | Request timeout in milliseconds |
| `api.requestCredentials` | `"omit" \| "same-origin" \| "include"` | browser default | Cookie/credential sending policy |
| `languageTabs` | `array` | 18 languages | Code snippet language configuration |

### Environment Variables

| Variable | Default | Used In | Description |
|---|---|---|---|
| `npm_config_user_agent` | — | Scaffolder | Auto-detect package manager |
| `NODE_ENV` | — | OpenAPIParser | Development/production behavior |
| `DOCUSAURUS_FASTER` | `"true"` | Demo config | Enable Docusaurus faster mode |

---

## 4. Deployment & Scaling

### Build Process

The monorepo build pipeline:

```bash
# Build all packages (plugin + theme)
yarn build-packages

# Build the demo site
yarn build-demo

# Or build everything
yarn build
```

> [!TIP]
> During development, use `yarn watch` to rebuild packages on change, and `yarn watch:demo` with nodemon to auto-restart the demo dev server when package builds complete.

### Production Build

```bash
# Generate API docs
npx docusaurus gen-api-docs all --all-versions

# Build static site
npx docusaurus build

# Serve locally to verify
npx docusaurus serve
```

The output is static HTML/JS/CSS in the `build/` directory, deployable to any static hosting.

### CI/CD Considerations

- **Node.js requirement**: >= 18 with native build tools (for `sass` compilation)
- **Generation step**: Run `gen-api-docs` before `docusaurus build` — the MDX files must exist
- **Spec changes**: Include a `clean-api-docs` + `gen-api-docs` step in CI to ensure fresh generation
- **Cache**: Clear `.docusaurus/` cache between builds if specs change
- **Large specs**: Enable `externalJsonProps: true` (default) to avoid MDX compilation timeouts with large API specs

> [!NOTE]
> The `externalJsonProps` feature writes large JSON to separate files loaded via `require()`, which can significantly reduce MDX compilation time. This is enabled by default since v5.0.

### Firebase Deployment

The project includes Firebase configuration (`.firebaserc`, `firebase.json`) for deploying the demo site. The demo is hosted at `https://docusaurus-openapi.tryingpan.dev`.

---

## 5. Operations

### Development Workflow

1. Clone the repository
2. Install dependencies:

```bash
yarn install
```

3. Build packages:

```bash
yarn build-packages
```

4. Start the demo:

```bash
yarn start
```

> [!TIP]
> Use `yarn watch` in a separate terminal to auto-rebuild packages as you edit. The demo uses `nodemon` via `yarn watch:demo` to detect changes in `packages/*/lib/`.

### Testing

```bash
# Unit tests (Jest)
yarn test

# Cypress integration tests (with dev server)
yarn test:cypress:dev

# Cypress tests (with built site)
yarn test:cypress
```

The test suite includes:

| Test Type | Location | Coverage |
|---|---|---|
| Schema generation | `src/markdown/createSchema.test.ts` | Snapshot tests for markdown output |
| Schema examples | `src/openapi/createSchemaExample.test.ts` | Example generation from schemas |
| OpenAPI processing | `src/openapi/openapi.test.ts` | Spec loading and processing |
| Webhook processing | `src/openapi/webhooks.test.ts` | Webhook/x-webhooks support |
| Sidebar generation | `src/sidebars/index.test.ts` | Sidebar slice creation |
| Theme utilities | `src/markdown/utils.test.ts` | Markdown utility functions |
| Cypress E2E | `cypress/integration/` | Schema snapshot tests |

> [!NOTE]
> Tests require `NODE_OPTIONS=--experimental-vm-modules` for Jest ESM support.

### Release Process

1. Update package versions:

```bash
yarn release:version <major|minor|patch|premajor|preminor|prepatch|prerelease|graduate>
```

2. Generate changelog:

```bash
yarn release:changelog
```

3. Open a PR, get it merged

4. Publish to npm:

```bash
yarn release:publish
```

This creates a git tag and publishes all packages via Lerna.

### Canary Releases

```bash
# Standard canary
yarn canary

# Beta canary
yarn canaryBeta
```

Canary versions use the format `0.0.0-<commit-count>+<short-hash>` and are published to the `canary` npm tag.

### Linting and Formatting

```bash
# Check formatting
yarn format

# Run ESLint
yarn lint
```

The project uses Prettier for formatting (via `lint-staged` + Husky pre-commit hook) and ESLint with TypeScript, React, and Cypress plugins.

---

## 6. Performance

### MDX Compilation Optimization

Large OpenAPI specs can produce MDX files with megabytes of embedded JSON, causing slow compilation. The `externalJsonProps` feature (enabled by default) mitigates this by:

1. Extracting large JSON properties (params details, request schemas, status codes) into separate `.json` files
2. Loading them via `require()` in the MDX instead of inline embedding
3. Reducing MDX parse/compile time significantly

### API JSON Compression

By default, the plugin compresses API JSON in MDX frontmatter using Node.js `zlib.deflateSync()` and base64 encoding. This reduces the size of generated MDX files. Set `disableCompression: true` to store JSON uncompressed (useful for debugging).

### Build Performance Tips

- Use `@docusaurus/faster` (enabled in demo config via `future.faster`) for faster Docusaurus builds
- Avoid generating unnecessary API configs during development — use `gen-api-docs <specific-id>` instead of `all`
- Clean the `.docusaurus/` cache if builds become slow after spec changes

---

## 7. Security

### Credential Handling

The API explorer handles authentication credentials with configurable persistence:

| Setting | Storage | Lifetime | Use Case |
|---|---|---|---|
| `false` | In-memory (Redux) | Page navigation only | Highest security |
| `"sessionStorage"` | Browser session storage | Current tab | Default, balanced |
| `"localStorage"` | Browser local storage | Persistent | Convenience |

The persistence middleware (`persistenceMiddleware.ts`) stores the Redux auth state using the configured storage backend. Keys are scoped by the API's info path.

> [!WARNING]
> When `authPersistence` is set to `"localStorage"`, API keys and tokens persist in the browser's local storage. This is convenient for development but inappropriate for shared or public machines. Use `"sessionStorage"` (default) or `false` for production documentation sites where users log in with real credentials.

### Request Credentials Policy

The `requestCredentials` option maps directly to the Fetch API's `credentials` option:

| Value | Behavior |
|---|---|
| `"omit"` | Never send cookies — use when docs are hosted on the same domain as the API |
| `"same-origin"` | Send cookies for same-origin requests only (browser default) |
| `"include"` | Always send cookies, even cross-origin |

### Credential Masking

Set `maskCredentials: true` per API to render auth input fields as password inputs (masked characters). This prevents shoulder-surfing in demo or presentation contexts.

> [!CAUTION]
> The `maskCredentials` feature only masks the UI input. Credentials are still stored in browser storage (if `authPersistence` is enabled) and sent with each request. It is a UI-level convenience, not a security control.

### CORS Proxy Security

When using `proxy`, all API requests are routed through the specified proxy server. The proxy receives the full request including authentication headers. Only use trusted proxies, and never route production API traffic through public CORS proxies.

### Dependencies with Known Considerations

The project depends on `crypto-js` for potential hashing operations in the theme. The theme also uses `pako` for compression and `buffer` for binary data handling in the browser.

---

## 8. Developer Internals

### Repository Structure

```text
docusaurus-openapi-docs/
├── packages/
│   ├── docusaurus-plugin-openapi-docs/    # Build-time plugin
│   │   ├── src/
│   │   │   ├── index.ts                   # Plugin entry, CLI commands
│   │   │   ├── options.ts                 # Joi validation schema
│   │   │   ├── types.d.ts                 # Core TypeScript interfaces
│   │   │   ├── markdown/                  # 20+ MDX generators
│   │   │   │   ├── index.ts               # Barrel: createApiPageMD, createInfoPageMD, etc.
│   │   │   │   ├── createSchema.ts        # Schema → markdown rendering
│   │   │   │   ├── createStatusCodes.ts   # Response status code tables
│   │   │   │   ├── createParamsDetails.ts  # Parameter documentation
│   │   │   │   ├── utils.ts               # render(), externalization helpers
│   │   │   │   └── ...                    # 15+ more section generators
│   │   │   ├── openapi/                   # Spec processing
│   │   │   │   ├── index.ts               # readOpenapiFiles, processOpenapiFiles
│   │   │   │   ├── openapi.ts             # Core processing logic
│   │   │   │   ├── types.ts               # OpenAPI type definitions
│   │   │   │   ├── createRequestExample.ts
│   │   │   │   ├── createResponseExample.ts
│   │   │   │   ├── createSchemaExample.ts
│   │   │   │   └── utils/                 # Spec resolution and parsing
│   │   │   │       ├── loadAndResolveSpec.ts
│   │   │   │       ├── services/OpenAPIParser.ts
│   │   │   │       ├── services/RedocNormalizedOptions.ts
│   │   │   │       └── utils/             # JsonPointer, helpers, openapi utils
│   │   │   └── sidebars/                  # Sidebar generation
│   │   │       ├── index.ts               # generateSidebarSlice
│   │   │       └── utils.ts               # versionSelector, versionCrumb
│   │   └── package.json
│   │
│   ├── docusaurus-theme-openapi-docs/     # Runtime theme
│   │   ├── src/
│   │   │   ├── index.ts                   # Theme plugin: webpack config, paths
│   │   │   ├── types.d.ts                 # ThemeConfig, DocFrontMatter
│   │   │   ├── theme/
│   │   │   │   ├── ApiItem/               # Page-level component + Redux store
│   │   │   │   ├── ApiExplorer/           # Interactive API testing panel
│   │   │   │   │   ├── Authorization/     # Auth forms + Redux slice
│   │   │   │   │   ├── Body/              # Request body editor
│   │   │   │   │   ├── CodeSnippets/      # Postman code-gen integration
│   │   │   │   │   ├── ParamOptions/      # Parameter form items
│   │   │   │   │   ├── Request/           # HTTP request execution
│   │   │   │   │   ├── Response/          # Response display
│   │   │   │   │   ├── Server/            # Server URL selector
│   │   │   │   │   └── ...                # 10+ more sub-components
│   │   │   │   ├── Schema/                # Recursive schema renderer
│   │   │   │   ├── SchemaItem/            # Individual schema property
│   │   │   │   ├── StatusCodes/           # Response code display
│   │   │   │   └── ...                    # 15+ more theme components
│   │   │   └── markdown/                  # Client-side markdown utilities
│   │   └── package.json
│   │
│   └── create-docusaurus-openapi-docs/    # Site scaffolder
│       ├── src/index.ts                   # init() scaffolding logic
│       ├── templates/default/             # Template Docusaurus site
│       └── package.json
│
├── demo/                                  # Demo/docs site
│   ├── docusaurus.config.ts               # 9 API configurations
│   ├── sidebars.ts                        # Complex sidebar with versions
│   ├── customMdGenerators.ts              # Custom markdown generator example
│   └── examples/                          # OpenAPI spec files (Petstore, etc.)
│
├── cypress/                               # E2E tests
├── scripts/                               # Release, changelog, publishing
├── package.json                           # Root workspace config
├── lerna.json                             # Lerna monorepo config
├── tsconfig.base.json                     # Shared TypeScript config
└── jest.config.js                         # Jest configuration
```

### Key Classes

#### `OpenAPIParser` (`src/openapi/utils/services/OpenAPIParser.ts`)

Central class for traversing and resolving OpenAPI schemas. Handles `$ref` pointer resolution, discriminator mapping, `allOf`/`anyOf`/`oneOf` merging, and circular reference detection. Uses a `RefCounter` helper to track dereferenced schemas.

#### `JsonPointer` (`src/openapi/utils/utils/JsonPointer.ts`)

RFC 6901 JSON Pointer implementation for navigating nested OpenAPI documents. Supports `get()`, `set()`, and `compile()`/`parse()` for path manipulation.

#### `RedocNormalizedOptions` (`src/openapi/utils/services/RedocNormalizedOptions.ts`)

Configuration normalization layer originally derived from Redocly. Provides defaults for rendering options like `requiredPropsFirst`, `sortPropsAlphabetically`, `hideSchemaPattern`, `showWebhookVerb`, `minCharacterLengthToInitTextArea`, and `payloadSampleIdx`.

### Plugin Architecture Deep Dive

The plugin (`pluginOpenAPIDocs`) returns a Docusaurus plugin object with a single lifecycle hook: `extendCli()`. This registers four CLI commands:

1. **`gen-api-docs <id>`** — Main generation command
   - Resolves the spec via `loadAndResolveSpec()`
   - Processes into page metadata via `processOpenapiFiles()`
   - Generates sidebar via `generateSidebarSlice()`
   - Renders MDX via Mustache templates with markdown generators
   - Writes `.api.mdx`, `.info.mdx`, `.tag.mdx`, `.schema.mdx`, `sidebar.ts`, and externalized `.json` files

2. **`gen-api-docs:version <id:version>`** — Versioned generation
   - Merges version config with parent config
   - Generates `versions.json` with version metadata
   - Calls `generateApiDocs()` for the specified version

3. **`clean-api-docs <id>`** — Cleanup
   - Globs and deletes `*.api.mdx`, `*.info.mdx`, `*.tag.mdx`, `sidebar.{js,ts}`, `*.json` (except `versions.json`), and `schemas/` directory

4. **`clean-api-docs:version <id:version>`** — Versioned cleanup
   - Cleans version-specific files and optionally `versions.json`

> [!NOTE]
> The plugin does **not overwrite** existing MDX files. This is intentional — it allows users to manually edit generated files without losing changes. To regenerate, always clean first.

### Theme Architecture Deep Dive

The theme plugin (`docusaurusThemeOpenAPI`) configures webpack with:

- **SCSS support**: Adds `sass-loader` rule (unless `docusaurus-plugin-sass` already provides one)
- **Polyfills**: Provides `buffer`, `path-browserify`, and `process/browser` for browser compatibility
- **Theme paths**: Points to `lib/theme/` for compiled theme components

#### Redux State Management

Each `ApiItem` page creates an isolated Redux store (`store.ts`) with the following slices:

| Slice | File | State |
|---|---|---|
| `accept` | `Accept/slice.ts` | Accept header selection |
| `auth` | `Authorization/slice.ts` | Auth credentials per security scheme |
| `body` | `Body/slice.ts` | Request body content (JSON, form data, files) |
| `contentType` | `ContentType/slice.ts` | Request content type selection |
| `encoding` | `EncodingSelection/slice.ts` | Multipart encoding configuration |
| `params` | `ParamOptions/slice.ts` | Path/query/header/cookie parameter values |
| `response` | `Response/slice.ts` | Response data from API calls |
| `schemaSelection` | `SchemaSelection/slice.ts` | oneOf/anyOf/discriminator selection |
| `server` | `Server/slice.ts` | Selected server URL and variables |

The `persistenceMiddleware` subscribes to auth state changes and persists them to the configured storage backend.

#### `buildPostmanRequest.ts`

Converts the Redux state (server URL, params, body, auth, headers) into a Postman `Request` object. This is used by `postman-code-generators` to produce code snippets and by `makeRequest.ts` to execute the actual HTTP call.

### Markdown Generation Pipeline

The `src/markdown/` directory contains 20+ generator functions, each responsible for one section of the MDX output:

| Function | Output |
|---|---|
| `createHeading` | `<Heading>` component with operation title |
| `createMethodEndpoint` | `<MethodEndpoint>` badge with HTTP method + path |
| `createDescription` | Operation description markdown |
| `createDeprecationNotice` | Deprecation banner (if `deprecated: true`) |
| `createAuthorization` | `<Authorization>` component link to info page |
| `createParamsDetails` | `<ParamsDetails>` with param tables |
| `createRequestBodyDetails` | `<RequestSchema>` with body schema |
| `createRequestSchema` | Request body schema rendering |
| `createResponseSchema` | Response schema rendering |
| `createStatusCodes` | `<StatusCodes>` with response codes |
| `createCallbacks` | Callback endpoint documentation |
| `createSchema` | Schema property tree (recursive) |
| `createVendorExtensions` | `x-*` vendor extension display |
| `createAuthentication` | Security scheme documentation |
| `createContactInfo` | API contact information |
| `createLicense` | License information |
| `createTermsOfService` | Terms of service link |
| `createLogo` | `<ApiLogo>` component |
| `createDownload` | Spec download button |
| `createVersionBadge` | Version badge display |

The `render()` utility in `utils.ts` joins an array of markdown sections, filtering `undefined` entries. The `runWithExternalization()` function captures externalized JSON files during rendering.

### Vendor Extension Support

The plugin recognizes these OpenAPI vendor extensions:

| Extension | Location | Purpose |
|---|---|---|
| `x-tagGroups` | Root | Group tags into sidebar categories |
| `x-codeSamples` / `x-code-samples` | Operation | Custom code examples |
| `x-deprecated-description` | Operation | Detailed deprecation message |
| `x-position` | Operation | Override sidebar ordering |
| `x-displayName` | Tag | Override tag display name |
| `x-explicitMappingOnly` | Discriminator | Only show explicitly mapped schemas |
| `x-examples` / `x-example` | Request/Response | Additional examples |

### Supported Security Schemes

The Authorization component handles all OpenAPI 3.x security scheme types:

| Type | Fields | UI |
|---|---|---|
| `apiKey` | name, in (query/header/cookie) | Text input for key value |
| `http` (Bearer) | scheme, bearerFormat | Text input for token |
| `http` (Basic) | scheme | Username + password inputs |
| `oauth2` | flows (implicit, password, clientCredentials, authorizationCode) | Scopes, client ID, URLs |
| `openIdConnect` | openIdConnectUrl | Discovery URL + token input |

### Generated File Types

| File Pattern | Content | Purpose |
|---|---|---|
| `*.api.mdx` | API endpoint page with compressed JSON frontmatter | One per operation |
| `*.info.mdx` | API info/overview page | One per spec |
| `*.tag.mdx` | Tag category page | One per tag |
| `schemas/*.schema.mdx` | Schema documentation page | One per named schema |
| `sidebar.ts` | TypeScript sidebar configuration | One per API |
| `versions.json` | Version metadata array | One per versioned API |
| `*.ParamsDetails.json` | Externalized parameter details | When `externalJsonProps` enabled |
| `*.RequestSchema.json` | Externalized request schema | When `externalJsonProps` enabled |
| `*.StatusCodes.json` | Externalized status codes | When `externalJsonProps` enabled |

---

## 9. Integration Points

### Docusaurus Plugin Integration

The plugin integrates with `@docusaurus/plugin-content-docs` by:

1. Reading the `routeBasePath` and `path` from the docs plugin config (or preset) to correctly generate `infoPath` URLs
2. Using the `docItemComponent: "@theme/ApiItem"` setting to replace the default doc item renderer

When using presets like `"classic"`, the plugin looks for docs config inside the preset's options. When using standalone `@docusaurus/plugin-content-docs` instances, it matches by plugin ID.

### Multiple Plugin Instances

The plugin supports multiple instances for sites with separate API documentation sections:

```typescript
plugins: [
  ["docusaurus-plugin-openapi-docs", {
    id: "core-api",
    docsPluginId: "classic",
    config: { /* ... */ },
  }],
  ["docusaurus-plugin-openapi-docs", {
    id: "admin-api",
    docsPluginId: "admin-docs",
    config: { /* ... */ },
  }],
],
```

When multiple instances exist, the CLI commands require `--plugin-id` to disambiguate.

### Custom Sidebar Generators

The `sidebarGenerators.createDocItem` option allows full control over how API and schema items appear in the sidebar:

```typescript
sidebarOptions: {
  sidebarGenerators: {
    createDocItem: (item, context) => ({
      type: "doc",
      id: item.id,
      label: item.title,
      className: `${item.method} api-method`,
      customProps: context.sidebarOptions.customProps,
    }),
  },
},
```

### Spec Format Compatibility

| Format | Support | Notes |
|---|---|---|
| OpenAPI 3.1.x | Full | Native processing |
| OpenAPI 3.0.x | Full | Native processing |
| OpenAPI 2.0 (Swagger) | Auto-converted | `swagger2openapi` converts to 3.0 at load time |
| JSON `$ref` | Full | `@apidevtools/json-schema-ref-parser` with 15s HTTP timeout |
| Circular `$ref` | Handled | Custom serializer replaces cycles with `circular()` markers |
| Multi-file specs | Supported | External `$ref`s resolved via file and HTTP |
| JSON5 | Used | Sidebar output uses JSON5 for human-readable formatting |

> [!NOTE]
> The plugin emits a console warning when converting Swagger 2.0: `[ReDoc Compatibility mode]: Converting OpenAPI 2.0 to OpenAPI 3.0`. This is informational and does not indicate an error.

### CSS Theming

The demo includes 7 pre-built color palettes:

| Theme | File |
|---|---|
| Cyber | `demo/src/css/themes/cyber.css` |
| Evergreen | `demo/src/css/themes/evergreen.css` |
| Indigo | `demo/src/css/themes/indigo.css` |
| Midnight | `demo/src/css/themes/midnight.css` |
| Nord | `demo/src/css/themes/nord.css` |
| PANW | `demo/src/css/themes/panw.css` |
| Violet | `demo/src/css/themes/violet.css` |

The `PalettePicker` component (`demo/src/components/PalettePicker/index.tsx`) allows runtime theme switching. The selected palette is persisted in `localStorage` under the `openapi-demo-palette` key, with a FOUC-prevention script injected via `injectHtmlTags()`.

Theme components use SCSS (`*.scss` files alongside components) and CSS modules (`*.module.css`) for scoped styling.

### Swizzling Theme Components

All theme components can be overridden via Docusaurus's swizzling mechanism:

```bash
npx docusaurus swizzle docusaurus-theme-openapi-docs ApiExplorer
```

The theme exports its TypeScript source path via `getTypeScriptThemePath()`, enabling `--typescript` swizzling.

---

## 10. Troubleshooting

### Error: `OpenAPI docs plugin ID '<id>' not found.`

**Cause:** The `--plugin-id` flag references a plugin instance that doesn't exist.

**Solution:** Check your `docusaurus.config.ts` for the correct `id` value in the plugin configuration.

### Error: `OpenAPI docs plugin ID must be specified when more than one plugin instance exists.`

**Cause:** Multiple `docusaurus-plugin-openapi-docs` instances exist but no `--plugin-id` was provided.

**Solution:** Pass `-p <plugin-id>` to specify which instance to target.

> [!NOTE]
> This applies to all four CLI commands (`gen-api-docs`, `gen-api-docs:version`, `clean-api-docs`, `clean-api-docs:version`).

### Error: `ID '<id>' does not exist in OpenAPI docs config.`

**Cause:** The API ID argument doesn't match any key in the `config` object.

**Solution:** Verify the API ID matches a key in `config: { <id>: { ... } }`.

### Error: `Can't use id 'all' for OpenAPI docs configuration key.`

**Cause:** A config entry or version uses the reserved key `"all"`.

**Solution:** Rename the config key to something other than `"all"`.

### Error: `invalid HTTP code`

**Cause:** An OpenAPI response uses an HTTP status code that isn't recognized.

**Solution:** Use standard HTTP status codes (200, 201, 400, etc.) or valid status code ranges (2XX, 4XX).

### Error: `Payload must have fields: ...`

**Cause:** An OpenAPI object is missing required fields during processing.

**Solution:** Validate your OpenAPI spec for completeness. Common missing fields include `type` on schema objects and `description` on response objects.

### Schema snapshot test failures

**Cause:** Changes to markdown generation functions produce different output.

**Solution:** Review the diff in `src/markdown/__snapshots__/` and update snapshots if the changes are intentional:

```bash
yarn test -- --updateSnapshot
```

### SASS compilation errors

**Cause:** The `sass` dependency failed to install native bindings.

**Solution:** Ensure you have native build tools installed (`build-essential` on Linux, Xcode CLI tools on macOS). If using Docker, use a Node.js image with native build support.

> [!WARNING]
> The theme automatically adds SCSS compilation rules to webpack unless `docusaurus-plugin-sass` is already configured. Having both can cause conflicts — install `docusaurus-plugin-sass` as a peer dependency and let it handle SCSS if you use it elsewhere in your site.

---

## 11. Reference

### CLI Commands Summary

| Command | Usage | Description |
|---|---|---|
| `gen-api-docs` | `<id> [-p plugin] [--all-versions] [--schemas-only]` | Generate API docs |
| `gen-api-docs:version` | `<id:version> [-p plugin] [--schemas-only]` | Generate versioned API docs |
| `clean-api-docs` | `<id> [-p plugin] [--all-versions] [--schemas-only]` | Clean generated API docs |
| `clean-api-docs:version` | `<id:version> [-p plugin] [--schemas-only]` | Clean versioned API docs |

### npm Scripts (Development)

| Script | Description |
|---|---|
| `yarn build` | Build all packages + demo |
| `yarn build-packages` | Build plugin + theme packages |
| `yarn build-demo` | Build demo site |
| `yarn start` | Start demo dev server |
| `yarn watch` | Watch and rebuild packages |
| `yarn watch:demo` | Watch packages and restart demo |
| `yarn test` | Run Jest tests |
| `yarn test:cypress` | Run Cypress E2E tests |
| `yarn test:cypress:dev` | Run Cypress with dev server |
| `yarn lint` | Run ESLint |
| `yarn format` | Check formatting |
| `yarn clean` | Remove all build artifacts and node_modules |
| `yarn gen-api` | Generate all demo API docs |
| `yarn clean-api` | Clean all demo API docs |
| `yarn release:version` | Bump package versions |
| `yarn release:changelog` | Generate changelog |
| `yarn release:publish` | Publish to npm |
| `yarn canary` | Publish canary release |

### Package Versions (as of source commit)

| Package | Version |
|---|---|
| `docusaurus-plugin-openapi-docs` | 5.0.1 |
| `docusaurus-theme-openapi-docs` | 5.0.1 |
| `create-docusaurus-openapi-docs` | 5.0.1 |

---

_Generated May 2026 from PaloAltoNetworks/docusaurus-openapi-docs at 89eecbd. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial, AI-generated guide for a Palo Alto Networks open-source repository; not reviewed by Palo Alto Networks._
