Skip to main content

Overview

OpenDocs provides a unified model that transforms documentation from any programming language into a consistent, navigable structure. Instead of maintaining separate models for TypeScript, Rust, Go, Python, and other languages, OpenDocs defines five core components that work together to represent documentation universally:
  • DocSet - The root object in opendocs.json containing metadata and projects
  • Project - Individual project in a monorepo (package, library, app)
  • DocItem - Universal element representing any documentable code (classes, functions, methods, etc.)
  • DocBlock - Structured documentation content extracted from code comments
  • DocTag - Individual documentation tags (@param, @returns, @deprecated)
This approach eliminates complexity while providing complete flexibility for language-specific features.

Model Hierarchy

The five models form a hierarchical structure where each plays a specific role: Data Flow:
  1. DocSet (the opendocs.json file) contains metadata and an array of Projects
  2. Projects contain top-level DocItems (packages, modules, namespaces)
  3. DocItems nest hierarchically through the items array
  4. Each DocItem references its parent container via ContainerRef
  5. DocItems link to their documentation via DocBlock
  6. DocBlocks organize tags in arrays for structured metadata

The Five Core Models

DocSet

The DocSet model represents the opendocs.json file - the entry point for your Documentation Set. This is the root object that contains metadata about the documentation and references all projects.
Purpose: The DocSet model exists to:
  • Provide a single entry point (opendocs.json) for the entire Documentation Set
  • Store metadata about the documentation itself
  • Organize multiple projects in monorepos
  • Enable versioning and tracking of documentation changes

Project

The Project model represents an individual project within a Documentation Set. In monorepos, each package, library, or app is a separate Project. Each Project has its own language, version, and contains all DocItems that make up that project’s API reference.
Key use case - Monorepos: The Project model was designed to support monorepos where a single Documentation Set contains multiple projects (packages, apps, libraries). Each project has its own identifier, language, and version while sharing a common documentation structure. Organizational patterns:
  • Use unique, descriptive IDs (e.g., "auth-service", "web-sdk")
  • Specify the programming language for each project
  • Organize top-level items logically (by module, package, or namespace)
  • Use meaningful project names that match your package/repository
  • Declare dependencies between projects for proper cross-referencing
  • Include version information for documentation tracking

DocItem

The DocItem is the fundamental unit of documentation in OpenDocs. Everything is a DocItem - from entire modules down to individual method parameters. This unified approach works across all programming languages while preserving language-specific characteristics.
Universal abstraction: Every documentation element, regardless of programming language, is represented as a DocItem:
  • Rust: struct, trait, impl-method
  • Go: struct, interface, receiver-method
  • TypeScript: class, interface, method, property
  • Python: class, function, property
Language-specific flexibility: The kind field enables complete language-specific typing without breaking the universal model:
{
  "id": "serde::de::Deserialize",
  "name": "Deserialize",
  "kind": "trait",
  "language": "rust",
  "metadata": {
    "associatedTypes": ["Item"],
    "supertraits": ["Sized"]
  }
}
Hierarchical nesting example:
{
  "id": "my-module",
  "name": "My Module",
  "kind": "module",
  "language": "typescript",
  "items": [
    {
      "id": "my-module#MyClass",
      "name": "MyClass",
      "kind": "class",
      "language": "typescript",
      "items": [
        {
          "id": "my-module#MyClass#constructor",
          "name": "constructor",
          "kind": "constructor",
          "language": "typescript"
        }
      ]
    }
  ]
}

DocBlock

DocBlock represents structured documentation content extracted from source code comments. It provides a unified format for documentation regardless of the original comment syntax (TSDoc, Javadoc, rustdoc, etc.).
Tag structure: DocBlock organizes tags in a Record<string, (string | DocTag)[]> where each tag can be either a simple string or a complex DocTag object.

DocTag

DocTag represents individual documentation tags. It supports both simple string values and complex parameter structures for tags like @param, @returns, and @deprecated.
Two types of tags: Simple tags are just strings:
{
  "tags": {
    "since": ["1.0.0"],
    "author": ["John Doe"]
  }
}
Complex tags include structured metadata:
{
  "tags": {
    "param": [
      {
        "name": "param",
        "content": "The width of the rectangle",
        "parameters": { "name": "width", "type": "number" }
      }
    ]
  }
}
Cross-format normalization: Different languages use different doc comment syntax, but all normalize to the same DocTag structure:
FormatSyntaxNormalized To
TSDoc@param width - The width{ name: "param", content: "The width", parameters: { name: "width" } }
Javadoc@param width the widthSame DocTag structure
Python:param width: The width
:type width: int
Same structure, with type: "int" in parameters
Rustdoc* \width` - The width`Same DocTag structure
XMLDoc<param name="width">The width</param>Same DocTag structure
This enables consistent rendering and cross-language documentation tools.

ContainerRef

ContainerRef links DocItems to their parent containers, enabling proper navigation and context.

How Models Work Together

Complete Hierarchy Example

Project: "My Project" (version: 1.0.0)
├── DocItem: Package "my-module" (module)
│   ├── DocItem: Class "Calculator"
│   │   ├── DocBlock
│   │   │   ├── description: "Performs calculations"
│   │   │   └── tags: { since: ["1.0.0"] }
│   │   ├── DocItem: Method "add"
│   │   │   ├── DocBlock
│   │   │   │   ├── description: "Adds two numbers"
│   │   │   │   └── tags:
│   │   │   │       ├── param: [{ name: "a", content: "First number" }]
│   │   │   │       ├── param: [{ name: "b", content: "Second number" }]
│   │   │   │       └── returns: ["The sum"]
│   │   │   ├── DocItem: Parameter "a"
│   │   │   └── DocItem: Parameter "b"
│   │   └── DocItem: Property "precision"
│   └── DocItem: Function "calculateArea"
└── DocItem: Namespace "Utils"

Cross-Model References

  • Parent-child relationships: DocItems contain child DocItems via the items array
  • Container links: DocItems reference their parent container via container (ContainerRef)
  • Documentation links: DocItems link to their documentation via docBlock (DocBlock)
  • Tag organization: DocBlocks organize tags in a Record<string, (string | DocTag)[]> structure

Cross-Format Compatibility

OpenDocs maps documentation from different formats to the same DocBlock structure, enabling consistent rendering across languages.

TSDoc → DocBlock

Source:
/**
 * Calculates the area
 * @param width - The width
 * @param height - The height
 * @returns The calculated area
 */
OpenDocs:
{
  "description": "Calculates the area",
  "tags": {
    "param": [
      { "name": "param", "content": "The width", "parameters": { "name": "width" } },
      { "name": "param", "content": "The height", "parameters": { "name": "height" } }
    ],
    "returns": ["The calculated area"]
  }
}

Javadoc → DocBlock

Source:
/**
 * Calculates the area.
 * @param width the width
 * @param height the height
 * @return the calculated area
 */
OpenDocs:
{
  "description": "Calculates the area.",
  "tags": {
    "param": [
      { "name": "param", "content": "the width", "parameters": { "name": "width" } },
      { "name": "param", "content": "the height", "parameters": { "name": "height" } }
    ],
    "returns": ["the calculated area"]
  }
}
This standardization enables:
  • Consistent rendering across languages
  • Template compatibility
  • Cross-format documentation migration
  • Support for both simple metadata tags and complex structured data

Next Steps