# Merge Request: Flatten MkDocs Structure + `--module-is-source` Support ## Summary This MR introduces structural improvements to the MkDocs generation pipeline to: 1. Ensure a root `docs/index.md` always exists 2. Flatten documentation structure (remove `docs/<module>/` nesting by default) 3. Add support for `--module-is-source` to treat the module as the documentation root 4. Align navigation (`docforge.nav.yml`) with the new flat layout 5. Regenerate MCP artifacts to reflect updated signatures and docstrings This resolves static hosting issues (e.g., Nginx 403 due to missing `site/index.html`) and makes each generated MkDocs site deployable as a standalone static website. --- ## Motivation Previously, documentation was generated under: ``` docs/<module>/... ``` Which resulted in: ``` site/<module>/index.html ``` When deployed at `/libs/<project>/`, this caused: * Missing `site/index.html` * Nginx returning 403 for root access * Inconsistent static hosting behavior This MR corrects the architecture so each MkDocs build is a valid static site with a root entry point. --- ## Key Changes ### 1️⃣ Flattened Docs Structure **Before** ``` docs/docforge/index.md ``` **After** ``` docs/index.md ``` All documentation paths were updated accordingly: * `docs/docforge/cli/...` → `docs/cli/...` * `docs/docforge/models/...` → `docs/models/...` * `docs/docforge/renderers/...` → `docs/renderers/...` Navigation updated to match the flat layout. --- ### 2️⃣ Root Index Enforcement `MkDocsRenderer` now guarantees: * `docs/index.md` is always created * Parent `index.md` files are auto-generated if missing * Parent indexes link to child modules (idempotent behavior) This ensures: ``` site/index.html ``` Always exists after `mkdocs build`. --- ### 3️⃣ New CLI Flag: `--module-is-source` Added option: ``` --module-is-source ``` Behavior: * Treats the provided module as the documentation root * Removes the top-level module folder from generated paths * Prevents redundant nesting when the module corresponds to the source root Updated components: * `cli.commands.build` * `mkdocs_utils.generate_sources` * `MkDocsRenderer.generate_sources` * Stub files (`.pyi`) * MCP JSON artifacts --- ### 4️⃣ Navigation Spec Update `docforge.nav.yml` updated: **Before** ```yaml home: docforge/index.md ``` **After** ```yaml home: index.md ``` All group paths adjusted to remove `docforge/` prefix. --- ### 5️⃣ MkDocs Config Update `mkdocs.yml` updated to: * Move `site_name` below theme/plugins * Use flat navigation paths * Point Home to `index.md` --- ### 6️⃣ MCP Artifact Regeneration Updated: * Function signatures (new parameter) * Docstrings (reflect `module_is_source`) * Renderer metadata * Line numbers Ensures MCP output matches updated API. --- ## Architectural Outcome Each project now produces a **valid standalone static site**: ``` site/ index.html assets/ search/ ``` Safe for deployment under: ``` /libs/<project>/ ``` No Nginx rewrites required. No directory-index issues. No nested-site ambiguity. --- ## Backward Compatibility * Existing CLI usage remains valid * `--module-is-source` is optional * Navigation spec format unchanged (only paths adjusted) --- ## Deployment Impact After merge: * Each library can be deployed independently * Sites can be merged under a shared root without internal conflicts * Static hosting is predictable and production-safe --- ## Testing * Verified MkDocs build produces `site/index.html` * Verified navigation renders correctly * Verified parent index generation is idempotent * Regenerated MCP docs and validated schema consistency --- ## Result The documentation compiler now: * Produces structurally correct static sites * Supports flat and source-root modes * Eliminates 403 root issues * Scales cleanly across multiple repositories This aligns doc-forge with proper static-site architectural invariants. Reviewed-on: #4 Co-authored-by: Vishesh 'ironeagle' Bangotra <aetoskia@gmail.com> Co-committed-by: Vishesh 'ironeagle' Bangotra <aetoskia@gmail.com>
120 lines
6.5 KiB
JSON
120 lines
6.5 KiB
JSON
{
|
|
"module": "docforge.cli.mcp_utils",
|
|
"content": {
|
|
"path": "docforge.cli.mcp_utils",
|
|
"docstring": null,
|
|
"objects": {
|
|
"Path": {
|
|
"name": "Path",
|
|
"kind": "alias",
|
|
"path": "docforge.cli.mcp_utils.Path",
|
|
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
|
|
"docstring": null
|
|
},
|
|
"click": {
|
|
"name": "click",
|
|
"kind": "alias",
|
|
"path": "docforge.cli.mcp_utils.click",
|
|
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
|
|
"docstring": null
|
|
},
|
|
"GriffeLoader": {
|
|
"name": "GriffeLoader",
|
|
"kind": "class",
|
|
"path": "docforge.cli.mcp_utils.GriffeLoader",
|
|
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.loaders.GriffeLoader')>",
|
|
"docstring": "Loads Python modules and extracts documentation using the Griffe introspection engine.",
|
|
"members": {
|
|
"load_project": {
|
|
"name": "load_project",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.GriffeLoader.load_project",
|
|
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
|
|
"docstring": "Load multiple modules and combine them into a single Project models.\n\nArgs:\n module_paths: A list of dotted paths to the modules to load.\n project_name: Optional name for the project. Defaults to the first module name.\n skip_import_errors: If True, modules that fail to import will be skipped.\n\nReturns:\n A Project instance containing the loaded modules."
|
|
},
|
|
"load_module": {
|
|
"name": "load_module",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.GriffeLoader.load_module",
|
|
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
|
|
"docstring": "Load a single module and convert its introspection data into the docforge models.\n\nArgs:\n path: The dotted path of the module to load.\n\nReturns:\n A Module instance."
|
|
}
|
|
}
|
|
},
|
|
"discover_module_paths": {
|
|
"name": "discover_module_paths",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.discover_module_paths",
|
|
"signature": "<bound method Alias.signature of Alias('discover_module_paths', 'docforge.loaders.discover_module_paths')>",
|
|
"docstring": "Discover all Python modules under a package via filesystem traversal.\n\nRules:\n- Directory with __init__.py is treated as a package.\n- Any .py file is treated as a module.\n- All paths are converted to dotted module paths.\n\nArgs:\n module_name: The name of the package to discover.\n project_root: The root directory of the project. Defaults to current working directory.\n\nReturns:\n A sorted list of dotted module paths."
|
|
},
|
|
"MCPRenderer": {
|
|
"name": "MCPRenderer",
|
|
"kind": "class",
|
|
"path": "docforge.cli.mcp_utils.MCPRenderer",
|
|
"signature": "<bound method Alias.signature of Alias('MCPRenderer', 'docforge.renderers.MCPRenderer')>",
|
|
"docstring": "Renderer that emits MCP-native JSON resources from docforge models.",
|
|
"members": {
|
|
"name": {
|
|
"name": "name",
|
|
"kind": "attribute",
|
|
"path": "docforge.cli.mcp_utils.MCPRenderer.name",
|
|
"signature": "<bound method Alias.signature of Alias('name', 'docforge.renderers.mcp_renderer.MCPRenderer.name')>",
|
|
"docstring": null
|
|
},
|
|
"generate_sources": {
|
|
"name": "generate_sources",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.MCPRenderer.generate_sources",
|
|
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.renderers.mcp_renderer.MCPRenderer.generate_sources')>",
|
|
"docstring": "Generate MCP-compatible JSON resources and navigation for the project.\n\nArgs:\n project: The project model to render.\n out_dir: Target directory for the generated JSON files."
|
|
}
|
|
}
|
|
},
|
|
"MCPServer": {
|
|
"name": "MCPServer",
|
|
"kind": "class",
|
|
"path": "docforge.cli.mcp_utils.MCPServer",
|
|
"signature": "<bound method Alias.signature of Alias('MCPServer', 'docforge.servers.MCPServer')>",
|
|
"docstring": "MCP server for serving a pre-built MCP documentation bundle.",
|
|
"members": {
|
|
"mcp_root": {
|
|
"name": "mcp_root",
|
|
"kind": "attribute",
|
|
"path": "docforge.cli.mcp_utils.MCPServer.mcp_root",
|
|
"signature": "<bound method Alias.signature of Alias('mcp_root', 'docforge.servers.mcp_server.MCPServer.mcp_root')>",
|
|
"docstring": null
|
|
},
|
|
"app": {
|
|
"name": "app",
|
|
"kind": "attribute",
|
|
"path": "docforge.cli.mcp_utils.MCPServer.app",
|
|
"signature": "<bound method Alias.signature of Alias('app', 'docforge.servers.mcp_server.MCPServer.app')>",
|
|
"docstring": null
|
|
},
|
|
"run": {
|
|
"name": "run",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.MCPServer.run",
|
|
"signature": "<bound method Alias.signature of Alias('run', 'docforge.servers.mcp_server.MCPServer.run')>",
|
|
"docstring": "Start the MCP server.\n\nArgs:\n transport: MCP transport (default: streamable-http)"
|
|
}
|
|
}
|
|
},
|
|
"generate_resources": {
|
|
"name": "generate_resources",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.generate_resources",
|
|
"signature": "<bound method Function.signature of Function('generate_resources', 7, 21)>",
|
|
"docstring": "Generate MCP-compatible documentation resources.\n\nArgs:\n module: The dotted path of the primary module to document.\n project_name: Optional override for the project name.\n out_dir: Directory where the MCP JSON resources and nav will be written."
|
|
},
|
|
"serve": {
|
|
"name": "serve",
|
|
"kind": "function",
|
|
"path": "docforge.cli.mcp_utils.serve",
|
|
"signature": "<bound method Function.signature of Function('serve', 23, 48)>",
|
|
"docstring": "Serve MCP documentation from a pre-built bundle.\n\nArgs:\n module: The dotted path of the primary module to serve.\n mcp_root: Path to the directory containing index.json, nav.json, and modules/."
|
|
}
|
|
}
|
|
}
|
|
} |