Skip to content

fix(website): give library-neutral docs pages an honest control plane - #920

Merged
blove merged 2 commits into
mainfrom
blove/docs-followups-adapter-page-mobile
Sep 1, 2026
Merged

fix(website): give library-neutral docs pages an honest control plane#920
blove merged 2 commits into
mainfrom
blove/docs-followups-adapter-page-mobile

Conversation

@blove

@blove blove commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Picks up the two follow-ups from #911. Re-checking them against main first changed both, so this PR is not quite what those notes described.

One follow-up was already done

"There is no docs nav below lg" is fixed#892 added a mobile drawer. That note was taken against the pre-#892 tree.

"/docs has no control plane" is not a defect. /docs is a designed landing page — "Start building with Threadplane", pick-your-backend cards. It's the front door; a sidebar would damage it. Left alone.

What the re-check found instead

On /docs/choosing-an-adapter at 375px, the drawer's Scope card read:

LangGraph / Getting Started / Documentation

Three fabrications in the one card whose job is telling you where you are. Nav.tsx derives the library from pathParts[1] — here "choosing-an-adapter", not a library — so getLibraryConfig() returned undefined and the code fell back to 'langgraph'. The drawer then showed LangGraph's picker, LangGraph's entire section tree, and a title of "Documentation".

The failure mode is silence: it renders something plausible.

Root cause: the control plane had no "no library selected" state, so every caller had to invent one.

The fix

activeLibrary becomes LibraryId | null through DocsControlPlane and DocsNavigation. Neutral pages get Docs / <page> in Scope, a Choose a library picker with nothing checked, and no section tree. Nav stops defaulting and resolves special-page titles — correcting the drawer on every library-neutral route, not just this one.

/docs/choosing-an-adapter, mobile Before After
Scope LangGraph / Getting Started / Documentation Docs / Choosing an adapter
Picker LangGraph Choose a library
Section tree LangGraph's, in full none

The page was also bespoke

That drift produced the rest of its symptoms. It now uses the same shell as every other docs page, which:

  • gives it the control plane it never had;
  • deletes an empty hero Section that opened a measured 144px gap above the H1, and whose empty <div> was the target of aria-labelledby — leaving the section with no accessible name at all;
  • replaces ~60 duplicated lines of MDX pipeline with the existing MdxRenderer.

MdxRenderer's library/section/slug/title props were accepted and never read — four of the website's lint warnings. Dropped. The blog route was passing library="langgraph" for blog posts, which only ever looked harmless because the value was discarded.

Testing

404 tests pass, 0 lint errors, production build green.

Nav.spec.tsx'does not invent a library on a library-neutral docs page' is the one that matters — it fails against main with expected <span></span> to be null, catching the fabricated LangGraph. The existing 'shows truthful scope and collapsed environment defaults' doubles as the regression guard that real library pages are untouched; verified in the browser too (LangGraph / Guides / Streaming, picker and tree intact).

Design spec: docs/superpowers/specs/2026-09-01-docs-library-neutral-pages-design.md.

🤖 Generated with Claude Code

blove and others added 2 commits August 31, 2026 21:21
Records the design for /docs/choosing-an-adapter and the control plane's
missing "no library selected" state. Also records that one of the two
follow-ups behind this work was already fixed by #892, and that /docs is
a landing page rather than a page missing its shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
On /docs/choosing-an-adapter the mobile drawer's Scope card read
"LangGraph / Getting Started / Documentation" — three fabrications in
the one card whose job is saying where you are. Nav derives the library
from the second path segment, which on that URL is
"choosing-an-adapter"; getLibraryConfig returns undefined and the code
fell back to 'langgraph', so the drawer showed LangGraph's picker and
its whole section tree.

The cause is that the control plane had no "no library selected" state,
so every caller had to invent one. Adds it:

- activeLibrary is now LibraryId | null through DocsControlPlane and
  DocsNavigation. Neutral pages show "Docs / <page>" in Scope, a
  "Choose a library" picker with nothing checked, and no section tree.
- Nav stops defaulting to langgraph and resolves special-page titles,
  which corrects the drawer on every library-neutral route.

/docs/choosing-an-adapter was also bespoke, and that drift is what
produced the rest of its symptoms. It now uses the same shell as every
other docs page, which:

- gives it the control plane it never had,
- deletes an empty hero Section that opened a measured 144px gap above
  the H1 and whose empty div was the target of aria-labelledby, leaving
  the section with no accessible name,
- replaces ~60 duplicated lines of MDX pipeline with MdxRenderer.

MdxRenderer's library/section/slug/title props were accepted and never
read — four of the website's lint warnings. Dropped. The blog route was
passing library="langgraph" for blog posts, which only ever looked
harmless because the value was discarded.

/docs keeps its landing-page treatment; it is the front door, not a
page missing its shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadplane Ready Ready Preview Sep 1, 2026 4:24am UTC

Request Review

@blove
blove enabled auto-merge (squash) September 1, 2026 04:23

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit d99daae into main Sep 1, 2026
24 checks passed
blove added a commit that referenced this pull request Sep 1, 2026
/docs was the only /docs/* route without the control plane. That was a
deliberate call in #920 — it is a designed landing page, and the prose
column would flatten its card grids — but the inconsistency reads worse
than that risk.

It now renders the docs shell with activeLibrary={null}, reusing the
library-neutral state from #920. The landing content sits inside
docs-shell-body but outside the [slug] route's md:max-w-3xl article
measure, so the grids keep their own width: verified still 2-up at 426px
on desktop and single-column at 375px.

The sidebar picker is kept even though the page's main content is itself
a backend picker. #911 removed a duplication of exactly this shape, so
to be explicit: that was two statements of the same fact, this is a
statement plus a shortcut for a reader who already knows where they are
going.

Also renames the render library's display label to json-render. It is
called that 85 times across docs content, on the marketing page, and on
the /docs card; "Render" existed only in docsConfig, feeding the picker,
breadcrumbs, structured data and search. With the control plane on this
page both labels are on screen at once. The package stays
@threadplane/render and the URL stays /docs/render/.

Two drifts found while building this:

- The page passed pageTitle="Overview" while Nav resolved the drawer's
  title independently and got "Documentation" — the same page named two
  ways by viewport width. Both now read a shared DOCS_INDEX_TITLE.
- e2e asserted getByText('Render'), which passed on a substring of
  json-render and would now also pass on the sidebar. It asserts card
  titles instead, and covers the Chat card again.

Every new guard was mutation-tested. The naming test initially passed
against a reverted docsConfig: getAllByText is exact-match and the
picker menu is closed on mount, so it only ever saw the index card.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@blove
blove deleted the blove/docs-followups-adapter-page-mobile branch September 1, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant