| 1 | # How to Publish Docs on Learn |
| 2 | |
| 3 | Publishing documentation to [Learn](https://github.com/netdata/learn) involves a few key steps. Follow this guide carefully to avoid broken links or failed builds. |
| 4 | |
| 5 | :warning: **Before You Begin** |
| 6 | |
| 7 | - If you plan to unpublish a file, see [Unpublishing Files](#unpublishing-files) first. It requires extra steps. |
| 8 | - If you make large changes or move multiple docs, you must test with a local deployment of Learn. |
| 9 | |
| 10 | ## Steps to Publish |
| 11 | |
| 12 | ### Quick Checklist |
| 13 | |
| 14 | | Step | Action | Output | |
| 15 | |-------|-----------------------------------------------------------------------------------------|----------------------------------------------------------------| |
| 16 | | **1** | Edit `map.yaml` alongside your doc changes. Update nodes and ordering as needed. | Docs mapped with proper sidebar labels, paths, and edit links. | |
| 17 | | **2** | Test locally with the `ingest.py` script. Optionally run a full local Learn deployment. | Confirms no broken links or build errors. | |
| 18 | | **3** | Merge the Docs PR (requires approval). | Docs + `map.yaml` merged into the repo. | |
| 19 | | **4** | Inspect the automatic Learn ingest PR. Check files + deploy preview. | Verified preview of Learn with changes. | |
| 20 | | **5** | Merge the Learn ingest PR. | Docs officially live on Learn. | |
| 21 | |
| 22 | ### 1. Edit `map.yaml` |
| 23 | |
| 24 | All docs must be mapped in the [map.yaml](https://github.com/netdata/netdata/blob/master/docs/.map/map.yaml) file. The file is an ordered navigation tree under the top-level `sidebar:` key. |
| 25 | |
| 26 | Each node is either: |
| 27 | |
| 28 | - A **doc node** (with a `meta` object) |
| 29 | - A **category node** (with `meta` + `items`) |
| 30 | - An **integration placeholder** (`type: integration_placeholder`) |
| 31 | |
| 32 | #### `meta` fields |
| 33 | |
| 34 | | Field | Purpose | Notes | |
| 35 | |-----------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
| 36 | | **label** | The label shown in the sidebar. | For category overview pages, this should match the sidebar position. Categories are defined by having `items`. | |
| 37 | | **path** | Single path segment override (optional). | Used when the document's Learn path segment differs from the tree structure. Example: `OpenTelemetry` (not a full path). If omitted, the path is derived from the tree hierarchy. | |
| 38 | | **edit_url** | Full GitHub **Edit** link for the file. Used for the "Edit this page" button. | Must use the full link (supports repos beyond `netdata/netdata`). Can be omitted only for nodes with `integration_placeholder` children (the integrations themselves will have edit URLs). | |
| 39 | | **keywords** | List of keywords for search. | Example: `["install", "linux"]` | |
| 40 | | **description** | Legacy metadata description. | Rarely used today. | |
| 41 | |
| 42 | #### Path Reconstruction |
| 43 | |
| 44 | The full Learn path for each document is automatically reconstructed by walking the tree hierarchy and concatenating parent labels. The `path` field in `meta` is only needed when a document's path segment differs from its tree position. |
| 45 | |
| 46 | For example, a document appearing under "Collecting Metrics" in the sidebar with `path: OpenTelemetry` will have Learn path `OpenTelemetry` instead of `Collecting Metrics/OpenTelemetry Metrics`. |
| 47 | |
| 48 | #### Integration placeholder node |
| 49 | |
| 50 | ```yaml |
| 51 | - type: integration_placeholder |
| 52 | integration_kind: collectors |
| 53 | ``` |
| 54 | |
| 55 | Placeholders are positional: the ingest pipeline replaces them in-place with generated integration entries while preserving list order. |
| 56 | |
| 57 | #### Example node |
| 58 | |
| 59 | ```yaml |
| 60 | - meta: |
| 61 | label: "Linux" |
| 62 | edit_url: "https://github.com/netdata/netdata/edit/master/docs/installation/linux.md" |
| 63 | description: "How to install Netdata Agent on Linux" |
| 64 | keywords: |
| 65 | - "install" |
| 66 | - "linux" |
| 67 | ``` |
| 68 | |
| 69 | ### 2. Test the Changes |
| 70 | |
| 71 | Before merging, **always test the map file**. |
| 72 | |
| 73 | 1. Clone [Learn](https://github.com/netdata/learn) locally. |
| 74 | 2. Prepare environment and dependencies (see [ingest instructions](https://github.com/netdata/learn#ingest-and-process-documentation-files)). |
| 75 | 3. Run the ingest command: |
| 76 | |
| 77 | ```bash |
| 78 | python3 ingest/ingest.py --repos OWNEROFREPO/netdata:YOURBRANCH |
| 79 | ``` |
| 80 | |
| 81 | 4. Inspect the ingested changes. |
| 82 | 5. (Optional, advanced) [Deploy Learn](https://github.com/netdata/learn#local-deploy-of-learn) locally to confirm it builds correctly. |
| 83 | |
| 84 | ### 3. Merge the Docs PR |
| 85 | |
| 86 | - Submit your PR with the updated docs **and** `map.yaml`. |
| 87 | - Get at least one approval. |
| 88 | - **Reviewers expect you to have tested already**. Don’t rely on them to test. Please also mention it if you have done testing, so it is clear. |
| 89 | |
| 90 | ### 4. Merge the Learn Ingest PR |
| 91 | |
| 92 | Once your docs PR is merged: |
| 93 | |
| 94 | 1. The ingest action triggers in [netdata/learn](https://github.com/netdata/learn). |
| 95 | 2. A PR is created automatically. |
| 96 | 3. Inspect the changes. |
| 97 | 4. Wait for the deploy preview. |
| 98 | 5. Check the deploy preview carefully. |
| 99 | 6. If everything looks good → merge. |
| 100 | |
| 101 | 🍻 Done! |
| 102 | |
| 103 | ## Unpublishing Files |
| 104 | |
| 105 | If you **delete**, **move**, or **unpublish** a file, redirects may break. |
| 106 | |
| 107 | 1. Open [LegacyLearnCorrelateLinksWithGHURLs.json](https://github.com/netdata/learn/blob/master/LegacyLearnCorrelateLinksWithGHURLs.json). |
| 108 | 2. Search (`Ctrl+F`) for the old GitHub link. |
| 109 | 3. Update the entry to a relevant new location. |
| 110 | 4. If no suitable replacement exists → remove the entry. |