The framework picker (sidebar + dropdown) and docs landing integration
grid previously rendered initials-as-image fallbacks (e.g. 'LG', 'Ma',
'Py') from /logos/<slug>.svg placeholder files. Replace with inline
SVG icons that use currentColor so they tint with the surrounding
text and adapt to light/dark mode.
Covers langgraph (python/typescript/fastapi), mastra, pydantic-ai,
crewai, agno, ag2, llamaindex, strands, google-adk, microsoft (ms-
agent-python/dotnet), claude-sdk (anthropic mark), and spring-ai.
Slugs without a branded mark fall through to the existing placeholder
SVG (currently only langroid).
Mirrors the upstream docs nav by adding a Free Developer Access link
to cloud.copilotkit.ai in the BrandNav, persistent across both the
CopilotKit and AG-UI tabs. Renders with cloud icon + external-link
arrow on desktop (icon-only below 1100px) and as a row in the mobile
slide-out menu.
The previous commit (993746111) bundled image fixes with a structural
nav change that wasn't asked for. The ask was simply "rename the page
to Overview so there is no duplicated item in the nav" — a frontmatter
title change, nothing more.
Reverting just the structural pieces:
- agentic-protocols/overview.mdx → index.mdx (back to original filename)
- agentic-protocols/meta.json: pages list back to ["index", ...]
- top-level meta.json: drop "---Agentic Protocols---" section header so
agentic-protocols stays as a subgroup under Get Started
- next.config.ts: drop the new /agentic-protocols → /overview redirect;
restore /concepts/agentic-protocols and /learn/agentic-protocols
redirect targets to /agentic-protocols (not /overview)
The page's frontmatter title stays "Overview" — that part of 993746111
was the actual ask and it solves the duplicate-label problem on its own.
Image fixes from 993746111 are kept.
## Replaced 11 LFS-pointer-stub images with real binaries
The repo stores several diagram PNGs in Git LFS and the local clone
didn't have them resolved (git-lfs not installed). They were 131-byte
text-pointer files on disk, so every page that referenced them
showed a broken-image icon. Affected images:
- any-agentic-backend-{light,dark}.png (used on /agentic-protocols
overview, /agentic-protocols/a2a, /agentic-protocols/mcp)
- agui-ecosystem-{light,dark}.png (/agentic-protocols/ag-ui)
- mcp-and-a2a-through-agui-{light,dark}.png (overview)
- gen-ui-specs-{light,dark}.png (/concepts/generative-ui-overview)
- ai-protocol-stack.png, ag-ui-overview-with-partners-dark.png,
a2ui-composer.png (referenced from various promoted pages)
- generative-ui/{chat,chat-plus,chatless}-surface.png (the surfaces
section in /concepts/generative-ui-overview — these were missing
from public/images entirely after the gen-UI merge; copied from
upstream first, then replaced with the real binaries from the live
docs site since upstream's copies are also LFS stubs)
Source: production docs site at docs.copilotkit.ai/images/* (HTTP 200
on every file). Pulled via curl, sizes range 128KB–714KB — real
binaries, not pointers.
## Agentic Protocols promoted to its own section
Per design call: "Agentic Protocols" is now a top-level section
between Get Started and Build Chat UIs (was wedged into Get Started
as a spread group, which produced an awkward duplicate label —
"Agentic Protocols" group label with an "Agentic Protocols" page
entry inside it).
Changes:
- `agentic-protocols/index.mdx` renamed to `overview.mdx` so the
nav slug is `/agentic-protocols/overview` (was the ugly
`/agentic-protocols/index` because buildNavTree pushed `"index"`
through as a literal slug).
- The page's frontmatter title is now "Overview" (was "Agentic
Protocols", which duplicated the section header in the nav).
- `agentic-protocols/meta.json` lists `["overview", "ag-ui", "mcp",
"a2a"]`.
- Top-level `meta.json` adds `---Agentic Protocols---` section header
before the spread, dropping the wedged `...agentic-protocols` from
inside Get Started.
- `next.config.ts` adds `/agentic-protocols → /agentic-protocols/overview`
redirect (the bare path used to resolve via `index.mdx`; now needs
to land on the renamed overview page). The earlier `/learn/...`
and `/concepts/...` redirects for the same target updated to point
at `/overview` directly.
## Sidebar reads cleanly now
GET STARTED
Quickstart, Coding Agents, Concepts (3-page subgroup)
AGENTIC PROTOCOLS
Overview, AG-UI, MCP, A2A
BUILD CHAT UIS
...
The first Accordion body wrapped two paragraphs of prose in a manual
`<p>...</p>` tag. MDX auto-wraps each blank-line-separated paragraph
in its own `<p>`, so the rendered output became `<p><p>...</p><p>...</p></p>`
— invalid HTML and a hydration error in the browser.
Removed the outer `<p>` wrapper; the prose now relies on MDX's
default paragraph wrapping. Also fixed a typo in the same block
("a server the suits your needs" → "a server that suits your needs").
Inherited from the upstream `learn/connect-mcp-servers.mdx` source.
Verified zero nested-`<p>` occurrences across all 13 of the
moved/promoted pages on this branch.
Tightens the Concepts subgroup (which had ballooned to 10 entries
after the /learn/ consolidation) and gives the protocol pages and
Enterprise-flavoured explanation pages the homes they actually
belong in.
## Structural changes
**New `Agentic Protocols` section under Get Started.** The four
protocol-related pages move from `/concepts/*` into a dedicated
`/agentic-protocols/` folder so they live as a coherent section
rather than as four siblings inside Concepts. Titles drop the
`(Agents<->X)` parenthetical — folder + section context already
disambiguates.
/concepts/agentic-protocols → /agentic-protocols (now the section overview)
/concepts/ag-ui-protocol → /agentic-protocols/ag-ui
/concepts/mcp-servers → /agentic-protocols/mcp
/concepts/a2a-protocol → /agentic-protocols/a2a
`agentic-protocols/meta.json` lists the four pages with the section
overview as `index`. Top-level `meta.json` adds `...agentic-protocols`
under Get Started.
**Intelligence Platform + Threads explanation pages move to
Enterprise.** Both pages document Premium-only architecture
(threads + the platform that hosts them); they belong next to the
how-to and self-hosting pages, not in framework-agnostic Concepts.
/concepts/intelligence-platform → /premium/intelligence-platform
/concepts/threads → /premium/threads-explained
(renamed to disambiguate from
the existing how-to /threads)
`premium/meta.json` reordered so the explanation pages sit between
the overview and the how-to pages.
**Generative UI Overview merged.** The old
`concepts/generative-ui-overview.mdx` (long, with surfaces /
attributes / patterns / ecosystem mapping sections, but using
inconsistent terminology — "Static" vs "Controlled") and
`concepts/three-types-of-gen-ui.mdx` (concise, sharp prose, canonical
"Controlled / Declarative / Open-Ended" terminology that matches the
Build Generative UI nav section names) overlapped substantially.
Merged into a single `concepts/generative-ui-overview.mdx` with:
- Tight intro from three-types
- Application Surfaces section (chat / chat+ / chatless) from overview
— unique value, not duplicated elsewhere
- Three types section using three-types' prose + terminology, with
the tradeoff bullets borrowed from overview's PatternCard component
- Ecosystem Mapping table from overview, retitled with the unified
terminology
- "AG-UI / CopilotKit are gen-UI agnostic" closer with the dual
light/dark image
- "Where to go next" pointers for downstream guides
three-types-of-gen-ui deleted; redirect catches any inbound link.
## `<Image>` registry fix (load-bearing)
The MDX `<Image>` component was registered to destructure only `src`
and `alt`, silently dropping `className`. Every page that ships dual
light/dark variants (`block dark:hidden` / `hidden dark:block`)
rendered both versions stacked — the user-visible "duplicate image"
on agentic-protocols (and the same shape on ag-ui, a2a, mcp, the
gen-UI overview).
Updated the registry component to forward `className`, `width`, and
`height`. The dark/light Tailwind toggling now works as authored.
## Concepts post-restructure
After the moves, the Concepts subgroup is back to a focused set:
architecture
generative-ui-overview
oss-vs-enterprise
These are the framework-agnostic 5-minute primers under Get Started.
Everything that was specifically about a protocol, the Intelligence
Platform, or threads has a more accurate home.
## Redirects
Per-path rules in `next.config.ts` for every URL that was live
between the /learn/ consolidation pass and this restructure:
/concepts/agentic-protocols → /agentic-protocols
/concepts/ag-ui-protocol → /agentic-protocols/ag-ui
/concepts/mcp-servers → /agentic-protocols/mcp
/concepts/a2a-protocol → /agentic-protocols/a2a
/concepts/intelligence-platform → /premium/intelligence-platform
/concepts/threads → /premium/threads-explained
/concepts/three-types-of-gen-ui → /concepts/generative-ui-overview
The earlier /learn/ rules also rewritten to point straight at the
new canonical homes (avoiding 308→308 chains).
## Inbound link rewrites
All cross-page links in the moved pages, plus the architecture
concept page, oss-vs-enterprise concept page, threads how-to,
premium/self-hosting, useCapabilities reference, and the snippets
that referenced the old `/concepts/*` paths. Verified zero remaining
references to the old URLs (except the irrelevant external
`learn.microsoft.com` URLs in MS Agent Framework integration pages).
## Smoke tested
All 9 new canonical URLs return 200. All 10 sampled redirects
(7 /concepts/* + 3 /learn/*) hit the right destination in one hop.
The upstream `/learn/*` tree was largely a Diátaxis explanation-tier
parallel to the rest of the docs, and after the IA restructure shipped
the Concepts subgroup under Get Started in PR #4329, /learn/* read as
visible duplication: two "Threads" entries, two "Architecture"
entries, two "AG-UI" pages, etc. The earlier Notion plan kept the
split and proposed a nav-label fix; this PR reverses that call and
folds the explanation pages into Concepts where they belong.
## What moved
**Promoted to /concepts/** (7 files):
- learn/threads.mdx → concepts/threads.mdx
- learn/intelligence-platform.mdx → concepts/intelligence-platform.mdx
- learn/agentic-protocols.mdx → concepts/agentic-protocols.mdx
- learn/ag-ui-protocol.mdx → concepts/ag-ui-protocol.mdx
- learn/a2a-protocol.mdx → concepts/a2a-protocol.mdx
- learn/connect-mcp-servers.mdx → concepts/mcp-servers.mdx (renamed)
- learn/generative-ui/index.mdx → concepts/generative-ui-overview.mdx
The new Concepts subgroup is a 10-page cluster covering architecture,
the Intelligence Platform, the three gen-UI types + a deep overview,
the four agentic protocols (AG-UI, MCP, A2A, plus the meta page), and
threads + OSS-vs-Enterprise. Ordered by topic flow rather than
alphabetically.
**Moved to natural homes**:
- learn/tutorials/multi-conversation-chat.mdx → tutorials/multi-conversation-chat.mdx
- learn/generative-ui/specs/open-json-ui.mdx → generative-ui/open-json-ui.mdx (added under "Declarative" in the gen-UI nav alongside A2UI)
**Promoted to top-level /whats-new/**: 7 files. New top-level
nav section between Tutorials and Migrate. Release-cadence content
doesn't belong inside Concepts; promoting it gives it room to grow as
a real changelog.
**Deleted** (5 files, all stubs or duplicates):
- learn/index.mdx (the Learn landing — its card grid pointed at the
pages above, all of which now live elsewhere)
- learn/architecture.mdx (15L stub: just a heading + the same
ImageZoom that already lives in /concepts/architecture)
- learn/generative-ui/specs/{index, a2ui, mcp-apps}.mdx (7-line
component-stubs already covered by their canonical
/generative-ui/* pages)
- learn/generative-ui/{meta.json, specs/meta.json} + learn/meta.json
(now-empty meta scaffolding)
## Nav updates
- concepts/meta.json grows to 10 pages, ordered by topic cluster
- tutorials/meta.json adds multi-conversation-chat
- generative-ui/meta.json adds open-json-ui under "Declarative"
- whats-new/meta.json gets a clean "What's New" title (was a dated
"Updates - Jan 22, 2025") + the full file list in reverse-chrono
- top-level meta.json gets a new "What's New" section between
Tutorials and Migrate
## Redirects
15 redirect rules in next.config.ts cover every /learn/* path that
existed (literal pages + the /learn/whats-new/:path* and
/learn/generative-ui/specs/* sets). Plus a generic /learn → /concepts/architecture
catch-all so the old root URL doesn't 404.
## Inbound link rewrites
22 inbound /learn/* references rewritten across the docs tree
(snippets, threads.mdx, premium/self-hosting.mdx, useCapabilities,
useThreads, the existing Concepts pages that linked to /learn/*, and
internal cross-links inside the moved files themselves). Verified zero
remaining /learn/ references except the unrelated `learn.microsoft.com`
external URLs in the MS Agent Framework integration pages.
## Smoke tested
All 12 new canonical URLs return 200. All 8 sampled /learn/* legacy
URLs 308-redirect to the correct canonical home (/concepts/*, /tutorials/*,
/generative-ui/*, /whats-new/*).
Closes PDX-69.
Two follow-ups from the tutorial walkthrough.
**Standalone Card link styling.** Cards used outside a `<Cards>`
wrapper (the GitHub source link on tutorial overviews; the lone Next
card on step-1 before this commit) still showed prose-style
underlines. Reason: the escape-hatch CSS rule
`.reference-content .not-prose a { text-decoration: none }` is a
*descendant* selector — it requires `not-prose` to live on a parent
of the <a>. Standalone Cards have nothing above them carrying that
class, so the rule never fired. Cards inside `<Cards>` were fine
because the wrapper has `not-prose`.
Fixed by adding inline `style={{ textDecoration: "none", color:
"inherit" }}` to the linked Card. Inline styles win on specificity
in every shape, regardless of whether `not-prose` is present on a
parent. The class-based `not-prose` + `no-underline` stay too —
they're harmless and serve as documentation of intent.
**Previous on step-1.** Earlier "steps 2-end need Previous" was read
too literally; step-1 of both tutorials wasn't getting a Previous
link back to overview. Added Previous + Next pairs (in `<Cards>`
2-column grid) on step-1 of both tutorials, matching the layout used
on step-2 / step-3 / step-4.
The full chain now:
overview → Next only
step-1 → Prev (Overview) + Next
step-2 / 3 / 4 → Prev + Next
next-steps → Prev only
MDX wraps loose paragraphs in <p>. The hand-written `<p>` I'd used
for the time/difficulty meta line ended up inside another <p> wrapper
generated by MDX, producing `<p><p>...</p></p>` — invalid HTML and a
hydration error in the dev console.
Switching to a `<div>` keeps the same inline-styled muted-text
appearance without triggering the autoclose-then-reopen behaviour
that React/HTML enforces around block-vs-inline `<p>` rules.
Verified the rendered HTML for /tutorials/ai-todo-app/overview no
longer contains a `<p><p>` sequence.
The MDX article body has class `.reference-content`, which carries
this global rule:
.reference-content a {
color: var(--accent);
text-decoration: underline;
}
That selector wins specificity-wise against Tailwind's `.no-underline`
class on the wrapping `<a>`, so the previous Card styling fix didn't
actually visibly remove the underline — the markup said
`no-underline` but the rendered link still had it.
The site has an escape-hatch rule:
.reference-content .not-prose a {
text-decoration: none;
color: inherit;
}
Add `not-prose` to the wrapping Cards container and to the linked
Card itself. The Card's own `hover:border-[var(--accent)]` +
`group-hover:text-[var(--accent)]` classes now control link
appearance entirely.
Verified the rendered anchor on /tutorials/ai-todo-app/step-2-setup-copilotkit
has both `not-prose` and `no-underline` on the wrapping <a>.
The earlier `unselected/` cleanup pass categorized
`unselected/generative-ui/your-components/interrupt-based.mdx` as
D-promote (unique content, needs new home at root). On closer
inspection the file is byte-identical to
`integrations/langgraph/human-in-the-loop/interrupt-flow.mdx` (modulo
title), and references LangGraph's `interrupt()` API + LangChain
interrupt docs throughout — it's LangGraph-specific, not a
framework-agnostic generative-UI feature.
Mastra has its own different interrupt-flow.mdx (264L vs 403L). Other
frameworks (ag2, agno, adk, llamaindex, etc.) don't have an interrupt
flow at all because their agent runtimes don't expose the concept.
Putting it at root would mislead users on other frameworks into
expecting an API that doesn't exist for them.
Reversing the promotion:
- Delete `generative-ui/your-components/interrupt-based.mdx` from the
root tree
- Drop `interrupt-based` from `generative-ui/your-components/meta.json`
- Repoint the `/unselected/.../interrupt-based` redirect to
`/human-in-the-loop` (the framework-agnostic HITL page) instead of
the now-deleted root location
LangGraph's interrupt page stays reachable at
`/langgraph-python/human-in-the-loop/interrupt-flow` (sidebar entry
"Interrupts" under the LangGraph framework block). Mastra's stays at
`/mastra/human-in-the-loop/interrupt-flow`. The `unselected/` copy was
just a redundant fork that was never visible in nav anyway.
Updates the verified-audit framing recorded in PDX-49 — the "13
unique promotions" count drops to 12 (the tutorials), and a new
D-delete entry replaces the interrupt-based promotion.
Three issues from the tutorial polish smoke test.
**1. Card links no longer show prose underlines, hover matches the
rest of the site.** The MDX `<Card>` component was rendering as a
`<Link>` wrapping a styled `<div>`, so prose CSS added a default
underline to the link text and the hover state was a faint
`bg-elevated` swap. Aligns with the docs-landing pointer-card pattern:
`no-underline`, accent border + soft shadow on hover, title color
flips to accent via `group-hover`. Non-linked Cards keep their
neutral surface.
**2. Tutorial overview meta strip simplified.** Replaced the heavier
`<Callout type="info">` (rendered with the "Info" icon + label) with
a small muted inline line: "⏱ 5 minutes · Easy". The Callout was
overweight for two pieces of frontmatter-style metadata.
**3. Previous buttons added to step-2 through next-steps** on both
tutorials. Each step now has a Prev + Next pair (in a `<Cards>`
2-column grid); the terminal `next-steps` page has Prev only. Pattern:
step-1: Next only
step-2..4: Prev + Next side by side
next-steps: Prev only
**4. Dev meta cache invalidation.** Caught while testing the earlier
interrupt-based nav fix: `metaCache` and `titleCache` in
`lib/docs-render.tsx` are process-scoped, so meta.json edits in dev
required a server restart to show up. Skip both caches when
`NODE_ENV=development` so authors get immediate feedback. Build / prod
behaviour unchanged (content is frozen at deploy time, so caching
the entire process lifetime is still right there).
Verified `/your-components/interrupt-based` now appears in the
sidebar without a restart, all 8 step Prev/Next routes return 200.
Three small fixes that surfaced when smoke-testing the
unselected/ → /tutorials/ promotion.
**Tutorial overviews** styled to match the rest of the site:
- Time/difficulty meta is now a `<Callout type="info">` (was a bare
`<div>` block with raw `**bold**` markdown that rendered as plain
prose).
- GitHub source link is a styled `<Card>` (was a hand-rolled
`<button class="bg-neutral-800 ...">` wrapped in `<Link>`, which
didn't match site Card patterns and rendered the icon as a
keyboard glyph since react-icons isn't in the MDX registry).
- Demo iframe is wrapped in `<Frame>` (was a hand-rolled chrome bar
with `bg-neutral-800` header div that didn't match site styling).
- Redundant `<h1>` "AI Todo List Copilot Tutorial" / "AI-Powered
Textarea Tutorial" headings removed — page title comes from
frontmatter + meta already.
- Fixed `<YouTubeVideo>` props: `videoId` → `id`, dropped
`defaultPlaybackRate` (neither matched the registry component's
shape; videos rendered nothing before).
**Next-step buttons** added to every step page until the final one.
Each step ends with a `<Card title="Next: ..." href="..."
description="..." />` so the reader can click straight through:
- ai-todo-app: overview → step-1 → step-2 → step-3 → step-4 → next-steps
- ai-powered-textarea: overview → step-1 → step-2 → step-3 → step-4 → next-steps
The terminal `next-steps` page has no Next card (per "until the final
one" — it's the wrap-up).
**Dangling import tails removed** from both tutorials' step-2 files —
historical sync-stripper artifact (orphaned `TailoredContent,
TailoredContentOption, } from "..."` block with the opening `import {`
missing).
**interrupt-based nav fix:** `generative-ui/your-components/meta.json`
was missing `interrupt-based` in its `pages` array, so the file
existed on disk but never appeared in the sidebar.
Verified all 13 tutorial / Next-button URLs return 200 in dev.
Three unique-content moves from `unselected/`:
- 12 tutorial files in two series (`ai-todo-app/*`, `ai-powered-textarea/*`)
→ `/tutorials/*` with a new `---Tutorials---` section in the top-level
nav, slotted before Migrate.
- `generative-ui/your-components/interrupt-based.mdx` (403L) →
`generative-ui/your-components/interrupt-based.mdx` alongside the
existing `display-only.mdx` and `interactive.mdx` peer pages.
Inline `/unselected/tutorials/*` link references (only in the two
`next-steps.mdx` files) rewritten to `/tutorials/*`.
Fixes a stale meta entry: `tutorials/ai-todo-app/meta.json` referenced
`step-4-copilot-actions` but the actual file was renamed to
`step-4-frontend-tools.mdx` at some point. Aligned the meta to the
real filename.
Outer `tutorials/meta.json` title bumped from `"tutorials"` to
`"Tutorials"` so the matching `---Tutorials---` section header
triggers the existing nav-render dedup (suppresses the redundant
inner group label).
Verified: `/tutorials/ai-todo-app/overview`, `/tutorials/ai-powered-textarea/overview`,
`/built-in-agent/tutorials/ai-todo-app/overview`, and
`/generative-ui/your-components/interrupt-based` all 200 in dev.
Nine files where the root version was either a one-line component stub
(`<Inspector />`, `<HeadlessUI />`, `<Observability />`, `<Overview />`)
or used v1 API patterns (`<CopilotKit>` / `@copilotkit/react-core`)
that the unselected/ tree had already updated to v2 patterns
(`<CopilotKitProvider>` / `@copilotkit/react-core/v2`). Promoting the
richer content over the root stubs / v1 versions:
- inspector.mdx (root: 11L stub → 79L of real content)
- premium/headless-ui.mdx (root: 7L stub → 290L)
- premium/observability.mdx (root: 7L stub → 259L)
- premium/overview.mdx (root: 7L stub → 84L)
- generative-ui/your-components/interactive.mdx (root: 21L IntegrationGrid placeholder → 78L with snippet_cell)
- troubleshooting/common-issues.mdx (v1 imports → v2; tighter prose)
- troubleshooting/error-debugging.mdx (v1 imports → v2; "& Observability" added to title; programmatic onError section retained)
- backend/ag-ui.mdx (v1 → v2 imports)
- backend/copilot-runtime.mdx (v1 → v2 imports)
The unselected/ versions weren't a side-tree of duplicate content —
they were the v2-aware refresh that hadn't propagated to root yet.
First commit of the `unselected/` editorial cleanup tracked under
PDX-49. Cat A deletes (root canonical), Cat B deletes (BIA canonical),
D-promote moves (interrupt-based + 12 tutorials), Cat D-delete
(agent-app-context), redirect rules, and inbound link rewrites still
to come.
Two related cleanups that fall out of the soft-default world.
**Framework-name sidebar link** — the labeled "you're reading X's docs"
header link below the framework selector was redundant. The selector
pill above it already identifies the active framework, the breadcrumb
trail at the top of the body covers "go to root," and `/` and
`/<framework>` now render the same docs-landing shell so clicking the
link mostly just changed the URL. Removed from all four call sites:
DocsOverview (unscoped /), FrameworkLandingPage,
NotAvailableForFrameworkPage, and DocsPageView.
DocsPageView's `sidebarTitle` and `backLink` props are gone (no
remaining consumers). Breadcrumb root label is now derived from
`frameworkOverride` at render time — "LangGraph (Python)" on
framework-scoped pages, "Docs" otherwise.
**Legacy `/integrations/<framework>/<slug>` URLs** — the original URL
scheme before `/<framework>/<slug>` shipped. The Notion plan flagged
them as still reachable via UnscopedDocsPage's regex match on
`integrations/...`. Since shell-docs hasn't shipped publicly, no real
inbound links exist; cleaner to retire them than maintain dual schemes.
UnscopedDocsPage's integrationMatch branch is gone. Any
`/integrations/...` URL now 404s. The `integrations/<framework>/`
content tree on disk stays — it's still loaded by the framework
router's per-framework override fallback (e.g. `/built-in-agent/quickstart`
serves `integrations/built-in-agent/quickstart.mdx`). Only the URL
scheme is retired.
search-modal.tsx integration and demo result links now point at the
shell host's integrations explorer (`${SHELL_HOST}/integrations/...`)
instead of the now-404 shell-docs paths.
Both affordances were vestiges of the pre-soft-default world.
"All docs" pointed at `/`. Before the IA restructure, that was a
distinct picker view; now `/` and `/<framework>` render the same
docs-landing shell with whichever framework is effective. Clicking
the link from a deep page just changed the URL with no visible
content change. The CopilotKit logo in the top header already covers
"go to root," and the framework-name link below the selector covers
"go to this framework's landing." Removed from all three call sites
(feature-page backLink, FrameworkLandingPage sidebar,
NotAvailableForFrameworkPage sidebar).
"Reset to default" set storedFramework to null and navigated to the
unscoped equivalent of the current page. With the CopilotKit row
pinned at the top of the dropdown, picking it does the same thing
end-to-end (effectiveFramework becomes BIA, navigation lands on a
BIA-scoped URL) — the user reaches for the same target either way.
The button only appeared when storedFramework was set, so removing it
loses no on-screen affordance for fresh visitors and one redundant
row for returning visitors.
Two small UX nudges so the soft-default reads naturally to a fresh
visitor:
1. Sidebar selector — closed pill and dropdown row both display
"CopilotKit" instead of "Built-in Agent" when BIA is the
effective framework. Topbar variant and other surfaces keep the
registry name. The framing in the sidebar is "you're reading
CopilotKit's docs" rather than "you've picked the Built-in Agent
backend"; in the docs landing's "Continue with X" / "Browse X
docs" affordances, the registry name is still the right framing.
2. Sidebar selector — BIA pinned at the top of the dropdown,
outside the Popular category bucket. It's the default, so it
reads more naturally as the always-there starting point than as
one of several Popular options.
3. "Switch backend" picker on the docs landing filters BIA out.
Showing "switch to Built-in Agent" inside a "Switch backend"
affordance is a no-op tile when BIA is already the soft-default.
The selector's display label and dropdown checkmark were keyed off
URL framework + stored only, so on `/` (URL null, no localStorage) it
read "Pick a backend" even though the page was rendering Built-in
Agent code. Switch both to `effectiveFramework` so the chrome stays
honest about what the page is actually rendering.
Renames the legacy "Clear selection" affordance to "Reset to default
(Built-in Agent)" — the action now means "go back to soft-default,"
not "have nothing selected." Only shown when storedFramework is set,
so it doesn't surface for fresh visitors who never picked.
FrameworkProvider gains an `effectiveFramework` field that falls
through URL → stored → DEFAULT_FRAMEWORK ("built-in-agent"), so it's
never null. Snippet renderers, sidebar links, and "Continue with X"
affordances read this; the original `framework` field stays
URL-strict for the few call sites that genuinely need to know
"is the URL scoped?"
Removes the forced-picker dead end. Fresh visitors land on the docs,
see BIA code immediately, and switch backends from the picker on the
landing page or the sidebar dropdown when they want.
Consumers updated:
- SidebarLink resolves href against effectiveFramework. Drops
hideWhenUnscoped (Quickstart entry now always lands on a real
framework-scoped URL).
- DocsLandingNext collapses its two-branch render (picker vs
Continue-with-X) into one: always shows "Continue with
{effectiveFramework}" + Quickstart/Browse pointer cards, with the
categorized framework picker below as a "Switch backend" affordance.
- RouterPivot becomes a pure redirect: dispatches to
`/<effectiveFramework>/<slug>` on mount. The legacy picker grid is
gone — soft-default makes that branch unreachable.
- FrameworkGuardedContent always returns null (the body is hidden
during the redirect tick).
- UnscopedDocsPage drops the props that fed RouterPivot's old picker
(frameworksWithCell, previewUrl, featureName, featureDescription).
Switching frameworks now lands on the same shell as / does, just with
the framework already URL-active. The /<framework> route renders the
docs-landing hero, CLI command, and utility cards (Concepts / API
Reference / Generative UI), then DocsLandingNext's "Continue with X"
branch with Quickstart / Browse {framework} docs / Switch framework
pointers. Replaces the previous bespoke FrameworkLandingPage that
showed a "You're viewing docs scoped to" panel and a hardcoded 4-card
grid (chat-ui / tool-rendering / frontend-tools / human-in-the-loop)
that drifted from the docs landing.
DocsLandingNext now prefers the URL-active framework over the stored
preference so /<framework> can render the "Continue with X" branch
during SSR with no mount-flicker — the previous storedFramework-only
gating caused a brief picker render before the localStorage effect
caught up.
Delete the orphaned per-framework index.mdx files. They were the
backing for the old sidebar Introduction entry (already removed) and
the URL /<framework>/index, which Next.js's optional catch-all
collapses to the bare framework path anyway. Their FrameworkOverview
content (banner video, init command, supportedFeatures grid) was a
legacy marketing-style landing that doesn't fit the new docs-routing
shape.
Each integration's meta.json opened with a "Getting Started" section
containing index (rendered as "Introduction") and quickstart. The
override filter already drops sections and root-equivalent pages, so
quickstart was always filtered (root quickstart.mdx exists), but
index slipped through and rendered as an Introduction link to
/<framework>/index — duplicating /<framework> with the marketing-style
FrameworkOverview content. Drop the entire opening section from every
framework's meta.json so the framework block in the sidebar starts at
the first framework-unique topic.
Also flatten empty-title wrapper groups in buildFrameworkOverridesNav.
buildNavTree clears the title on a spread-derived group when the
preceding section has the same name (so the renderer doesn't double-
print "Generative UI"). The override filter then drops those section
headers, leaving titleless containers that only added an extra indent
step around their children. Inline the children at the wrapper's
level instead, raising "Your Components" up where "Generative UI"
used to sit.
The root /quickstart page is a routing shim — it has no real content,
just a pointer to the per-framework quickstarts. Showing it in the
sidebar on / leads users into a dead-end click ("This page is a
routing shim..."). Hide the entry until a framework is active in the
URL or stored in localStorage; once either is set, SidebarLink prepends
it and the click lands on real per-framework content.
The framework-scoped route resolves root MDX before per-framework
overrides, which is correct for most pages — root content rendered
with framework-specific snippets is the primary path. But the new
root quickstart.mdx is a routing shim that exists only so the sidebar
entry has a backing page; real quickstart content lives per-framework
at integrations/<framework>/quickstart.mdx. Special-case the
quickstart slug so the override always wins for framework-scoped URLs.
While here, add the missing crewai-crews → crewai-flows docs-folder
mapping. The registry slug was renamed but the docs folder kept the
older name, so /crewai-crews/quickstart couldn't find the override.
The merged landing's "no framework selected" branch previously showed a
flat IntegrationGrid. Swap it back to the categorized picker (Popular /
Agent Frameworks / Provider SDKs / …) so the docs root mirrors the same
shape users saw before the merge — the affordance to pick a backend is
unchanged from their perspective.
Also re-add the "Quickstart" sidebar entry so every framework has it.
The page itself is a routing shim; SidebarLink prepends the stored
framework, and direct hits to /quickstart 308 to /.
Extract FRAMEWORK_CATEGORY_ORDER into lib/framework-categories so the
client component can pull the constant without dragging fs-using
helpers from lib/docs-render through the bundle. docs-render
re-exports the constant so existing server-side imports keep working.
The docs landing at `/` and the standalone `/quickstart` picker did
overlapping jobs and confused first-time users. "Quickstart" as a
top-level URL was misleading: clicking it from the shell landing or
the docs overview's top-card list led to a 23-line picker rather than
the actual quickstart guide (which lives at `/<framework>/quickstart`,
117–527 lines per framework).
Merge them. `/` becomes the single docs-side landing:
- Always shown: hero + product positioning, the `npx copilotkit@latest
create` CLI command (moved up from /quickstart), and three utility
cards (Concepts, API Reference, Generative UI).
- Conditional below: a new `DocsLandingNext` client component that
branches on `storedFramework`. Null → "Pick your agent framework"
+ the integrations grid (the picker). Set → "Continue with
{name}" + three pointer cards (quickstart for that framework,
framework landing, switch frameworks).
The standalone `/quickstart` page is deleted; `/quickstart` 301-redirects
to `/`. `/<framework>/quickstart` is unchanged — that's the canonical
per-framework quickstart guide.
Side effects of the merge:
- The unscoped catch-all's `DocsOverview` was rewritten to drop the
former two-step "Pick a backend / Or jump into a topic" panels.
The framework picker is now in `DocsLandingNext` (only when there's
no stored choice); the topic cards (DOCS_SECTIONS) were a flatter
duplicate of the new JTBD sidebar and got deleted entirely.
- `content/docs/index.mdx` was the file that rendered at `/index`
(reachable from a sidebar entry under Get Started). With the
merged `/` landing serving as the canonical overview, the
`/index` URL stops being meaningful — `index.mdx` is deleted and
the entry is removed from the top-level `meta.json`.
- `DocsLandingNext` is registered in the MDX components map so
future pages can drop it inline if useful, but its primary use is
inside `DocsOverview` itself.
Pairs with PDX-46 (BIA-as-default). Once BIA defaults are in, the
"no framework" branch of `DocsLandingNext` becomes rare and the page
reads as the "what's next" experience for nearly every visitor.
Closes PDX-58.
The concepts/three-types-of-gen-ui page and the canonical
learn/generative-ui/index page both use "Open-Ended" (with the
suffix) as the third gen-UI category alongside Controlled and
Declarative. The sidebar subsection had been shipped as just "Open"
in the JTBD reorg, leaving readers with three different namings
across the site ("Open" in nav, "Open-Ended" in concept page,
"Open-Ended" / "Fully Generated" in the learn page).
Align the sidebar to the canonical name. The other two subsections
("Controlled" and "Declarative") were already consistent.
Two changes to index.mdx that align it with the new JTBD sidebar
instead of competing with it:
- Drop the lower "Explore by feature" 6-card section. Every entry
there (Chat UI, Headless UI, Generative UI, Backend & Runtime,
Programmatic Control, API Reference) was a flatter version of a
sidebar section the JTBD reorg introduced. The overview pitching
the same content twice made the page heavier without adding routing
value.
- Swap one of the 4 top cards (was: Chat UI → /prebuilt-components)
for Concepts → /concepts/architecture so the conceptual entry
point is reachable from the docs front door, not just the sidebar
subgroup.
The overview is now: 4 top cards (Quickstart, API Reference, Concepts,
Generative UI), the LandingCodeShowcase, and the IntegrationGrid.
Tighter and clearly a doc-router rather than a product-pitch redux.
The merge anchor was hardcoded to "app control" with fallbacks to
"threads" and "backend". After the JTBD reorg renamed "App Control"
→ "Give Your App Agent Powers" and "Backend" → "Agents & Backends",
none of the candidates matched and every framework-scoped sidebar fell
back to append-at-end, relegating the framework section ("Built-in
Agent", "LangGraph (Python)", etc.) to the bottom of the nav.
Restore the original placement by adding the new section names to the
anchor candidate list: "give your app agent powers" (the renamed App
Control) and "agents & backends" (the renamed Backend) take priority,
with the old names kept as fallbacks for resilience. The match is
case-insensitive and stops at the first hit. Verified the framework
section now lands between Give Your App Agent Powers and Agents &
Backends for /built-in-agent/* and /langgraph-python/*.
The redirect entries are self-describing — source, destination, and
permanent flag say everything the runtime needs. The block comments
were rationale that belongs in commit messages, not in a config file
that future readers scan for shape.
The previous commit renamed the file but didn't add a redirect, so
any open browser tab or external link to /concepts/oss-vs-cloud now
404s — surfacing as a "sidebar disappeared" experience because the
404 page doesn't render the docs shell. Add the 301 redirect alongside
the migrate-to-* and frontend-actions ones.
"Cloud" implied a single deployment shape (managed-only). "Enterprise"
is the accurate name for the layer — same Intelligence Platform runs
hosted at Copilot Cloud or self-hosted via the copilot-intelligence
Helm chart. The page already used "Enterprise" terminology in the
body; this aligns the slug, page title, and meta entry to match.
File renamed via git mv (history preserved). search-index.json paths
update on the next build (gitignored, regenerated).
Replaces the TODO placeholders left by the JTBD restructure with
written explanation-layer content sourced from existing repo material
(learn/architecture, learn/generative-ui, learn/intelligence-platform,
ag-ui/concepts/architecture, premium/overview) and from two CopilotKit
blog posts ("AG-UI Is Redefining the Agent–User Interaction Layer"
and "The Three Types of Generative UI: Static, Declarative and Fully
Generated").
- concepts/architecture.mdx: the three-layer stack (frontend, runtime,
agent), AG-UI as the protocol bridge between runtime and agent, the
request flow at a glance. Reuses the existing architecture-diagram
PNG via ImageZoom and links out to the deeper learn/* coverage.
- concepts/three-types-of-gen-ui.mdx: a freedom-vs-control framing of
Controlled / Declarative / Open-Ended generative UI with one concrete
example per type and explicit "when to pick" guidance. Notes the
alias terminology (Static, Fully Generated) so readers can match the
blog and the learn/ pages. Cross-links to the implementation pages
for each type.
- concepts/oss-vs-cloud.mdx: clear OSS-vs-Enterprise feature split with
a capability-by-capability table, hosted-vs-self-hosted explanation,
and a decision rubric ("if you want CopilotKit to *be* your
conversation persistence layer, that's where Enterprise begins").
All three keep the explanation-layer scope (Diátaxis): they orient
and explain, then point the reader at the canonical detailed pages
for implementation specifics. None of them duplicate how-to content.
The concepts/what-is-copilotkit.mdx placeholder duplicated the
overview rendered at /index.mdx — same intent ("orient the reader"),
same target audience. Keep the index page as the single what-is
entry point and remove the concept-page slot.
The current meta convention pairs a `---X---` section header with a
`...x` spread that resolves to a sub-meta whose `title` is also "X".
buildNavTree emitted both a section node and a group node with the
same title, and the renderers showed each one — so users saw "BUILD
GENERATIVE UI" (section, uppercase tracking-widest) followed by
"Build Generative UI" (group, regular case) for the same content.
The doubling was already on the live site for one section
("Generative UI") and didn't get pushback there, but the JTBD reorg
makes it more visible: every spread-backed section ends up doubled
(Migrate, Other, etc.).
Fix in two halves, kept narrow:
- buildNavTree: when the previously-pushed node is a section header
with the same title that the spread's group would carry, set the
group's title to empty string. The group still wraps its children
for indentation/nesting; only the redundant inner label is dropped.
- All three nav renderers (renderNavItem in docs-page-view.tsx,
OverviewNavItem in app/[[...slug]]/page.tsx, RenderNav in
app/[framework]/[[...slug]]/page.tsx) gain a `{node.title && ...}`
guard so an empty string doesn't render an empty <div>.
Sections without a matching spread (Get Started → index/quickstart/
coding-agents listed inline) and spreads without a preceding section
header (legacy framework-tree work, override merges) are unaffected.
A spread whose sub-meta title differs from the section header (e.g.
section "Observe & Operate" + ...troubleshooting whose title is
"Troubleshooting") still renders both labels, which is correct —
they're meaningfully different and the inner one acts as a
sub-grouping label.
Restructures the top-level sidebar from feature-primitive sections
(Basics / App Control / Backend / Generative UI / Platform / Premium
Features / Troubleshooting) into 9 jobs-to-be-done sections that match
how readers describe what they want to build. Decisions captured in
the IA Restructure plan.
Section structure:
1. Get Started — index, quickstart, coding-agents, + concepts subtree
(placeholders for what-is-copilotkit, architecture,
three-types-of-gen-ui, oss-vs-cloud)
2. Build Chat UIs — prebuilt-components, custom-look-and-feel,
multimodal-attachments
3. Build Generative UI — nested Controlled / Declarative / Open
subgroups (tool-based, tool-rendering, state-rendering, reasoning,
your-components / a2ui + dynamic-schema + fixed-schema / mcp-apps)
4. Give Your App Agent Powers — frontend-tools, shared-state,
multi-agent/subagents, programmatic-control
5. Agents & Backends — built-in-agent (new), copilot-runtime,
custom-agent, ag-ui, runtime-server-adapter
6. Observe & Operate — inspector, vs-code-extension, +
troubleshooting subgroup (event-inspector, hook-explorer,
debug-mode, observability-connectors, common-issues,
error-debugging)
7. Enterprise — premium/overview, premium/observability,
premium/self-hosting, threads (merged from former Threads section
per product call: threads + persistence are part of Enterprise)
8. Migrate — v2, 1.10.X, 1.8.2 (moved out of Troubleshooting and
renamed to drop the redundant 'migrate-to-' prefix)
9. Other — contributing, telemetry (unchanged)
Reference stays as a separate root-true tree, not surfaced through the
top-level meta. Its v1/v2 treatment is a follow-up decision.
Page moves and new files:
- Migration guides moved from troubleshooting/migrate-to-{v2,1.10.X,
1.8.2}.mdx to migrate/{v2,1.10.X,1.8.2}.mdx with 301 redirects from
the old URLs in next.config.ts. Migrate gets its own first-class
section with a lucide/RefreshCw icon — separate from
Troubleshooting per IA-analysis pillar ("I'm upgrading deliberately"
≠ "something broke").
- 4 concept placeholders + index under content/docs/concepts/. Each
has frontmatter (title, description, icon, doc_type: explanation)
and a TODO body referencing where the content will come from
(existing repo material + blog posts). Slot exists; content
backfills later.
- New built-in-agent.mdx at root — 1-page summary that places BIA in
Agents & Backends as a peer to copilot-runtime / custom-agent / etc,
with a link out to the full BIA-scoped docs at /built-in-agent.
Other meta moves:
- programmatic-control: Basics → Give Your App Agent Powers
- inspector: Basics → Observe & Operate
- vs-code-extension: Platform → Observe & Operate
- multimodal-attachments: Platform → Build Chat UIs
- runtime-server-adapter: Platform → Agents & Backends
- The 3 migration pages: Troubleshooting → Migrate (with file moves)
Removed dead code: the `...unselected` line in top-level meta.json
was a no-op (unselected/meta.json has `root: true` so the spread
produced nothing). Stripped during the rewrite.
Multiple new visible labels are intentional. The renderer renders
sections (uppercase tracking-widest) and groups (medium-weight regular
case) at the same level when a section spreads a sub-meta with a
matching title — same pattern that's been live for 'Generative UI'
through every prior PR. The Build Generative UI nesting (Controlled /
Declarative / Open) is a deliberate three-types-of-gen-UI subgrouping
inside the section, surfaced via subsection headers in
generative-ui/meta.json's pages array.
## Summary
Six small, independently-verifiable shell-docs cleanup commits. All
scoped to polish — no structural reorganization.
- **Sidebar title now shows the integration name** on framework-scoped
routes. Previously every `/<framework>/*` URL hardcoded `\"CopilotKit
Docs\"` at the top of the sidebar; now `/langgraph-python/*` reads
\"LangGraph (Python)\", `/built-in-agent/*` reads \"Built-in Agent\",
`/ms-agent-dotnet/*` reads \"MS Agent Framework (.NET)\", etc. Unscoped
routes (`/`, `/quickstart`) keep the \"CopilotKit Docs\" default.
- **Event Inspector + Hook Explorer added to the Troubleshooting
sidebar.** Both pages exist on disk but weren't in
`troubleshooting/meta.json`, making them unreachable from the sidebar —
only direct-URL navigation surfaced them. Inserted between Debug Mode
and Observability Connectors so the four debugging tools cluster
together.
- **Framework selector now reflects the stored choice on unscoped
pages.** The dropdown's display label was derived from the URL-derived
`framework` only. On unscoped pages where `framework` is null, it
reverted to the \"Pick an agentic backend\" placeholder even when
localStorage held the user's prior selection — so the choice appeared to
be forgotten on every return to the root. Falls back to
`storedFramework`, matching the precedence the Clear-Selection button
below already uses.
- **Wire the orphan `multi-agent/subagents` page into the App Control
nav.** `content/docs/multi-agent/subagents.mdx` is a real page with
`snippet_cell: subagents` and a lucide icon, but had no entry in any
`meta.json` — only direct-URL navigation reached it. Slotted into App
Control next to `frontend-tools` and `shared-state`.
- **Collapse legacy `/frontend-actions` into `/frontend-tools`.**
`content/docs/frontend-actions.mdx` was a 33-line stub from when the
feature was called \"Frontend Actions\" (the API is now exclusively
`useFrontendTool`). Deleted the orphan + added a 301 redirect in
`next.config.ts` so external links still land cleanly. The HTML anchor
IDs `id=\"frontend-actions-example\"` referenced from 12 framework
`frontend-tools.mdx` files are unaffected (anchors, not URLs).
- **Drop dormant per-framework threads + self-hosting stubs.** 24
byte-identical stub files across 12 framework trees: 12 ×
`integrations/<fw>/threads.mdx` (7L each, body `<Threads />`, all md5
`0371508d…`) and 12 × `integrations/<fw>/premium/self-hosting.mdx` (8L
each, body `<SelfHosting />`, all md5 `06d17f98…`). The
`buildFrameworkOverridesNav` filter already dropped them from the merged
sidebar (root wins), and the framework-scoped router falls back to root
MDX when no per-framework override exists — so deletion is invisible to
users. Net 187 lines gone. Path-exclusion patterns added to
`sync-docs-from-main.ts` so future upstream syncs don't resurrect them.
## Test plan
- [ ] `/langgraph-python/quickstart`,
`/langgraph-typescript/quickstart`, `/langgraph-fastapi/quickstart` show
\"LangGraph (Python)\", \"LangGraph (TypeScript)\", \"LangGraph
(FastAPI)\" respectively at the top of the sidebar.
- [ ] `/built-in-agent/quickstart` shows \"Built-in Agent\".
- [ ] `/mastra/quickstart` shows \"Mastra\".
- [ ] `/ms-agent-dotnet/auth` and `/ms-agent-python/auth` show \"MS
Agent Framework (.NET)\" and \"MS Agent Framework (Python)\".
- [ ] `/quickstart` (unscoped) keeps \"CopilotKit Docs\" — default
unchanged.
- [ ] Pick a framework, navigate back to `/` — the sidebar dropdown
shows the stored choice with violet active styling, not the \"Pick an
agentic backend\" placeholder.
- [ ] Use Clear Selection — dropdown reverts to placeholder; `framework`
is null and `storedFramework` is null.
- [ ] After a dev server restart (meta.json cache is module-scoped): the
Troubleshooting section in any docs page sidebar lists Common Issues →
Error Debugging → Debug Mode → **Event Inspector** → **Hook Explorer** →
Observability Connectors → migrate-* in that order.
- [ ] After a dev server restart: `/multi-agent/subagents` appears in
the App Control sidebar section (after Shared State) and renders with
the \"Sub-Agents\" title.
- [ ] After a dev server restart (next.config.ts redirects load on
startup): `curl -I http://localhost:3003/frontend-actions` returns `301`
with `Location: /frontend-tools`.
- [ ] `/frontend-tools` renders unchanged.
- [ ] All of these continue to render with multi-hundred-KB bodies after
stub deletion (routing fallback to root MDX): `/built-in-agent/threads`,
`/langgraph-python/threads`, `/mastra/threads`,
`/built-in-agent/premium/self-hosting`,
`/langgraph-python/premium/self-hosting`. Sidebar appearance unchanged —
these stubs were already filtered from the override nav.
24 files in two byte-identical families across 12 integration trees:
- 12 `integrations/<fw>/threads.mdx` — 7 lines each, all md5 0371508d…,
body is just `<Threads />`.
- 12 `integrations/<fw>/premium/self-hosting.mdx` — 8 lines each, all
md5 06d17f98…, body is just `<SelfHosting />`.
Both render shared snippets the root-level pages already render. The
`buildFrameworkOverridesNav` filter dropped them from the merged
sidebar (root wins), and the framework-scoped router falls back to
root MDX when no per-framework override exists, so deletion is
invisible to users — `/built-in-agent/threads`,
`/langgraph-python/premium/self-hosting`, etc. continue to render
identically. Verified: each URL still returns 200 with full body
(340–465 KB) by curling the dev server before commit.
Add path-exclusion patterns to sync-docs-from-main.ts so future
upstream syncs don't resurrect them. Same shape as the BIA branch's
`(other)/` exclusion. Sample-tested the regexes against expected-
exclude and expected-keep paths — all classify correctly.
Audit covered every `integrations/<fw>/*.mdx` with body ≤ 2 non-blank
lines; no false-negative stubs of other shapes.
content/docs/frontend-actions.mdx was a 33-line stub from when the
feature was called "Frontend Actions." The product API is now
exclusively useFrontendTool, the canonical page is /frontend-tools
(1967 bytes, snippet_cell-driven, in the App Control sidebar
section), and the orphan stub had no entry in any meta.json — it
only rendered if you typed /frontend-actions directly.
Per the IA analysis: "redirect or delete; pick one." Picked both:
delete the orphan file + add a 301 redirect /frontend-actions →
/frontend-tools so any external link (search results, blog posts,
customer docs) lands cleanly on the canonical page.
Other 'frontend-actions' references in the repo are stable HTML
anchor IDs (`id="frontend-actions-example"` in 12 integration
`frontend-tools.mdx` files) and external links to the legacy
docs.copilotkit.ai site — neither breaks.
content/docs/multi-agent/subagents.mdx is a real, well-written page
(snippet_cell: subagents, lucide/Users icon) covering the supervisor →
specialized-sub-agents pattern. It rendered at /multi-agent/subagents
but had no entry in any meta.json, so it was unreachable from the
sidebar — a true orphan.
Slot it into the existing App Control section (next to frontend-tools
and shared-state, where it fits conceptually as another agent-behavior
control). The structural IA restructure (sam-shell-docs-ia, PR 2) can
promote it to a dedicated '---Multi-Agent---' section later if the
JTBD reorganization warrants it; this commit just stops it from being
hidden.
The 'multi-agent-flows' references in three integration metas
(crewai-flows, llamaindex, pydantic-ai) point at framework-specific
files (e.g. integrations/crewai-flows/multi-agent-flows.mdx), not at
this top-level page — different topic, no overlap.
The sidebar framework dropdown derived its display label and
"current" highlight from the URL-derived `framework` only. On
unscoped pages (/, /quickstart, /threads, etc.) where `framework` is
null, that resolved to `undefined` and the dropdown reverted to its
"Pick an agentic backend" placeholder — even when localStorage held
the user's prior selection. Visually this looked like the user's
choice had been forgotten on every return to a root-scoped URL.
Fall back to `storedFramework` when `framework` is null. Same
precedence as the Clear-Selection button further down the file
(`framework || storedFramework`). Framework-scoped routes are
unaffected because `framework` is set there.
Both files exist on disk (event-inspector.mdx, hook-explorer.mdx) but
weren't in troubleshooting/meta.json's pages array, so they were
unreachable from the sidebar — only direct-URL navigation surfaced
them. buildNavTree iterates meta.pages exclusively when present
(filesystem auto-discovery only fires when meta.json is missing or
its pages field is missing), so the slugs were effectively orphans.
Inserted between debug-mode and observability-connectors so the four
in-IDE debugging tools (error-debugging → debug-mode → event-inspector
→ hook-explorer) cluster naturally before observability and the
migration-guide tail.
Note: dev server picks up the new entries on restart — readMeta in
lib/docs-render.tsx caches at module scope by design (comment notes
this is intentional).