|
| 1 | +# Aligning the docs index with the control plane |
| 2 | + |
| 3 | +**Date:** 2026-09-01 |
| 4 | +**Scope:** `/docs`, and the `Render` / `json-render` naming split |
| 5 | +**Status:** approved, ready to implement |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +After #920, `/docs` is the only `/docs/*` route without the control plane. That |
| 10 | +was a deliberate call at the time — it is a designed landing page, and forcing |
| 11 | +its 2-up card grids into the prose column would flatten it. In review the |
| 12 | +inconsistency was judged worse than that risk, so the page adopts the shell. |
| 13 | + |
| 14 | +## Design |
| 15 | + |
| 16 | +### The shell, without the prose measure |
| 17 | + |
| 18 | +`/docs` renders `docs-shell-page` with `<DocsControlPlane activeLibrary={null}>`, |
| 19 | +reusing the library-neutral state added in #920. |
| 20 | + |
| 21 | +The landing content goes inside `docs-shell-body` but **not** inside the |
| 22 | +`md:max-w-3xl` article measure the `[slug]` route uses. Its `Section`/`Container` |
| 23 | +structure keeps its own width. The chrome becomes consistent; the layout does |
| 24 | +not get squeezed. |
| 25 | + |
| 26 | +Scope reads `Docs / Overview`. Passing the page title verbatim would render |
| 27 | +`Docs / Documentation`, which is redundant. |
| 28 | + |
| 29 | +`Nav` resolves the drawer's title independently of the page, so setting this on |
| 30 | +the page alone made the desktop say `Docs / Overview` while the mobile drawer |
| 31 | +said `Docs / Documentation` — the same page named two ways by viewport width. |
| 32 | +Both now read a shared `DOCS_INDEX_TITLE` constant so they cannot drift. |
| 33 | + |
| 34 | +### The picker stays, deliberately |
| 35 | + |
| 36 | +The page's main content *is* a backend picker, so the sidebar picker is |
| 37 | +arguably duplicative — the same class of problem removed in #911, where the |
| 38 | +library was stated twice. |
| 39 | + |
| 40 | +Kept anyway, because the two do different jobs: the cards are a decision aid |
| 41 | +(compare, copy the install line, follow the quickstart), the picker is a |
| 42 | +shortcut for a returning reader who already knows where they are going. The |
| 43 | +#911 duplication was two *statements of the same fact*; this is a statement and |
| 44 | +a shortcut. |
| 45 | + |
| 46 | +### `Render` → `json-render` |
| 47 | + |
| 48 | +The library is called `json-render` 85 times across docs content and on the |
| 49 | +marketing page, and on the `/docs` card. It is called `Render` in exactly one |
| 50 | +place: `docsConfig[].title`, which feeds the picker, breadcrumbs, structured |
| 51 | +data and search. |
| 52 | + |
| 53 | +Once the index has the control plane, both names appear on screen at once — the |
| 54 | +sidebar saying `Render`, the card saying `json-render`. |
| 55 | + |
| 56 | +`docsConfig` title becomes `json-render`. The package stays |
| 57 | +`@threadplane/render` and the URL stays `/docs/render/`; only the display label |
| 58 | +changes. Marketing surfaces (`/render`, the footer, `solutions-data`) keep |
| 59 | +`Render` — those describe the product page, a different context, and are not |
| 60 | +part of this alignment. |
| 61 | + |
| 62 | +### Test hygiene |
| 63 | + |
| 64 | +`e2e/website.spec.ts` → `'docs landing page shows library cards'` asserts |
| 65 | +`getByText('Render')`, which passes on a substring of `json-render` and would |
| 66 | +also pass on the new sidebar. It is tightened to assert the cards themselves. |
| 67 | + |
| 68 | +## Testing |
| 69 | + |
| 70 | +1. **The index renders the control plane** with a library-neutral Scope of |
| 71 | + `Docs / Overview` and a `Choose a library` picker. |
| 72 | +2. **The picker reads `json-render`**, not `Render`. |
| 73 | +3. **The landing content keeps its width** — it is not inside the article |
| 74 | + measure. |
| 75 | +4. **The drawer and the page agree on the index's name.** |
| 76 | + |
| 77 | +Each guard was mutation-tested. The naming test initially passed against a |
| 78 | +reverted `docsConfig` — `getAllByText` is exact-match and the picker menu is |
| 79 | +closed on mount, so it only ever saw the index card. It now opens the menu |
| 80 | +first. |
| 81 | + |
| 82 | +## Out of scope |
| 83 | + |
| 84 | +Marketing surfaces keep `Render`. Renaming those is a product-vocabulary |
| 85 | +decision about the `/render` page, not about docs consistency. |
0 commit comments