# Sidebars

The Learn site sidebar is **autogenerated** from the
filesystem. Order is driven by `sidebar_position` frontmatter
that ingest assigns from `map.yaml` traversal order.

## `sidebars.js` is one line

`${NETDATA_REPOS_DIR}/learn/sidebars.js:12-19`:

```js
module.exports = { sidebar: [{ "type": "autogenerated", "dirName": "." }] };
```

Docusaurus walks `docs/` and builds the entire sidebar from
filesystem structure plus per-file frontmatter. There is NO
manual sidebar list.

## Ordering rules

Per Docusaurus, the displayed order in each parent scope is
controlled by:

1. **Frontmatter `sidebar_label`** -- set by ingest from
   `map.yaml`'s `meta.label`.

2. **Frontmatter `sidebar_position`** -- set by
   `automate_sidebar_position` (`ingest.py:2238-2299`) and then
   re-normalized per parent scope by
   `normalize_sidebar_positions_by_parent` (`ingest.py:425-519`).
   Values are assigned in steps of 10 within each parent scope;
   map-derived order wins, then alphabetical fallback.

3. **`_category_.json`** (Docusaurus convention) -- written by
   `ensure_category_json_for_dirs` (`ingest.py:336-382`) for
   any subdirectory that contains `.mdx` files but no overview
   file. Format: `{label, position}`. Currently only one in
   the live tree: `docs/Collecting Metrics/OpenTelemetry/_category_.json`.

4. **Section overview pages** -- when a directory has
   `<dir>/<dir>.mdx`, it acts as the category landing page
   (Docusaurus convention) AND is routed to the parent URL via
   the duplicate-segment slug trim (`mapping.md`).

5. **Auto-generated grid pages** --
   `get_dir_make_file_and_recurse` (`ingest.py:2333-2510`)
   creates `<dir>/<dir>.mdx` for any directory that contains
   integration pages and has no overview file. The generated
   MDX uses `<Grid columns="4">` with `<Box ...>` children
   (the `Grid_integrations` component), and carries
   `learn_status: AUTOGENERATED` plus computed `slug:` and
   `learn_link:`.

## Special rule: "Ask Nedi" pinned to position 0

`automate_sidebar_position` (`ingest.py:493-512`) forces a
top-level page whose `sidebar_label` is "Ask Nedi" to position
0. The "Ask Nedi" entrypoint is
`${NETDATA_REPOS_DIR}/learn/docs/ask-nedi.mdx`. Other top-level
entries cannot occupy position 0; they get >= 10.

`docs/ask-nedi.mdx` is the only file currently flagged
`part_of_learn: True` -- meaning it's hand-authored in the
learn repo and survives the cleanup step. See
`authoring-boundary.md`.

## Section landing page convention

When a directory has a file matching `<dir>/<dir>.mdx`:

- Docusaurus treats it as the category landing page.
- `add_new_learn_path_key_to_dict` (`ingest.py:1862-1876`)
  removes the duplicate dir segment from the URL.
- So `docs/Collecting Metrics/Collecting Metrics.mdx` is
  routed to `/docs/collecting-metrics` (parent URL), not
  `/docs/collecting-metrics/collecting-metrics`.

This is how every category gets a landing page that displays
when the user clicks the parent in the sidebar.

For directories WITHOUT an overview file, a `_category_.json`
is generated to provide a label and position (otherwise
Docusaurus uses the directory name verbatim, which often has
poor casing/spacing).

## Auto-grid generation

`get_dir_make_file_and_recurse` (`ingest.py:2333-2510`) walks
`docs/` after publication. For directories that contain
integration pages (matched by their `<!--startmeta` blocks)
but lack a `<dir>/<dir>.mdx` overview file:

1. Generate an MDX file with a `<Grid_integrations>` component
   listing the integrations in that directory.
2. `learn_status: AUTOGENERATED` is set in the frontmatter.
3. `slug:` and `learn_link:` are computed and injected.

If a directory contains EXACTLY one published integration plus
zero non-integration content, the script special-cases that as
content-leaf and skips the grid (`ingest.py:2429-2503`).
Adding/removing files can flip a directory between "grid" and
"leaf" presentations. See `pitfalls-and-gotchas.md`.

## Top-level vs nested

There is no structural difference between top-level and nested
sections, except for the "Ask Nedi" position-0 rule, which
applies only to the root scope. All other scopes are ordered by
map traversal first, alphabetical second.

## To reorder the sidebar

You do NOT edit `sidebars.js`. You reorder the rows in
`<repo>/docs/.map/map.yaml`. Ingest re-runs
`automate_sidebar_position`, which assigns new
`sidebar_position` values. Docusaurus rebuilds with the new
order on the next ingest cycle.

## Common mistakes

- **Editing `sidebars.js` directly.** The file is one line and
  not consulted for ordering. Useless.
- **Editing `_category_.json` files in the learn repo.** These
  get overwritten on the next ingest run (`safe_cleanup_learn_folders`
  deletes ALL `.json` files unconditionally -- not just
  non-`part_of_learn` ones; see `pitfalls-and-gotchas.md`).
  The right fix is to put the page in `map.yaml` so the
  sidebar position comes from there.
- **Setting `sidebar_position: 0` in the source frontmatter.**
  It is overwritten by ingest's `automate_sidebar_position`.
  And the value 0 is reserved for "Ask Nedi" at the top level
  -- any conflict gets re-stamped to >= 10.
- **Empty directory expectations.** Empty directories
  disappear from the sidebar (Docusaurus drops them). Removing
  the last doc in a category removes the category from the
  sidebar.
