Two things this PR was missing, both now closed.
## The Claude SDK quickstarts are unblocked
#6618 put `showcase/integrations/claude-sdk-{python,typescript}` on
`createCopilotRuntimeHandler` with `mode: "single-route"`, at the **plain**
`route.ts` path. That dissolves the coupling that forced these two pages to be
reverted earlier: `verify-shell-docs.ts` asserts each page claims a starter file
at `src/app/api/copilotkit/route.ts` AND that the file exists in the extracted
starter. Single-route keeps that path, so the prose claims and
`requiredStarterFiles` are unchanged — only the fence bodies move to v2.
The two content assertions that pinned those pages to v1
(`ExperimentalEmptyAdapter`, `copilotRuntimeNextJSAppRouterEndpoint`) now
require `createCopilotRuntimeHandler`, the `/v2` entrypoint,
`mode: "single-route"` and a `POST` export. Mutation-checked: flipping the
fixture to `mode: "multi-route"` fails with
`app/api/copilotkit/route.ts missing single-route mode`.
## Snippet gating: 1 -> 20 route fences
I previously claimed the integration pages could not be doctested because of
path aliases and per-integration deps. **That was an assumption I never
checked, and it was wrong.** Of the 52 migrated route fences, 47 import nothing
project-relative; 36 are complete, self-standing routes. 27 pages were
eligible, 20 now hold a gated fence — each extracted and typechecked by
`tsc --noEmit` against real npm-installed packages in CI.
One fence per (page, title): `extract.ts` concatenates tagged blocks sharing a
title, so a second complete route on the same page would collide.
Mutation-checked on `snippets/integrations/langsmith/index.mdx`: restoring the
v1 import in the gated fence turns the run red (20 passed, 1 failed). My first
attempt at this check was a no-op — the pattern missed because the fence is
JSX-indented — and it "passed" misleadingly. The real check asserts the mutation
reached the extracted snippet before trusting the result.
### Harness changes this needed
- `extract.ts` now finds the nearest `doctest.json` by walking up to the docs
root, instead of looking only in the page's own directory. Otherwise gating
20 pages means ~20 duplicated dependency lists that then drift. A shared list
lives at `content/doctest.json`; `docs/integrations/langgraph/` keeps its own
(Python deps) and now also carries the TS deps its page needs.
- `run.ts` installs each dependency set **once**, into
`.doctest-output/.deps/<hash>`, and links it into every snippet sharing that
set. Per-snippet installs took **7:58** for 21 snippets, uncomfortably close
to the job's 15-minute timeout; shared installs take **0:45** cold. Different
dep sets still get separate stores, so this is a dedupe, not a merge.
### `@ag-ui/*` versions have to be pinned to what the runtime expects
Unpinned, the gated fences failed with `HttpAgent is not assignable to
AbstractAgent — separate declarations of a private property '_debug'`: npm
installs a newer `@ag-ui/client` than `@copilotkit/runtime` depends on, so two
`AbstractAgent` declarations collide. The sidecar pins `@ag-ui/client@0.0.57` and
`@ag-ui/core@0.0.57` to match `@copilotkit/runtime@1.68.3`.
## Seven fences are deliberately NOT gated
Un-tagged with the reason, rather than left failing or quietly dropped:
- `docs/auth.mdx`, `docs/premium/connect-your-runtime.mdx` — illustrative
fences referencing placeholders (`myAgent`, `verifyJwt`) that cannot compile
standalone by design.
- the four langgraph-family pages and
`snippets/self-hosting-copilot-runtime-langgraph-endpoint.mdx` — these hit
`LangGraphAgent is not assignable to AbstractAgent — separate declarations of
a private property '_debug'`, which pinning does not fix.
**That last one is a real pre-existing defect, not a migration regression.** I
reconstructed the v1 form of the langgraph quickstart snippet verbatim from
`origin/main` and typechecked it against the identical installed dependencies:
it fails with the same error. So these snippets have never typechecked against
published packages — worth filing separately. It is also what the ~220
`@ts-ignore` comments across `showcase/integrations` were papering over.
## Verified
doc-tests (cold, no cache) -> 21 passed, 0 failed in 0:45
mutation check (real, verified) -> 20 passed, 1 failed
vitest extract + verify-shell-docs -> 34 passed
showcase/shell-docs typecheck -> exit 0
showcase/shell-docs build -> exit 0
structural audit -> 21/21 pages, fence + JSX identical to HEAD
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The earlier commits in this PR taught `createCopilotEndpoint` paired with
`handle` from `hono/vercel`, and added `hono` to 20 install commands with a
callout explaining why readers must install it. Both were wrong, and the second
was a consequence of the first.
`createCopilotEndpoint` is a **deprecated alias**. This repo's own handler table
says so — `docs/backend/runtime-endpoints.mdx`:
| Deprecated | Use instead |
| `createCopilotEndpoint` | `createCopilotHonoHandler` |
| `createCopilotEndpointSingleRoute` | ... with mode: "single-route" |
`createCopilotRuntimeHandler` serves the same multi-route mode (it is the
default), returns a plain fetch handler, is not deprecated, and needs **no hono
at all**. So the route collapses to:
const handler = createCopilotRuntimeHandler({
runtime,
basePath: "/api/copilotkit",
});
export const GET = handler;
export const POST = handler;
`hono` was therefore an artifact of the shape, not a requirement of the library.
The install lines and the callout are reverted; nothing tells readers to install
it any more.
## Verified with hono deleted, not merely absent from package.json
`examples/shadcn` converted to this shape, `hono` removed from its
`package.json`, and `node_modules/hono` deleted outright so a hoisted copy could
not mask the result:
GET /api/copilotkit/info -> 200
POST /api/copilotkit/agent/default/run -> 200, chat turn rendered
tsc --noEmit / eslint / next build -> clean
next build route -> ƒ /api/copilotkit/[[...slug]]
The doctest sidecar drops `hono` too, so the CI gate now typechecks the
canonical snippet against `@copilotkit/runtime` alone — proof by construction
that the snippet needs nothing else.
pnpm tsx scripts/doc-tests/run.ts -> 2 passed, 0 failed
showcase/shell-docs: typecheck -> exit 0
showcase/shell-docs: build -> exit 0
structural audit: 31/31 mdx files, fence + JSX identical to HEAD
## Also corrected
`docs/backend/custom-agent.mdx` repeated the same incorrect transport claim the
earlier commit fixed in four other places ("Both `<CopilotKit>` and
`<CopilotKitProvider>` negotiate the transport when the prop is omitted").
Corrected to match released behaviour.
## Left alone deliberately
`snippets/shared/backend/custom-agent.mdx` and `docs/backend/custom-agent.mdx`
still call `createCopilotEndpoint` in three fences each, as
`export default copilotEndpoint` — the Hono-app deployment pattern rather than a
Next.js route handler. That predates this PR, the documented replacement is
`createCopilotHonoHandler`, and I have not run that shape. Recorded as follow-up
rather than guessed at. (The two files have also drifted from each other, which
is a separate problem.)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Migrates the Next.js App Router runtime fences across the docs from the v1
entrypoint to the v2 multi-route shape proved in `examples/shadcn`: catch-all
path, `createCopilotEndpoint`, a runner, and both verbs exported. 38 fences
across 33 pages.
Only the boilerplate is rewritten. Each page's agent wiring — `MastraAgent`,
`LangGraphAgent`, `HttpAgent`, `BuiltInAgent`, middleware `.use(...)` calls —
is left byte-identical, because that part is not what was broken.
Three co-changes travel with every migrated page, since the shape does not work
without them:
- `hono` added to the page's install command (20 lines). It is a dependency of
`@copilotkit/runtime`, not a peer, so `hono/vercel` resolves under npm's flat
layout but not under pnpm.
- `useSingleEndpoint={false}` on `<CopilotKit>` (27 provider tags). The
provider defaults to the single-route transport, which posts to the bare
`runtimeUrl`; a multi-route runtime answers with 404. Only tags carrying a
`runtimeUrl` are touched — a provider using `agents__unsafe_dev_only` has no
runtime to match. Angular's `provideCopilotKit` defaults its transport to
`"auto"` and needs no equivalent, so those snippets are unchanged.
- fence titles retitled to the catch-all path, plus the prose that introduces
them, so no snippet claims a path its body contradicts.
`LangGraphAgent` moves from the v1 root entrypoint to
`@copilotkit/runtime/langgraph` on one page. Both spellings resolve, but the
subpath is the one that survives the v1 entrypoint; verified by typechecking
`LangGraphAgent` + v2 `CopilotRuntime` + `createCopilotEndpoint` together
against the published 1.68.3.
## Two mistakes worth recording, since both were caught by a check rather than by reading
A block regex scoped to the fence's opening indentation corrupted five
quickstart pages: their fences open and close at *different* indentation, so
the match ran past the closing backticks and re-indented the following
`</Step>` / `</Tab>` boundary into the code block. The five pages were reverted
and redone with a line-oriented pass that never re-indents anything and
re-emits the original closing line verbatim.
Every modified page is now checked structurally — fence-marker count and the
full set of JSX structural lines, indentation included, must be identical to
`HEAD`. All 33 pass. That check is what found the corruption; a diff review had
already missed it on the first pass.
## Verified
pnpm tsx scripts/doc-tests/extract.ts -> 2 snippets
pnpm tsx scripts/doc-tests/run.ts -> 2 passed, 0 failed
showcase/shell-docs: pnpm typecheck -> exit 0
showcase/shell-docs: pnpm lint -> exit 0 (pre-existing warnings only)
showcase/shell-docs: pnpm build -> exit 0
structural audit: 33/33 pages, fence + JSX structure identical to HEAD
Note this validates that the pages still build and that the one doctested
snippet compiles. It does not execute the other 37 fences. Their correctness
rests on Stage 0: the boilerplate they now contain is the text that was run in
`examples/shadcn`, and their agent wiring is untouched.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Embed the live demo directly in the cookbook recipe, mirroring the in-doc
iframe approach used by integration landing pages (framework-overview.tsx
liveDemos[] / IframeSwitcher). The recipe now opens with a 'Try it live'
section above the prerequisites, iframing the showcase deployment so
readers can drive the runCode tool against a real Daytona sandbox without
leaving the page.
URL is a placeholder ('showcase-daytona-runcode-production.up.railway.app',
matching the showcase-{slug}-production.up.railway.app backend host
pattern from the registry generator). Will render Railway's not-found
page until a permanent demo deployment is provisioned at that name; the
inline MDX comment notes the placeholder.
OSS-222
Addresses PR review feedback (@tylerslaton): the docs/ folder is deprecated
in favor of showcase/shell-docs and will be removed soon. Move the entire
Cookbook contribution to shell-docs:
- showcase/shell-docs/src/content/docs/cookbook/ — landing + Daytona recipe
copied verbatim (Fumadocs frontmatter/components/dividers all match).
- showcase/shell-docs/src/content/docs/meta.json — new top-level
'---Cookbook---' divider with a '...cookbook' spread, slotted between
Platforms and Other.
- showcase/shell-docs/src/components/brand-nav.tsx — Cookbook tab added to
LEFT_LINKS (lucide ChefHat icon) and active-route detection extended so
/cookbook/* highlights it (peer to the existing Reference handling).
Reverts all earlier edits to docs/ from this PR (navbar, root meta, learn
meta, and the docs/content/docs/cookbook/ tree) so the deprecated folder is
left at zero-diff vs main.
OSS-222