| 1 | # Sidebars |
| 2 | |
| 3 | The Learn site sidebar is **autogenerated** from the |
| 4 | filesystem. Order is driven by `sidebar_position` frontmatter |
| 5 | that ingest assigns from `map.yaml` traversal order. |
| 6 | |
| 7 | ## `sidebars.js` is one line |
| 8 | |
| 9 | `${NETDATA_REPOS_DIR}/learn/sidebars.js:12-19`: |
| 10 | |
| 11 | ```js |
| 12 | module.exports = { sidebar: [{ "type": "autogenerated", "dirName": "." }] }; |
| 13 | ``` |
| 14 | |
| 15 | Docusaurus walks `docs/` and builds the entire sidebar from |
| 16 | filesystem structure plus per-file frontmatter. There is NO |
| 17 | manual sidebar list. |
| 18 | |
| 19 | ## Ordering rules |
| 20 | |
| 21 | Per Docusaurus, the displayed order in each parent scope is |
| 22 | controlled by: |
| 23 | |
| 24 | 1. **Frontmatter `sidebar_label`** -- set by ingest from |
| 25 | `map.yaml`'s `meta.label`. |
| 26 | |
| 27 | 2. **Frontmatter `sidebar_position`** -- set by |
| 28 | `automate_sidebar_position` (`ingest.py:2238-2299`) and then |
| 29 | re-normalized per parent scope by |
| 30 | `normalize_sidebar_positions_by_parent` (`ingest.py:425-519`). |
| 31 | Values are assigned in steps of 10 within each parent scope; |
| 32 | map-derived order wins, then alphabetical fallback. |
| 33 | |
| 34 | 3. **`_category_.json`** (Docusaurus convention) -- written by |
| 35 | `ensure_category_json_for_dirs` (`ingest.py:336-382`) for |
| 36 | any subdirectory that contains `.mdx` files but no overview |
| 37 | file. Format: `{label, position}`. Currently only one in |
| 38 | the live tree: `docs/Collecting Metrics/OpenTelemetry/_category_.json`. |
| 39 | |
| 40 | 4. **Section overview pages** -- when a directory has |
| 41 | `<dir>/<dir>.mdx`, it acts as the category landing page |
| 42 | (Docusaurus convention) AND is routed to the parent URL via |
| 43 | the duplicate-segment slug trim (`mapping.md`). |
| 44 | |
| 45 | 5. **Auto-generated grid pages** -- |
| 46 | `get_dir_make_file_and_recurse` (`ingest.py:2333-2510`) |
| 47 | creates `<dir>/<dir>.mdx` for any directory that contains |
| 48 | integration pages and has no overview file. The generated |
| 49 | MDX uses `<Grid columns="4">` with `<Box ...>` children |
| 50 | (the `Grid_integrations` component), and carries |
| 51 | `learn_status: AUTOGENERATED` plus computed `slug:` and |
| 52 | `learn_link:`. |
| 53 | |
| 54 | ## Special rule: "Ask Nedi" pinned to position 0 |
| 55 | |
| 56 | `automate_sidebar_position` (`ingest.py:493-512`) forces a |
| 57 | top-level page whose `sidebar_label` is "Ask Nedi" to position |
| 58 | 0. The "Ask Nedi" entrypoint is |
| 59 | `${NETDATA_REPOS_DIR}/learn/docs/ask-nedi.mdx`. Other top-level |
| 60 | entries cannot occupy position 0; they get >= 10. |
| 61 | |
| 62 | `docs/ask-nedi.mdx` is the only file currently flagged |
| 63 | `part_of_learn: True` -- meaning it's hand-authored in the |
| 64 | learn repo and survives the cleanup step. See |
| 65 | `authoring-boundary.md`. |
| 66 | |
| 67 | ## Section landing page convention |
| 68 | |
| 69 | When a directory has a file matching `<dir>/<dir>.mdx`: |
| 70 | |
| 71 | - Docusaurus treats it as the category landing page. |
| 72 | - `add_new_learn_path_key_to_dict` (`ingest.py:1862-1876`) |
| 73 | removes the duplicate dir segment from the URL. |
| 74 | - So `docs/Collecting Metrics/Collecting Metrics.mdx` is |
| 75 | routed to `/docs/collecting-metrics` (parent URL), not |
| 76 | `/docs/collecting-metrics/collecting-metrics`. |
| 77 | |
| 78 | This is how every category gets a landing page that displays |
| 79 | when the user clicks the parent in the sidebar. |
| 80 | |
| 81 | For directories WITHOUT an overview file, a `_category_.json` |
| 82 | is generated to provide a label and position (otherwise |
| 83 | Docusaurus uses the directory name verbatim, which often has |
| 84 | poor casing/spacing). |
| 85 | |
| 86 | ## Auto-grid generation |
| 87 | |
| 88 | `get_dir_make_file_and_recurse` (`ingest.py:2333-2510`) walks |
| 89 | `docs/` after publication. For directories that contain |
| 90 | integration pages (matched by their `<!--startmeta` blocks) |
| 91 | but lack a `<dir>/<dir>.mdx` overview file: |
| 92 | |
| 93 | 1. Generate an MDX file with a `<Grid_integrations>` component |
| 94 | listing the integrations in that directory. |
| 95 | 2. `learn_status: AUTOGENERATED` is set in the frontmatter. |
| 96 | 3. `slug:` and `learn_link:` are computed and injected. |
| 97 | |
| 98 | If a directory contains EXACTLY one published integration plus |
| 99 | zero non-integration content, the script special-cases that as |
| 100 | content-leaf and skips the grid (`ingest.py:2429-2503`). |
| 101 | Adding/removing files can flip a directory between "grid" and |
| 102 | "leaf" presentations. See `pitfalls-and-gotchas.md`. |
| 103 | |
| 104 | ## Top-level vs nested |
| 105 | |
| 106 | There is no structural difference between top-level and nested |
| 107 | sections, except for the "Ask Nedi" position-0 rule, which |
| 108 | applies only to the root scope. All other scopes are ordered by |
| 109 | map traversal first, alphabetical second. |
| 110 | |
| 111 | ## To reorder the sidebar |
| 112 | |
| 113 | You do NOT edit `sidebars.js`. You reorder the rows in |
| 114 | `<repo>/docs/.map/map.yaml`. Ingest re-runs |
| 115 | `automate_sidebar_position`, which assigns new |
| 116 | `sidebar_position` values. Docusaurus rebuilds with the new |
| 117 | order on the next ingest cycle. |
| 118 | |
| 119 | ## Common mistakes |
| 120 | |
| 121 | - **Editing `sidebars.js` directly.** The file is one line and |
| 122 | not consulted for ordering. Useless. |
| 123 | - **Editing `_category_.json` files in the learn repo.** These |
| 124 | get overwritten on the next ingest run (`safe_cleanup_learn_folders` |
| 125 | deletes ALL `.json` files unconditionally -- not just |
| 126 | non-`part_of_learn` ones; see `pitfalls-and-gotchas.md`). |
| 127 | The right fix is to put the page in `map.yaml` so the |
| 128 | sidebar position comes from there. |
| 129 | - **Setting `sidebar_position: 0` in the source frontmatter.** |
| 130 | It is overwritten by ingest's `automate_sidebar_position`. |
| 131 | And the value 0 is reserved for "Ask Nedi" at the top level |
| 132 | -- any conflict gets re-stamped to >= 10. |
| 133 | - **Empty directory expectations.** Empty directories |
| 134 | disappear from the sidebar (Docusaurus drops them). Removing |
| 135 | the last doc in a category removes the category from the |
| 136 | sidebar. |