{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "fb299f86",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:46:52.976835Z",
     "iopub.status.busy": "2026-10-02T14:46:52.976632Z",
     "iopub.status.idle": "2026-10-02T14:46:52.980557Z",
     "shell.execute_reply": "2026-10-02T14:46:52.979899Z"
    },
    "papermill": {
     "duration": 0.006218,
     "end_time": "2026-10-02T14:46:52.981083+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:46:52.974865+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "active-ipynb",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    from openmdao.utils.notebook_utils import notebook_mode  # noqa: F401\n",
    "except ImportError:\n",
    "    !python -m pip install openmdao[notebooks]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "baf430bb",
   "metadata": {
    "papermill": {
     "duration": 0.113204,
     "end_time": "2026-10-02T14:46:53.095432+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:46:52.982228+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# Local Building of OpenMDAO Documentation\n",
    "\n",
    "When developing new features for OpenMDAO, it will be necessary to build the documents locally to ensure that code embedding, formatting, and links are all working as intended. The documentation uses Jupyter notebooks executed by [papermill](https://papermill.readthedocs.io/) and rendered to HTML by [Sphinx](https://www.sphinx-doc.org/) via [MyST-NB](https://myst-nb.readthedocs.io/).\n",
    "\n",
    "## Installation\n",
    "\n",
    "The doc build dependencies are included in the `docs` feature of the pixi environment. From the repository root, activate the dev environment:\n",
    "\n",
    "```bash\n",
    "pixi shell -e dev\n",
    "```\n",
    "\n",
    "Alternatively, install the docs extras directly with pip:\n",
    "\n",
    "```bash\n",
    "pip install -e .[docs]\n",
    "```\n",
    "\n",
    "## Building the Docs\n",
    "\n",
    "From the repository root, run:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs build\n",
    "```\n",
    "\n",
    "This runs the full pipeline:\n",
    "1. Disables SNOPT-specific cells\n",
    "2. Generates the API reference (`_srcdocs/`)\n",
    "3. Copies the source tree to `_executed_book/`\n",
    "4. Executes all notebooks with papermill\n",
    "5. Builds HTML with Sphinx\n",
    "\n",
    "The output is at `openmdao/docs/_executed_book/_build/html/main.html`.\n",
    "\n",
    "### Useful flags\n",
    "\n",
    "| Flag | Description |\n",
    "|------|-------------|\n",
    "| `--no-exec` | Skip notebook execution; re-run Sphinx on existing `_executed_book/` output. |\n",
    "| `--no-serial` | Skip serial (non-MPI) notebook execution. |\n",
    "| `--no-mpi` | Skip MPI notebook execution. |\n",
    "| `--fast` | Parallel Sphinx build (`-j auto`); also skips warnings-as-errors. |\n",
    "| `--workers N` | Number of parallel notebook execution workers (default: cpu count). |\n",
    "| `--no-rich` | Plain-text progress output (used on CI). |\n",
    "\n",
    "### Incremental builds\n",
    "\n",
    "Notebooks are skipped if their output in `_executed_book/` is already newer than the source. After editing a single notebook, re-running the build will only re-execute changed notebooks.\n",
    "\n",
    "To force re-execution of all notebooks regardless of timestamps:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs build --no-exec\n",
    "# then manually delete the specific notebook from _executed_book/ and re-run\n",
    "```\n",
    "\n",
    "Or simply remove the entire output tree and rebuild from scratch:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs clean\n",
    "python -m openmdao.devtools.build_docs build\n",
    "```\n",
    "\n",
    "## Viewing the Docs\n",
    "\n",
    "The built HTML can be opened directly as files in a browser, and most content will display correctly. However, some features — in particular, embedded N2 diagrams — are loaded via `<iframe>` and will not render when opened as `file://` URLs. This is a browser security restriction: browsers block cross-frame navigation between `file://` documents to prevent untrusted local files from accessing each other's content. The restriction applies even when both the page and the iframe source are in the same directory.\n",
    "\n",
    "To avoid this, serve the docs over HTTP using the `view` subcommand:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs view\n",
    "```\n",
    "\n",
    "This starts a local HTTP server and opens the docs in your default browser. An optional `--port` flag selects the port (default: 8000):\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs view --port 9000\n",
    "```\n",
    "\n",
    "Press Ctrl-C to stop the server when done.\n",
    "\n",
    "### Viewing a Downloaded CI Artifact\n",
    "\n",
    "GitHub Actions produces a built-docs artifact for every CI run. After downloading and unzipping the artifact, you can serve it the same way using the `--path` flag, pointing to either the artifact directory or the `main.html` file inside it:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs view --path ~/Downloads/built-docs-artifact\n",
    "```\n",
    "\n",
    "or:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs view --path ~/Downloads/built-docs-artifact/main.html\n",
    "```\n",
    "\n",
    "Note that simply opening the artifact files directly in a browser will have the same `file://` limitation described above — N2 diagrams will not render. Always use `view --path` to serve the artifact over HTTP.\n",
    "\n",
    "## MPI Examples\n",
    "\n",
    "The documentation includes several examples that demonstrate MPI features. These require MPI to be installed. MPI notebooks are identified by `\"mpi\": true` in the notebook's top-level metadata and are executed serially (one at a time) since each one internally spawns its own `mpiexec` subprocess.\n",
    "\n",
    "If you don't have MPI installed, use `--no-mpi` to skip them:\n",
    "\n",
    "```bash\n",
    "python -m openmdao.devtools.build_docs build --no-mpi\n",
    "```\n",
    "\n",
    "## Style Guide\n",
    "\n",
    "When writing new notebooks, refer to the [documentation style guide](doc_style_guide.ipynb)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.14"
  },
  "orphan": true,
  "papermill": {
   "default_parameters": {},
   "duration": 0.848402,
   "end_time": "2026-10-02T14:46:53.210773+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/other_useful_docs/developer_docs/doc_build.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/other_useful_docs/developer_docs/doc_build.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:46:52.362371+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}