The shell embeds each demo in a cross-origin iframe whose `allow`
attribute only granted clipboard access. Browsers block
`getUserMedia({ audio: true })` at the Permissions Policy layer in
cross-origin frames unless the parent grants `microphone` via `allow`,
so every voice demo across every integration threw "Microphone
permission denied" before any user prompt was shown.
Add `microphone` to the iframe `allow` in all three places that embed
demo previews — the per-demo viewer, the standalone preview route, and
the demo drawer — so voice demos work uniformly across all 18
integrations. No other demo type uses getUserMedia / getDisplayMedia
/ geolocation, so no other Permissions Policy features are needed.
Heater shield with CopilotKit kite logo in magenta on dark
background, matching the sub-property icon style across
copilotkit.dev properties. Wires up Next.js metadata for
title, description, icons, and openGraph.
Review feedback from #4196:
- `[slug]/[demo]/page.tsx` constructed `${backend_url}${demo.route}`
without a null check, so command-only demos (which have no `route`)
rendered an iframe pointing at `${backend_url}undefined`. Now builds
the src only when `demo.route` exists and renders a 'no live preview'
panel otherwise, mirroring the Get Started section on the profile
page. Also replaces the `any`-typed state with proper `Demo` and
`Integration` types imported from `@/lib/registry`.
- `[slug]/[demo]/preview/page.tsx` had the same bug — already typed
but TypeScript doesn't catch template-literal coercion of undefined.
Now bails with a command-focused message before concatenating.
- `profile-client.tsx` no longer duplicates `Demo`/`Integration`
interfaces — deleted the local copies and imports from
`@/lib/registry`. copyDemoCommand's catch now logs the failure so a
double-failure (no clipboard API + blocked prompt) is diagnosable.
Comment above the live-demos section updated from 'Demos' to
'Live Demos' to match the rendered heading.
The cli-start entry in each integration's demos[] is a copy-paste CLI
command, not a runnable demo, but the profile page rendered it as a
Live Demo tile whose drawer iframe loaded ${backend_url}undefined.
Split demos into liveDemos (runnable) and commandDemos (command-only)
and render commandDemos in a new "Get Started" section above the
Live Demos grid, mirroring how the dashboard already handles them.
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.
The oneLight SyntaxHighlighter theme sets a near-white background on
both <pre> and the inner <code>. customStyle overrides the <pre>, but
the <code> child keeps its own background — and since <code> renders
inline, that bg hugs each line of text and shows as a pale per-line
rectangle against the dark page chrome, making untouched code look
like it's text-selected. Unset the <code> background so the chosen
<pre> background reads as a flat block.
Same fix 4084 already landed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A framework-scoped URL asserting "unselected" in its path is
incoherent — you can't be both on langgraph-python AND in the
no-framework state. Collapse the redundant segment: if the framework
catch-all receives a slug that starts with unselected/, permanent-
redirect to the same path without that prefix (the framework-scoped
version serves the same content, just with Snippets resolved against
the selected framework's cells).
/docs/unselected/<path> remains a valid framework-agnostic URL.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Port the full docs routing + rendering infrastructure from the 4084
branch (atai/2026-04-17/internal-showcase-followups):
- New [framework]/[[...slug]] catch-all that validates the first
segment against the registry and renders framework-scoped docs
with a "not available for this framework" banner when the page's
defaultCell is not tagged in the framework's cells.
- FrameworkProvider + selector: framework is strictly URL-derived,
storedFramework is an advisory localStorage signal. No
auto-redirect from localStorage.
- /docs/[[...slug]] rewritten as a thin wrapper around DocsPageView
with a new DocsOverview landing: framework picker + topic cards.
- New lib/docs-render.tsx centralising snippet inlining,
frontmatter parsing, nav tree + breadcrumb builders.
- New lib/mdx-registry.tsx consolidating the ~700-line component
shim used by both routes.
- Server <Snippet> component with demo-content regions + syntax
highlighting via highlight.js.
- Per-feature <InlineDemo> iframe embedder pointing at the
integration's backend (single-container shape
http://localhost:3100/demos/<cell>).
- FrameworkTabs, docs-callout, docs-steps, docs-tabs, router-pivot,
stored-framework-highlight components for the MDX registry.
- Global typography + color pivot in globals.css: Plus Jakarta
Sans body, Spline Sans Mono code, cool-gray background, purple
accent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Shell /code viewer now builds a recursive file tree with core-only
(★ highlighted) and show-all-files toggle via ?view=all; collapses the
legacy flat files + backend_files arrays into one tree
- bundle-demo-content: strict mode — errors on missing highlight paths;
drop backend_files field; pull in external backend files referenced
by highlight: (column-relative paths) alongside demo-folder contents;
stable page-first ordering
- Update tests to reflect new column-relative filename shape
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a single command to spin up the exact image Railway deploys,
for any of the 17 showcase packages, with a single shared .env:
./showcase/scripts/dev-local.sh up [<slug> ...] # all if empty
./showcase/scripts/dev-local.sh down|build|logs|ps|ports
Pieces:
- `docker-compose.local.yml` with a service per package. Ports come
from `shared/local-ports.json` (langgraph-python -> 3100, ...).
- `.env.example` as a commit-safe template. Real `.env` is gitignored
and fed to every container via `env_file`, so keys (OPENAI_API_KEY,
etc.) live in one place.
- `dev-local.sh` wraps `docker compose` and handles the
`shared_python/` / `shared_typescript/` staging step that CI does
before `docker build` (see showcase_deploy.yml).
- Staged `shared_*` dirs added to .gitignore.
Shell wiring:
- `shell/next.config.ts` reads `shared/local-ports.json` when
`SHOWCASE_LOCAL=1` is set and injects it as a public env.
- `/integrations/[slug]/[demo]/preview` uses that map to iframe
`http://localhost:<port>` instead of `integration.backend_url`.
Per-slug; any slug not running locally falls back to Railway.
Unset SHOWCASE_LOCAL -> prod behavior, unchanged.
Full workflow + prerequisites (Colima / Docker Desktop) documented in
showcase/README.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces a new internal-facing showcase app (`showcase/shell-internal`)
that renders a feature × integration grid. Each cell links to one of two
new canonical standalone routes on the main `shell` app:
- `/integrations/[slug]/[demo]/preview` — iframe-only hosted demo
- `/integrations/[slug]/[demo]/code` — code viewer; supports `?file=<name>`
and `?lines=<start>-<end>` URL params for future line-highlighting
Keeping the canonical pages in `shell` means they can also be embedded in
docs/marketing; `shell-internal` is a pure overview with no duplicated
content (reads `shell/src/data/registry.json` directly).
Also drops `--turbopack` from `shell`'s dev script: Next.js 15.4.10's
turbopack panics on the repo's multi-lockfile layout. Webpack dev works
fine and this doesn't affect production builds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>