- Escape every interpolated value in convertMarkdownTableToHtml to
close an XSS vector: MDX table cells with HTML-significant characters
(e.g. <script>, &) previously landed raw in the generated markup.
- Scope readTitle and loadDoc title/description lookups to the
frontmatter block so a 'title:' / 'description:' that happens to
appear inside the MDX body (code samples, example config) can't
override the real frontmatter.
- Export a small escapeHtml helper for reuse within this module;
duplicated rather than imported from snippet.tsx to keep
docs-render server-only.
The img and video MDX shims spread props then overrode className to
undefined, silently dropping any className from authors' MDX. Remove the
bogus override so user-supplied className flows through.
Button had no type attribute, defaulting to type="submit" inside a
form (unintentional submits). Default to type="button", accept and
forward onClick/disabled/aria-label, and emit a dev-mode warning when
rendered without onClick so MDX authors learn their Button is
non-interactive.
IframeSwitcher had no sandbox attribute, letting user-controlled MDX embed
malicious-origin iframes with full browser capabilities. Mirror the
InlineDemo sandbox policy (scripts/same-origin/forms/popups) and add an
a11y title.
YouTubeVideo was missing both a title (screen readers announced only the
URL) and a sandbox policy. Add sandbox tuned for YouTube embeds
(scripts/same-origin/presentation/popups) and title fallback.
Extracts everything that exists to render MDX documentation (docs/[[...slug]],
[framework]/[[...slug]], ag-ui/[[...slug]], reference/[...slug]) out of shell
into the new shell-docs package that will serve docs.showcase.copilotkit.ai.
Moves (git mv preserves history):
- App routes: /docs, /[framework], /ag-ui, /reference
- Docs-only components: docs-page-view, docs-callout, docs-steps, docs-tabs,
mdx-components, framework-tabs, framework-selector, sidebar-*, snippet,
property-reference, router-pivot, stored-framework-highlight, react/*
- Docs-only libs: lib/docs-render, lib/mdx-registry
- All content: content/docs, content/ag-ui, content/reference, content/snippets
- .docs-sync-sha marker (follows the content)
Duplicates into shell-docs (both shells need them):
- brand-nav, search-modal, search-trigger, copy-button, framework-provider
- lib/registry.ts, data/registry.json, data/demo-content.json,
data/search-index.json
- app/layout.tsx + globals.css + public/{images,logos}
shell-docs gets its own minimal middleware (PostHog-only — no SEO redirect
table, docs host never served legacy URLs). shell keeps seo-redirects.ts
for the legacy-URL migration table; framework-scope protection in its
middleware is now effectively dead but harmless (next.config.ts redirects
fire before middleware ever sees /<framework>/ paths).
InlineDemo updated for cross-host context: 'Open full demo' link points
at the shell host (showcase.copilotkit.ai) since the integration profile
route only exists there.