Tighten the gap between the page header and the body to canonical's
mb-8 (was mb-14 with a responsive ladder that opened a half-inch hole
at xl widths between the description paragraph and the first prose
paragraph).
Align the sidebar treatment to canonical:
- Section header banner uses the same Plus Jakarta default-weight
uppercase + tracking as canonical's separator, sized up to 15px so
it sits above the link list as a clear divider rather than a tiny
caption below it.
- Section divider rule uses --border (white/10 in dark, #d9d9e0 in
light) so the horizontal line survives the dark token set.
- Active-link pill picks up dark-mode contrast: --bg-hover surface
with a 1px white/10 ring instead of the near-flat --bg-surface
that read as undifferentiated against the sidebar bg in dark.
- Idle pages get a white/5 hover affordance in dark.
- Nested section separators (depth > 0) demote to a quiet 11px
uppercase label in --text-faint with no divider rule, so the
Build Generative UI > Controlled / Declarative / Open-Ended
subsection breaks read as inline labels inside their parent
group instead of competing banner headers.
Move the root /docs overview route onto the same SidebarNav +
.docs-content-wrapper + max-w-[900px] mx-auto pattern docs-page-view
uses, and rewrite OverviewNavItem so sections, pages, and groups
paint with the same tokens as the per-doc routes -- previously the
root was still rendering against the pre-wave3 shell with a 240px
sidebar, p-4 padding, browser-default scrollbar, and an off-center
max-w-4xl content column.
Rename the "Give Your App Agent Powers" main-meta section to
"Adding Agent Powers" per product copy.
The TOC scrollspy used IntersectionObserver with a -20%/-70% root
margin band, which never fires for the last heading once the user
has scrolled it past that band. The active state stayed parked on
whichever heading last entered the band even when the user had
clearly arrived at the document end.
Replace with a scroll listener on .docs-content-wrapper that walks
the heading list, picks the last heading whose top has crossed the
trigger line (~25% from the viewport top), and forces the final
heading active when the scroll container is at scrollMax. Falls back
to window scroll for routes that don't wrap content in
.docs-content-wrapper.
Add a .dark token block to globals.css mirroring canonical
docs.copilotkit.ai for every var the wave3 chrome consumes (--bg,
--bg-surface, --bg-elevated, --bg-hover, --border, --border-dim,
--sidebar, --glass-background, --text*, --accent*, --violet*, --blue,
--scrollbar-color, --scrollbar-track). The navbar already shipped a
Toggle theme button + sun/moon SVGs + documentElement.classList
.toggle('dark') + localStorage.theme persistence; this commit makes
that toggle paint the rest of the page because all wave3 chrome
(sidebar, navbar, banner, callouts, tables, TOC, content wrapper)
consumes those vars.
Add @custom-variant dark (&:is(.dark *)) so dark: Tailwind utilities
react to the .dark class instead of prefers-color-scheme. Without
this, the navbar's class-driven swap pairs (slanted-end-border-dark
vs -light, theme-moon vs theme-sun, every dark: utility) are dead
when the theme toggle runs.
Add an inline beforeInteractive script in <head> that reads
localStorage.theme (falling back to prefers-color-scheme) and applies
the class before first paint, with suppressHydrationWarning on <html>
so Next.js doesn't revert the class to match the server output.
Apply scrollbar-width: thin and scrollbar-color to .docs-content-wrapper
and the sidebar's inner scroll container so the thumb tracks the
active theme instead of paying the bright browser default that pops
against dark surfaces.
Bump dark-mode contrast on the icon-button hover surface in the
navbar (GitHub, Discord, theme toggle) to a rounded black/5 in light
and white/10 in dark so the buttons read as interactive.
The search modal renders inside SearchTrigger, which lives in the
navbar's right cluster. The cluster has backdrop-blur-lg, and
backdrop-filter creates a containing block for fixed-position
descendants. The modal's `fixed inset-0` overlay was therefore being
clamped to the cluster's bounding rect (~505x70 at 1440x900) instead
of the viewport, so the overlay+card rendered as a tiny clipped strip
under the search button.
Wrap SearchModalWrapper in createPortal mounted on document.body. The
modal now resolves position: fixed against the viewport like a normal
overlay.
The 53 hard-500 URLs in the public sitemap split into three independent
root causes, all surfaced in production-mode rendering only because the
underlying issues throw inside next-mdx-remote:
1. tutorials/ai-powered-textarea/step-2-setup-copilotkit and
tutorials/ai-todo-app/step-2-setup-copilotkit reference
<CopilotCloudConfigureCopilotKit>,
<SelfHostingCopilotRuntimeConfigureCopilotKit>, and
crewai-flows/quickstart references <CloudCopilotKit> — three
unsuffixed component names whose only registered counterparts in
docsComponents end in "Provider". MDX rendering throws "Expected
component X to be defined" and 500s. Adds the unsuffixed names as
aliases of the existing Provider stubs in mdx-registry.
deploy-agentcore (langgraph variants + aws-strands) uses
<Content framework="..." />, also unregistered. Adds Content as a
children-passthrough stub for the same reason.
2. Three langgraph tutorial pages (agent-native-app/step-6-shared-state,
ai-travel-app/step-3-setup-copilotkit,
ai-travel-app/step-4-integrate-the-agent) place a closing </Step>
tag immediately under a markdown bullet list with no blank line
separator. The remark parser treats the closing tag as a list-item
continuation, errors out with "Expected the closing tag </Step>",
and ships a 500. Adds the missing blank line before the close tag.
3. Five MDX files (llamaindex + adk shared-state/predictive-state-updates,
pydantic-ai shared-state/in-app-agent-write, plus crewai-flows and
pydantic-ai human-in-the-loop/index — last two not in the 53 but
share the bug) use {/\\* ... \\*/} where the asterisks are escaped.
Acorn cannot parse the resulting expression and the page 500s.
Replaces the escapes with proper {/* ... */} JSX comments.
Verified: a clean production build of shell-docs followed by
`npx next start` and a curl probe of all 53 URLs from
validation/test2_results.json returns 200 across the full set with
zero MDX or React errors in the server log.
Two issues found in Phase 4 validation against docs.showcase.copilotkit.ai.
1. 31 entries in seo-redirects.ts had source === destination, causing
middleware to issue infinite 301 loops on canonical URLs like
/frontend-tools, /faq, /human-in-the-loop. Remove the dead entries
and add a defense-in-depth skip-when-equal guard in middleware so
future drift cannot regress.
2. Framework-scoped paths (e.g. /agno/frontend-actions) bypassed the
redirect catalog entirely because the pathIsFrameworkScoped short-
circuit fired before any catalog lookup. Reorder middleware so the
exact-match catalog is consulted first for every request, including
framework-scoped paths. Wildcard scan still skips legacy patterns
that would hijack canonical framework URLs, but allows same-framework
wildcard rewrites (e.g. /agno/concepts/:path* -> /agno) to fire.
85 framework-scoped redirects across 18 registry slugs now resolve
instead of soft-404ing.
Verified by curl probes against localhost: all 85 framework-scoped
catalog entries 301 to the expected destination, all 31 former self-
loop URLs return 200, and canonical framework URLs (/agno, /langgraph-
python/quickstart, etc.) still pass through unchanged.
The InlineDemo Code tab constructs a feature-viewer.copilotkit.ai URL
from the integration's docs-folder name, but feature-viewer expects its
own slug scheme. Six framework slugs 404'd outright (built-in-agent,
google-adk, claude-sdk-python, claude-sdk-typescript, ms-agent-python,
ms-agent-dotnet) and two more were named differently (crewai-crews
needed crewai, llamaindex needed llama-index). Demo IDs also diverged
(gen_ui_tool_based vs tool_based_generative_ui, hitl_in_chat vs
human_in_the_loop, etc.) so even when the framework slug was right the
Code panel rendered an empty 404 page.
Add getFeatureViewerSlug() and getFeatureViewerDemoId() to registry.ts
with explicit override maps. Both return null when the integration or
demo has no feature-viewer counterpart. Update mdx-registry.tsx to use
both and to suppress the Code tab (rendering the Demo iframe alone)
whenever either helper returns null.
Verified by probing feature-viewer.copilotkit.ai for each (framework x
demo) combination using NEXT_HTTP_ERROR_FALLBACK soft-404 detection plus
inspection of the rendered code panel; all post-fix URLs that the
helpers emit resolve to real code panels for the six demos
feature-viewer ships (agentic_chat, tool_based_generative_ui,
agentic_generative_ui, predictive_state_updates, shared_state,
human_in_the_loop).
The active-link pill in the docs sidebar rendered flush against the
scroll gutter because the inner scroll container had no right padding;
canonical adds pr-1 on its scroll container so the pill stops 4px short
of the scrollbar. Match that.
The content column used px-8 py-6 xl:px-16 xl:py-12 with a non-centered
max-w-[900px] cap, which pushed content 32px to the right of canonical
at xl widths and left a wide gap between content and the right rail.
Replace with canonical's exact pattern: px-4 py-6 md:px-6 md:pt-8
xl:px-8 xl:pt-14 outside, max-w-[900px] mx-auto inside, so the column
centers between sidebar and TOC and the h1 lands at the same x as
docs.copilotkit.ai at 1440.
Updates the docs navbar and showcase shell-docs brand-nav so the "Talk
to engineers" CTA points at copilotkit.ai/talk-to-an-engineer instead
of the deprecated /contact-us endpoint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## 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.
## Summary
- Updates the V1 reference autogen entry in `scripts/docs/lib/files.ts`
for the upstream rename of `sdk-python/copilotkit/langgraph_agent.py` to
`langgraph_agui_agent.py`. The class also renamed from `LangGraphAgent`
to `LangGraphAGUIAgent` (now subclasses the upstream `LangGraphAgent`).
- Updates `sourcePath`, `destinationPath` (now
`LangGraphAGUIAgent.mdx`), `title`, `description`, and `pythonSymbols`
to match.
- Regenerates
`showcase/shell-docs/src/content/reference/sdk/python/LangGraphAGUIAgent.mdx`.
The autogen run now reports 26/26 entries succeeding (was 25/26 — the
previous entry failed silently via `Promise.allSettled` because the
source file no longer existed).
Stacked on top of #4693 (autogen-retarget). Once that lands this PR can
be retargeted at `main`.
## Test plan
- [x] `tsx scripts/docs/gen.ts` from repo root succeeds with `All
reference docs processed (26/26 succeeded)`.
- [x] `npm run build` in `showcase/shell-docs/` clean (Next build
prerendered 27/27 routes).
- [ ] Spot-check rendered `/reference/sdk/python/LangGraphAGUIAgent` on
a dev server. Note: the new `LangGraphAGUIAgent` class in `sdk-python`
does not yet carry a class-level docstring, so the generated MDX is
currently frontmatter-only. Adding a docstring upstream will populate
the page on the next pipeline run.
## Summary
Two commits porting the V1 reference autogen pipeline so it writes into
shell-docs instead of the legacy upstream tree. Without this,
`/reference/v1/*` URLs (around 20k pageviews per quarter on
`docs.copilotkit.ai`) would 404 or 301 to a stub on shell-docs after the
cutover.
- `c30613c8d` Retarget the autogen pipeline. `scripts/docs/gen.ts` is
the entrypoint; `scripts/docs/lib/files.ts` carries the `REFERENCE_DOCS`
array with hardcoded `destinationPath` strings. Switched all
destinationPath strings from `docs/content/docs/reference/v1/...` to
`showcase/shell-docs/src/content/reference/v1/...`. Routing was verified
via `src/app/reference/[...slug]/page.tsx` (which reads from
`src/content/reference/`, not the legacy `content/docs/reference/`
tree). Anchored cwd to repo root in `gen.ts` to fix a latent
path-resolution bug that had broken the pipeline upstream too. Switched
the orchestration to `Promise.allSettled` so one source-rename rot
doesn't abort the rest.
- `55e72eeec` Lefthook auto-format pass.
## What this generates
25 of 26 V1 reference docs land in
`showcase/shell-docs/src/content/reference/v1/`:
- 20 under `reference/v1/{components,hooks,classes}` (TypeScript-source
autogen)
- 5 under `reference/v1/sdk/python/` (Python-source autogen)
The 26th entry (`sdk-python/copilotkit/langgraph_agent.py` to
`langgraph_agui_agent.py` rename) is tracked separately as a follow-up.
## Test plan
- [ ] `npm run build` from `showcase/shell-docs/` clean.
- [ ] Visit `/reference/v1/hooks/useCopilotAction`,
`/reference/v1/classes/CopilotRuntime`,
`/reference/v1/components/chat/CopilotChat`,
`/reference/v1/sdk/python/LangGraph` on the dev server. Confirm full
content renders.
- [ ] Re-run `tsx scripts/docs/gen.ts` on a clean checkout. Confirm
25/26 entries succeed; the LangGraph SDK Python entry fails gracefully
without aborting the rest.
## Timing note
Merging this pre-cutover means upstream's
`docs/content/docs/reference/v1/*` MDX files freeze at their current
state. If anyone re-runs autogen between now and 5/12 the regenerated
MDX goes to shell-docs only. V1 surface is stable so the practical risk
is small, but the safest move is to hold this PR until cutover day. Open
question for review.
## Summary
Two-part redirect work for the docs.copilotkit.ai → shell-docs cutover,
in one PR.
### Part 1 — Retarget destinations in `seo-redirects.ts`
shell-docs serves canonical framework docs at `/{fw-slug}/...` from the
host root (no `/docs/` prefix) and uses different framework slugs from
the legacy SHELL surface. The redirect catalogue has been retargeted
accordingly:
- **Drop the `/docs/integrations/` prefix** from every destination.
- **Apply framework-slug renames** in destinations:
- `langgraph` → `langgraph-python`
- `adk` → `google-adk`
- `aws-strands` → `strands`
- `microsoft-agent-framework` → `ms-agent-dotnet`
- `crewai-flows` → `crewai-crews`
- **Re-flip the BIA → unselected rename** — `unselected/` was retired;
destinations now point at `/built-in-agent/`.
- **Slug-rename catch-alls** for the bare `/{old-slug}/*` form so legacy
upstream URLs (e.g. `/langgraph/quickstart`) 301 directly to the new
slug.
- **`/docs/integrations/*` and `/docs/*` catch-alls** so any URL still
carrying the legacy SHELL routing prefix lands at the shell-docs
equivalent.
- **`/migration-guides/*` → `/migrate/*`** (4 URLs).
- **Folder-index redirects** for shell-docs folders without an
`index.mdx` (`/troubleshooting`, `/migrate`, `/premium`, `/concepts`,
`/reference`).
390 redirect entries total in the new catalogue.
### Part 2 — Port middleware to shell-docs
- Copied the retargeted `seo-redirects.ts` to
`showcase/shell-docs/src/lib/`.
- Merged the SHELL redirect-middleware logic into shell-docs's existing
pageview-tracking middleware. Redirects fire first (with the
`seo_redirect` PostHog event); non-redirected requests still get the
`docs_pageview` capture and `distinct_id` cookie.
- Preserved the framework-scoped short-circuit so canonical
`/{fw-slug}/...` URLs are never hijacked by legacy patterns.
- Left the SHELL versions of `middleware.ts` and `seo-redirects.ts` in
place — the SHELL still serves `docs.showcase.copilotkit.ai` until DNS
flips.
## Test plan
- [x] `npm run build` clean in `showcase/shell-docs/`
- [x] `npm run build` clean in `showcase/shell/` (existing operation
unaffected)
- [x] `curl -sI
http://localhost:3099/docs/integrations/langgraph/quickstart` → 301 to
`/langgraph-python/quickstart`
- [x] `curl -sI http://localhost:3099/langgraph/quickstart` → 301 to
`/langgraph-python/quickstart`; `/aws-strands/quickstart` →
`/strands/quickstart`; `/migration-guides/v2` → `/migrate/v2`;
`/troubleshooting` → `/troubleshooting/common-issues`; `/coagents` →
`/langgraph-python`
- [ ] Validate full set against a running shell-docs instance with
`validate-redirects.ts` (run from `showcase/scripts/` against the
deployed preview)
R15 and R17 sources were /builtin-agent (no hyphen), matching no real traffic. Real legacy URLs live under /integrations/built-in-agent/* (47 URLs in the upstream sitemap). Retarget the source patterns to match.
Adds a Callout linking to "Build Interactive Agents with Generative UI"
(free DeepLearning.AI short course) on the two Generative UI overview
pages and the six lesson-specific pattern pages (display-only,
tool-rendering, state-rendering, open-generative-ui, a2ui, mcp-apps),
mirrored across docs/ and showcase/shell-docs/.
The earlier V2 canonical sweep misread the brand-name guidance ("always
CopilotKit") as a directive on import paths and stripped /v2 from
@copilotkit/react-core specifiers. Inline review feedback clarified that
guidance applied only to the component name. This restores
"@copilotkit/react-core/v2" and "@copilotkit/react-core/v2/styles.css"
across the docs sweep scope (now including 8 framework quickstarts
inherited via rebase onto main); the <CopilotKit> rename and the drop
of @copilotkit/react-ui from install commands are kept.
Registry demo slugs are dash-form (`agentic-chat`); feature-viewer.copilotkit.ai
serves them at underscore-form (`agentic_chat`). The Code tab iframe was
404'ing because the slug was passed through verbatim. Replace `-` with `_`
when building the code URL.
Wraps the InlineDemo iframe in a Demo / Code tab strip mirroring the
IframeSwitcher component, so pages using <InlineDemo demo="..." /> now
expose both the live demo (integration backend) and a code view. The
code iframe points at feature-viewer.copilotkit.ai/<framework>/feature/
<demo>?view=code&sidebar=false&codeLayout=tabs, where <framework> is
translated through getDocsFolder() to map registry slugs like
langgraph-python down to their upstream folder name (langgraph) used by
the feature viewer.
The mdx-registry shipped a stub IframeSwitcher that took `src`/`title`
props and rendered a single iframe. MDX consumers actually pass
`exampleUrl`/`codeUrl`/`exampleLabel`/`codeLabel`, so the stub was
silently dropping those props and rendering an empty container. The
result: pages using `<IframeSwitcher>` showed no demo+code tabs.
Replace the stub with the real component from `@/components/content`,
which matches the props shape consumers actually use.
IframeSwitcher: forward the `id` prop to a wrapping `<div id={id}>` so MDX
authors can deep-link to a specific switcher instance. The prop was
declared but never consumed.
oss-vs-enterprise.mdx: fix the Frontend SDK bullet to reflect canonical
V2 — both hooks and prebuilt components ship from `@copilotkit/react-core`
(the standalone `@copilotkit/react-ui` package is V1-era).
Several MDX files import `IframeSwitcher` from `@/components/content`
(prebuilt-components, frontend-tools, interactive, tool-rendering, plus
integration overrides), but the component file was missing. This adds it
as a thin wrapper around the existing `<Tabs>` component, rendering a
demo iframe and a code iframe in a Tabs strip.
Props: `exampleUrl`, `codeUrl`, `exampleLabel` (default "Demo"),
`codeLabel` (default "Code"), `height` (default "600px"). Both iframes
are sandboxed and lazy-loaded.
Matches the upstream IframeSwitcher pattern used on docs.copilotkit.ai
to render embedded feature-viewer demos alongside their backing code.
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.
Apply the canonical V2 import form across all V2 docs:
- `<CopilotKit>` (not `<CopilotKitProvider>`)
- imports from `@copilotkit/react-core` (root, not `/v2`)
- styles from `@copilotkit/react-core/styles.css` (not `react-ui/v2/styles.css`)
- drop `@copilotkit/react-ui` from npm install commands
Fix V2 leaks in canonical pages: replace stale `useCopilotAction` and
`useCopilotReadable` references in agentic-protocols/a2a.mdx and
backend/custom-agent.mdx with their V2 equivalents (`useFrontendTool`,
`useAgentContext`).
Excludes intentional V1 references in migrate guides, V1 reference tree,
migration callouts, and V1 release notes.
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.
Part 1 — Retarget seo-redirects.ts destinations:
- Drop the legacy /docs/integrations/ prefix everywhere; shell-docs
serves canonical framework docs at /<fw-slug>/<...> from the host
root.
- Apply registry-slug renames in destinations:
langgraph → langgraph-python
adk → google-adk
aws-strands → strands
microsoft-agent-framework → ms-agent-dotnet
crewai-flows → crewai-crews
unselected → built-in-agent (BIA canonical re-flip)
- Add slug-rename catch-alls for the bare /<old-slug>/* form so legacy
upstream URLs (e.g. /langgraph/quickstart) 301 to the new slug.
- Add /docs/integrations/* and /docs/* catch-alls so any URL still
carrying the legacy SHELL routing prefix lands at the shell-docs
equivalent.
- Add /migration-guides/* → /migrate/* (4 URLs).
- Add folder-index redirects for shell-docs folders without an
index.mdx (/troubleshooting, /migrate, /premium, /concepts,
/reference) so bare folder URLs land on a representative inner page.
Part 2 — Port the redirect middleware to shell-docs:
- Copy the retargeted seo-redirects.ts to shell-docs/src/lib/.
- Merge the SHELL redirect-middleware logic into shell-docs's existing
pageview-tracking middleware: redirects fire first (with seo_redirect
PostHog event), and non-redirected requests still get the
docs_pageview capture and distinct_id cookie.
- Preserve the framework-scoped short-circuit so canonical
/<fw-slug>/<...> URLs are never hijacked by legacy patterns.
- Leave the SHELL versions in place — the SHELL still serves
docs.showcase.copilotkit.ai until DNS flips.
Verified shell-docs and SHELL builds clean. Spot-checked redirects on a
local shell-docs server: /docs/integrations/langgraph/quickstart →
/langgraph-python/quickstart, /langgraph/quickstart →
/langgraph-python/quickstart, /migration-guides/v2 → /migrate/v2,
/troubleshooting → /troubleshooting/common-issues, /coagents →
/langgraph-python, /aws-strands/quickstart → /strands/quickstart.
Upstream renamed sdk-python/copilotkit/langgraph_agent.py to
langgraph_agui_agent.py and the class to LangGraphAGUIAgent. Update the V1
reference autogen entry in scripts/docs/lib/files.ts to point at the new
source and class name, and regenerate the shell-docs MDX. Pipeline now
reports 26/26 entries succeeding (was 25/26).
Restructure the "Run our CLI" step in all eight framework quickstarts to surface
two paths: the upstream interactive flow (which now covers the Enterprise
Intelligence Platform prompt and sign-up) and the `--framework <id>` flag fast
path. LangGraph and Microsoft Agent Framework keep both language variants in the
flag block.
Update scripts/docs to write directly into showcase/shell-docs/src/content/reference/
(consumed by /reference/[...slug]) instead of the legacy docs/content/docs tree.
Adds repo-root cwd anchoring, mkdir -p on the destination, allSettled so a single
missing source doesn't abort the run; generates 25 MDX pages (20 V1 + 5 SDK) and
shell-docs build passes.
Switch CLI command to `npx copilotkit@latest create --framework <id>` on all 8
framework quickstarts. Bypasses the unfiltered 18-framework picker and skips
the EIP prompt (which is mutually exclusive with --framework and today
scaffolds langgraph-python-threads regardless of which framework page the
user came from).
For LangGraph: keep an EIP callout since EIP=Yes does scaffold a LangGraph-
Python project today; note that threads support for other frameworks is
coming. For Microsoft Agent Framework and LangGraph (multi-variant): show
both --framework <variant> commands.
Apply the canonical V2 form:
- \`<CopilotKit>\` from \`@copilotkit/react-core\` (root, not /v2).
- styles from \`@copilotkit/react-core/styles.css\` (not react-ui/v2).
- drop \`@copilotkit/react-ui\` from npm install commands.
## Summary
Three small pre-cutover cleanup fixes batched into one PR (consolidation
of the prior #4680, #4681, #4682 — same content, fewer review queues).
- `b3ec38720` — Add `<WhenFrameworkHas absent>` fallback to
`programmatic-control.mdx` for the 7 frameworks without
`interrupt_pattern` (ag2, agno, built-in-agent, crewai-crews,
google-adk, mastra, spring-ai), mirroring the canonical pattern from PR
#4496.
- `c080ca062` — Retarget `/migrate/1.10.X` redirect destination from
`/migrate` (which 404s) to `/migrate/v2`. `permanent: false` preserved.
- `e61e8c36d` — Add `mcp-server-setup.mdx` exclusion to docs sync
script. Shell-docs version is intentionally ahead of upstream (HTTP/SSE
Tabs + `mcp-remote` + Tadata callout); without exclusion the next sync
would clobber it.
Supersedes #4680, #4681, #4682.
## Test plan
- [ ] `nx run shell-docs:dev` and visit `/programmatic-control` while
switching the framework selector to non-native fws — verify fallback
callout renders and links to `/human-in-the-loop`.
- [ ] Visit `/migrate/1.10.X` — should redirect to `/migrate/v2` and
render the V2 migration page.
- [ ] Inspect `showcase/scripts/sync-docs-from-main.ts` PATH_EXCLUSIONS
for the `mcp-server-setup` regex.
The shell-docs Docker build fails because link-to-copilot-cloud.tsx
imports from lucide-react but the package was never added to
shell-docs/package.json. Adding it at ^0.469.0 to match sibling
showcase packages.
Two bugs in the Reo init <Script> in layout.tsx:
- If NEXT_PUBLIC_REO_KEY was unset, the script still ran with
e = "undefined" and fetched https://static.reo.dev/undefined/reo.js.
Sibling REB2B_KEY was correctly gated; Reo now matches.
- Bare interpolation into dangerouslySetInnerHTML — any future env
value containing " or </script> would break out of the inline
literal. Switches to JSON.stringify(REO_KEY) and reuses the
resulting binding inside Reo.init() so the key only appears once.
Pulls the dashboard.operations.copilotkit.ai href + UTM string back
into CLOUD_CTA so the desktop and mobile placements share a single
source of truth. UTM tweaks become a one-line change instead of two.
Two review fixes for framework-selector.tsx:
- Replaces the `posthog-js` singleton import with `usePostHog()` from
`posthog-js/react`, matching the rest of the codebase. Both work after
posthog.init() runs, but the singleton was an outlier.
- Renames the event from `framework_selected` to `docs.framework_selected`
to match the dotted-prefix convention used elsewhere in PostHog
Insights (oss.* / cloud.* / eip.* / pricing.cta_clicked). Cheap to do
now since the event is brand-new with no historical data.
The suppressor was carried over from the original telemetry-stack port
of upstream's posthog-provider.tsx. Its job was masking
ERR_BLOCKED_BY_CONTENT_BLOCKER noise from PostHog requests being
blocked by ad blockers targeting *.i.posthog.com directly.
This PR ships the /ingest reverse proxy (mirroring upstream #4554), so
PostHog calls now flow through the docs host and the underlying
hostname is invisible to ad blockers. With nothing to suppress, the
mask only hid real errors that mention "posthog". Three concrete
problems on top of the dead-code framing:
- Substring match on "posthog" swallows unrelated messages.
- isInitializedRef.current only guards the same component instance,
so HMR or StrictMode remounts re-capture the already-patched
console.error and layer wrappers on each remount.
- originalLog is captured but console.log is never patched.
Resolves PDX-112.
Mirrors upstream #4646 in two changes from the same PR:
- Drop the duplicate useRB2B hook in favor of the canonical
<Script id="reb2b-script"> in app/layout.tsx (gated on REB2B_KEY).
Env var renames from NEXT_PUBLIC_RB2B_ID (the hook's name) to
NEXT_PUBLIC_REB2B_KEY (upstream's canonical name) — deployment
ops will need updating.
- Set capture_dead_clicks: false on PostHog init so the
dead-clicks-autocapture.js bundle isn't pulled in on the critical
path.
Mirrors upstream #4643 + #4646 follow-ups. New trackCommandCopy helper
infers install_type from the leading token (covers npx/pnpm/pip/uv/
docker/curl/brew/helm/kubectl/make/bash/sh, falls back to "code"), and
the CopyTracker provider monkey-patches navigator.clipboard.writeText
once at app boot so every programmatic copy fires cli_command_copied
without per-component instrumentation. Preserves upstream's chained-
wrapper pattern so it coexists with Reo's writeText patch.
Final event shape is { install_type, location? } — the command body
and product props from the original draft were dropped upstream
(commit 0b7b3c77c) before merge.
Adds a Talk to Our Engineers CTA to the right side of the docs nav at
viewports >= 1400px and surfaces it in the mobile burger menu below
that. Fires posthog talk_to_us_clicked with { location: "docs_nav" }
on click, then navigates to copilotkit.ai/contact-us. Mirrors the
event the docs/ navbar fires so docs-originated clicks can be
segmented separately from website clicks (which use "nav").