The default framework's docs now live at bare root URLs (/quickstart,
/server-tools, ...) instead of under /built-in-agent/. The root
catch-all resolves BIA-authored pages first, /built-in-agent/:path*
permanently redirects to /:path*, and sidebar/landing/selector hrefs
are root-relative.
The whole root surface shares ONE sidebar: the Built-in Agent IA with
the agnostic root sections (Concepts, Runtime, Deploy, Platforms, Other)
folded in via buildRootSurfaceNav. Empty ---Section--- placeholders in
the BIA meta.json position each folded-in section; appendSharedRootSections
fills them, dropEmptySections clears any that stay empty, and route-group
nodes (e.g. the (other) tree) are excluded so the fold never emits a bogus
/(other)/... href. Without this, navigating from a BIA page to an agnostic
page (/concepts/*, /backend/*) swapped the sidebar between two overlapping
IAs. The fold is scoped to the root surface only — deepagents keeps
Platforms-only and generated frameworks are untouched.
Duplicate pages that the fold would otherwise double up are consolidated
onto their canonical root homes:
- The three BIA backend wrappers (copilot-runtime, custom-agent, ag-ui)
are retired; the folded-in Runtime section is their single home. This
resolves the /backend/ag-ui collision (the wrapper had shadowed the
real root page). The bare /ag-ui segment belongs to the AG-UI protocol
docs, so old /built-in-agent/ag-ui links redirect to /backend/ag-ui.
- The BIA troubleshooting wrappers are retired in favor of the canonical
/troubleshooting/* pages surfaced by the folded-in Other section, so
Troubleshooting appears once.
Stale redirect R25 (/runtime-server-adapter -> /backend/copilot-runtime)
is removed: runtime-server-adapter is a distinct, current 'Deploy to any
runtime' page linked from the sidebar, and the redirect had made it
unreachable at its own URL.
Middleware rules that would shadow or loop against the new surface
(M2 /quickstart, BIA_DEFAULT_ROOT_REDIRECTS, MV-telemetry) are retired,
and remaining live destinations move off the old prefix. The sitemap,
llms.txt, per-page .md/.mdx, and OG image routes resolve the same
content the pages serve. The client-side RouterPivot bounce is removed
since root URLs now render real content in place.
Six fixes addressing CR findings on the Option-B runtime URL-injection migration:
1. SSR_PLACEHOLDER must be parseable URL sentinels — `new URL("")` throws on
SSR causing 500s for any consumer that constructs URLs from runtime-config
fields. Use `.invalid`-TLD sentinels (RFC 2606) for URL fields; analytics
keys stay empty string. Add `suppressHydrationWarning` on consumers that
render the placeholder server-side and the real value post-hydration
(integration-grid, page-actions popover).
2. Hook-order: move `usePathname()`/`useEffect` ABOVE the early-return in
use-google-analytics. Gate the effect bodies on `GA_ID` instead so React
sees a stable hook order across renders.
3. `readUrl`/`readKey` accept either bare or `NEXT_PUBLIC_*`-prefixed env
names via a fallback chain — covers both server-only and inlined-public
variable conventions without forcing a rename across deploy targets.
4. Extract `serializeRuntimeConfig` to `lib/runtime-config-serialize.ts` so
the OWASP-escape behavior (XSS via </script>, U+2028/U+2029 line-terminator
injection) can be unit-tested without importing the layout into vitest.
5. Reclassify `intelligenceSignupUrl`/`posthogHost` from FATAL-CONFIG to
info-level in shell-docs — these are optional integrations, not hard
wiring failures, so absence should not poison the error stream.
6. Comment-rot cleanup: drop "Option B", B12, "the bug we are fixing", fix
"four substrings"→"three substrings" miscounts, and refresh shell-docs
.env.example to describe the runtime-injection contract instead of a
stale next.config throw claim.
V1: shell + shell-docs `next build` succeeds (no Edge-runtime crash on
`unstable_noStore`).
V2: `OPS_BASE_URL=` shell-dashboard `next build` no longer throws —
`next.config.ts` is now a phase-aware function that emits a sentinel
destination at build time and throws only at start (PHASE_PRODUCTION_BUILD
from next/constants).
Tests: shell-docs 72/72, shell 12/12, shell-dashboard runtime-config 16/16
(pre-existing baseline-partner-count failure unchanged).
Two coupled changes that complete the Option B runtime-injection
switch for shell-docs:
- app/sitemap.ts + app/robots.ts: add `export const dynamic =
"force-dynamic"` so Next.js regenerates both routes per request.
Without this Next would statically prerender them at build time
and freeze whichever NEXT_PUBLIC_BASE_URL was set during
`next build` — the exact freeze that defeats the runtime-config
plumbing.
- next.config.ts: REMOVE the `next build` gates that threw when
NEXT_PUBLIC_BASE_URL or NEXT_PUBLIC_SHELL_URL were unset. Those
gates assumed build-time URL injection. Under Option B both URLs
are read per-request from process.env via getRuntimeConfig(), so
a single built artifact must be allowed to build with neither var
set — they're a deploy-time concern now. Missing-value surfacing
moves to `console.error` from runtime-config.ts at request time.
Post-cutover, every image on docs.copilotkit.ai broke because Next.js's
/_next/image optimizer needs the sharp module at runtime and sharp is
missing from the Railway runtime image. Setting images.unoptimized=true
makes <Image> render as a plain <img> pointing at the source URL,
eliminating the sharp dependency entirely.
This is visually identical for users: our CDN (cdn.copilotkit.ai,
CloudFront/S3) ignores ?fm=webp and serves the cached PNG regardless,
so the optimizer was already producing no format-conversion gains for
CDN-hosted images. A wave-2 follow-up will pre-bake WebP variants of
the two 4K gen-ui-specs-*.png files for bandwidth.
Stack upgrade
- fumadocs-core/ui 15.8.5 → 16.8.12, next 15 → 16 (Turbopack), react 19 → 19.2
- Swap "next lint" → "oxlint ." to match the rest of the repo
- New deps for the page-actions component: @radix-ui/react-popover,
class-variance-authority, clsx, tailwind-merge
Layout & brand polish
- Sidebar floats as a rounded-2xl card with column-aligned padding;
framework picker pill, accent-purple section icons (16px), accent
active state, and a single divider line at the footer
- New custom <ThemeSwitch> — single 50×28 neutral switch replaces the
fumadocs sun/moon split (drops the vertical divider and purple tint)
- Sidebar folder collapse state persists across navigations via
SidebarFolderStatePreserver
- BrandNav: wider top bar, lowercase "Talk to an engineer", BookIcon
for Docs, GitHub/Discord icons rendered inline in our footer row
- Mobile: nav clipping + content padding fixes, content grid-span-full
- TOC-less pages: lift article max-width so content stretches into the
empty TOC column on wide viewports
New routes
- /llms.txt — page index per fumadocs LLMs integration
- /llms-full.txt — concatenated full text of every docs page
- /<path>.md and /<path>.mdx — per-page raw markdown with <Snippet>
regions inlined as fenced code blocks (resolver in lib/llm-text.ts
reuses the same demo-content.json the <Snippet> runtime reads)
- Page-actions bar: Copy Markdown + Open in Claude / Claude Code /
Windsurf / Codex (Codex links to https://chatgpt.com/codex for
universal coverage)
Content fixes
- Reasoning page (generative-ui/reasoning.mdx): rewrite to point at
the real reasoning-default / reasoning-custom cells instead of the
stale agentic-chat-reasoning / reasoning-default-render names
- Strip <FeatureIntegrations /> chip list ("SUPPORTED BY ...") from
16 docs MDX files (component definition kept in mdx-registry)
- Drop hideTOC: true from 11 pages so they pick up the lifted-cap rule
- Default home (/) to the built-in-agent authored sidebar; fix active
state matching on the home url
- Restore default fumadocs Callout (drop the bespoke docs-callout)
- OpsPlatformCTA redesign — light bordered card with accent stripe
- FrameworkOverview redesign — drop atmospheric chrome, smaller hero
- Homepage / docs-landing redesign
Integrations (LGP / LGT / ADK)
- Tag @region[default-reasoning-zero-config] in reasoning-default and
@region[reasoning-block-render] in reasoning-custom for all three
frameworks so the docs <Snippet> calls resolve
- Tag @region[use-agent-simple] + @region[message-list-simple] in
headless-simple and @region[use-rendered-messages-hook] +
@region[manual-tool-call-rendering] +
@region[manual-activity-message-rendering] + @region[custom-bubbles]
across headless-complete
Other
- docs/components/layout/mobile-sidebar.tsx: lowercase "engineer" to
match shell-docs
- .claude/launch.json + .claude/preview/ — dev launch configs for the
worktree so /preview brings up shell-docs on :3003
Rebuild the shell-docs chrome on top of Fumadocs UI primitives and ship the
visual polish pass that replaces the legacy custom chrome.
- Fumadocs adoption: route every docs page (home, framework-scoped, ag-ui)
through a shared ShellDocsLayout that wraps DocsLayout / DocsPage with
the project's nav slot, sidebar config, scroll preserver, and content
wrapper. Swap custom tabs/code-block components for Fumadocs's Tabs,
CodeBlock, Pre, CodeBlockTabs, DynamicCodeBlock — Snippet and DemoSource
now share the same chrome as authored fenced blocks.
- Syntax highlighting: replace rehype-highlight + hand-rolled hljs CSS
with Fumadocs's Shiki-based rehypeCode in all three MDX renderers and
in mdx-registry-loader. A tiny `transformerMeta` Shiki transformer
surfaces fence title= / language as data-attrs so MdxCodeBlock can
render the file-path figcaption + floating copy button.
- Sidebar: floats on all four viewport edges (rounded-2xl, 0.75rem inset,
light-gray border), framework picker pill is rounded-xl with symmetric
padding above/below, sticky picker bg matches the panel surface.
Section headers render in normal caps (no more uppercase shouting), with
scroll position preserved across navigations via SidebarScrollPreserver.
- Navbar: bg flips to `--bg`, full-width inset matches the sidebar,
search trigger drops its border and the entire right-wing pill is the
click target.
- Code chrome: figure surface forced to plain white in light and the
matching dark in dark, shadow stripped, figcaption divider uses
`--border` (was `currentColor` from `text-fd-muted-foreground`). Scoped
the `.reference-content code` chip-bg rule to `:not(pre)` so block
code bodies no longer pick up the gray inline-chip background.
- Content area: 49px (3.0625rem) of left/right padding so the article
column has visible breathing room from both the floating sidebar and
the viewport edge.
- IA: meta.json restructure for /docs (Build Generative UI section,
controlled/declarative/open-ended folders, A2UI lifted to its own
folder with an index page, Migrate moved under Other), Concepts content
rewrite, snippet/region cleanups.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related next.config tweaks for the framework intro pages:
1. images.remotePatterns allows cdn.copilotkit.ai so next/image stops
throwing 'hostname not configured' for banner videos, architecture
diagrams, and the CopilotKit color logo embedded in every
FrameworkOverview data record.
2. 308 redirect /built-in-agent → / since built-in-agent is the
default framework and the docs root is its overview. Without the
redirect, /built-in-agent rendered a separate intro and the
sidebar carried a redundant Introduction link.
The next.config redirects() block runs at Next.js routing time (before
middleware), so it preempts the seo-redirects.ts catalog rules. The
existing catch-all dropped users at the framework-agnostic root tree
(/agentic-chat-ui, /frontend-tools, etc.) instead of the BIA-scoped
equivalent (/built-in-agent/...), diffusing SEO equity from legacy
/unselected/ URLs.
Changes:
- /unselected (root): destination /built-in-agent (was /)
- /unselected/:path* catch-all: destination /built-in-agent/:path* (was /:path*)
- Add 14 explicit slug-rename entries above the catch-all, mirroring
SUBPATH_RENAMES in seo-redirects.ts (S1-S15 minus S13).
Verified against Phase 4 redirect probe — closes 13 of 22 unselected/
failures.
## Summary
Phase 3 of the docs.copilotkit.ai cutover. Surfaces a complete sitemap,
basic robots config, and per-framework self-canonical metadata so every
URL variant is indexed under its own canonical instead of collapsing
onto a single root.
- **sitemap.ts** — emits one entry per (root URL × framework variant)
pair plus reference, AG-UI, and per-framework override pages.
`lastModified` resolves from MDX frontmatter \`lastmod\` first, then
file mtime, then \`new Date()\`. Strips Next.js route-group \`(name)\`
segments and trailing \`/index\` so URLs match what the routers actually
serve. ~2,250 entries.
- **robots.ts** — allow all, disallow \`/api/\`, sitemap pointer at
\`\${NEXT_PUBLIC_BASE_URL}/sitemap.xml\`.
- **sitemap-helpers.ts** — shared MDX walking + base-URL resolution.
- **generateMetadata()** added to the four catch-all docs routes
(\`[[...slug]]\`, \`[framework]/[[...slug]]\`, \`reference/[...slug]\`,
\`ag-ui/[[...slug]]\`). Each sets \`alternates.canonical\` to the page's
own full URL — per-framework self-canonical, not root canonical. So
\`/langgraph-python/quickstart\` declares itself canonical,
\`/agno/quickstart\` declares itself canonical, and the bare
\`/quickstart\` declares itself canonical too.
- **.env.example** — documents \`NEXT_PUBLIC_BASE_URL\` and
\`NEXT_PUBLIC_SHELL_URL\`. Extended the existing comment in
\`next.config.ts\` with the new consumers.
## Test plan
- [x] \`npm run build\` from \`showcase/shell-docs/\` passes; route
table shows \`/sitemap.xml\` and \`/robots.txt\` as static.
- [x] \`curl http://localhost:3099/sitemap.xml\` returns valid XML;
2,254 \`<url>\` entries covering bare unscoped, framework-scoped,
reference, and AG-UI URLs; no \`(other)\` route-group leakage; no
trailing \`/index\` artifacts.
- [x] \`curl http://localhost:3099/robots.txt\` returns the expected
User-Agent / Allow / Disallow / Sitemap config.
- [x] \`/shared-state\` HTML contains \`<link rel="canonical"
href=".../shared-state">\`.
- [x] \`/langgraph-python/quickstart\` HTML contains \`<link
rel="canonical" href=".../langgraph-python/quickstart">\` (NOT pointing
at the bare \`/quickstart\`).
- [x] \`/agno/quickstart\` and \`/reference/components/CopilotChat\` and
\`/ag-ui/concepts/architecture\` all self-canonical.
backend/custom-agent.mdx (508 lines, structurally complete) is the canonical
Factory Mode page. The integrations/built-in-agent/custom-agent.mdx copy
(240 lines, missing 5 sections) was retired:
- Add 301 redirects in next.config.ts for the two historical paths
(/built-in-agent/custom-agent and /integrations/built-in-agent/custom-agent
→ /backend/custom-agent).
- Inbound link retargets to /backend/custom-agent landed in the previous
V2 normalization commit (5 files).
- Delete the divergent 240-line copy.
Phase 3 of the docs.copilotkit.ai cutover: surface a complete sitemap,
basic robots config, and per-framework self-canonical metadata so each
URL variant (bare /quickstart, /langgraph-python/quickstart,
/agno/quickstart, etc.) is indexed under its own canonical rather than
collapsing onto a single root.
- src/app/sitemap.ts: emit one entry per (root URL, framework variant)
pair plus reference and AG-UI sections. lastModified resolves from
MDX frontmatter `lastmod`, then file mtime, then now. Strips Next.js
route-group `(name)` segments and trailing `/index` so URLs match
what the routers actually serve.
- src/app/robots.ts: allow all, disallow /api/, sitemap pointer at
${NEXT_PUBLIC_BASE_URL}/sitemap.xml.
- src/lib/sitemap-helpers.ts: shared MDX walking + base-URL resolution
used by both metadata routes.
- generateMetadata() on the four catch-all docs routes
([[...slug]], [framework]/[[...slug]], reference/[...slug],
ag-ui/[[...slug]]) sets `alternates.canonical` to the page's own
full URL. Per-framework self-canonical, NOT root canonical.
- .env.example: document NEXT_PUBLIC_BASE_URL and NEXT_PUBLIC_SHELL_URL.
- next.config.ts: extend the existing NEXT_PUBLIC_BASE_URL doc comment
with the new sitemap/robots/canonical consumers.
Routes PostHog analytics through /ingest/* (rewrites to eu.i.posthog.com)
so requests bypass ad blockers and tracking-protection that target the
*.i.posthog.com hostname directly. Hardcodes POSTHOG_HOST = "/ingest"
in the provider, points ui_host at https://eu.posthog.com so PostHog UI
links still resolve, and excludes /ingest from the middleware matcher
so the proxy itself doesn't fire phantom pageviews. Mirrors the same
fix in docs/.
Sidebar / IA / HITL cleanup from the shell-docs QA triage:
- Add `absent` mode to `<WhenFrameworkHas>` so MDX pages can declare a
fallback branch for frameworks where a flag is null/missing, instead
of collapsing to an empty middle.
- Use the new `absent` branch on `useInterrupt.mdx` and `headless.mdx`
to point readers without `interrupt_pattern` at `useHumanInTheLoop`.
- Wrap the `useHeadlessInterrupt`-using "Driving it from plain UI"
section in `headless.mdx` inside the native gate where the symbol is
actually defined.
- Add `multi-agent/meta.json` so breadcrumbs / section labelling for
`/multi-agent/subagents` use the explicit "Multi-Agent" title.
- Add a shared lead-in between `<InlineDemo>` and the gated branches in
`agent-config.mdx`.
- Move `ag-ui-middleware.mdx` into `agentic-protocols/`, register it in
the section's `meta.json`, link to the upstream AG-UI guide, and add
a 302 from the old `/ag-ui-middleware` path.
Drop orphaned/broken/AI-slop pages from nav, add 302 redirects, and
delete dead per-framework override stragglers. Items addressed:
- 1.1: Tutorials section hidden (broken end-to-end; rewrite post-launch)
- 6.1: coding-agent-setup.mdx (rename straggler -> /coding-agents)
- 10.1: copilot-suggestions.mdx (orphaned broken stub)
- 11.1: generative-ui/open-json-ui.mdx (AI-slop placeholder)
- 21.1: migrate/1.10.X.mdx (~1yr-old migration target)
- 16.1: 3 orphan shared-state files in adk/langgraph/llamaindex
(each meta.json wires only one of state-inputs-outputs vs
workflow-execution; the other was a dead duplicate)
All redirects use permanent: false (302) so URLs can be restored at
the same paths once the affected pages are properly authored.
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
...
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.
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.
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 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.
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.
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.
Shell owns /integrations (live explorer) and /matrix (feature matrix),
mirroring shell's existing redirect table that sends /docs/*, /ag-ui/*,
/reference/*, and /<framework>/* to the docs host. Adds the reverse
redirects in shell-docs' next.config so /integrations and /matrix jump
out to showcase.copilotkit.ai at the edge.
Removes the redundant shell-docs framework-picker page at
showcase/shell-docs/src/content/docs/integrations/index.mdx. All internal
links can now use bare /integrations hrefs — the redirect handles the
cross-host jump in production, and in dev it 404s cleanly (no local
page to render). Legacy per-framework subtrees under integrations/* are
unchanged.
Replace the argv-sniffing 'process.argv.includes("build")' check with
process.env.NEXT_PHASE === "phase-production-build", the Next.js
canonical signal for a production build. The argv approach is fragile:
it breaks under wrappers, programmatic invocation, or any tool that
invokes next via a different argv shape.