From 314d021beac09350b474cbd844f0e88e07baf9f4 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Apr 2026 21:57:41 -0700 Subject: [PATCH 1/8] docs: add multi-library docs architecture spec Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-04-06-multi-library-docs-design.md | 255 ++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-06-multi-library-docs-design.md diff --git a/docs/superpowers/specs/2026-04-06-multi-library-docs-design.md b/docs/superpowers/specs/2026-04-06-multi-library-docs-design.md new file mode 100644 index 000000000..93c14cbf0 --- /dev/null +++ b/docs/superpowers/specs/2026-04-06-multi-library-docs-design.md @@ -0,0 +1,255 @@ +# Multi-Library Documentation Architecture + +**Date:** 2026-04-06 +**Status:** Draft +**Approach:** Config-driven multi-library (Approach A) + +## Overview + +Expand the website docs to support all three libraries (agent, render, chat) with independent sections per library, a shared landing page at `/docs`, and a dropdown library selector in the sidebar. + +## Decisions + +| Decision | Choice | Rationale | +|----------|--------|-----------| +| Docs structure | Library-scoped | Each lib gets its own Getting Started, Guides, API, etc. | +| Landing page | Shared at `/docs` | Introduces ecosystem, links into each library | +| Sidebar switcher | Dropdown selector | Compact, scales well, familiar pattern (Stripe/Tailwind) | +| URL structure | `/docs/[library]/[section]/[slug]` | Library first matches mental model of "pick a lib, browse its docs" | +| Content directory | `content/docs//
/` | Filesystem mirrors URL structure | +| Content migration | Move `docs-v2/` to `docs/agent/` | Drop "v2" naming, establish clean structure | +| File renames | Drop "new"/"v2" suffixes | `docs-new.ts` -> `docs.ts`, `DocsSidebarNew` -> `DocsSidebar`, `MdxRendererNew` -> `MdxRenderer` | +| Placeholder content | Skeleton MDX for render & chat | Titles + one-paragraph descriptions; full authoring is a follow-up task | + +## Config & Types + +### docs-config.ts + +```ts +export type LibraryId = 'agent' | 'render' | 'chat'; + +export interface DocsLibrary { + id: LibraryId; + title: string; // "Agent", "Render", "Chat" + description: string; // One-liner for /docs landing page + sections: DocsSection[]; +} + +export interface DocsSection { + title: string; + id: string; + color: 'blue' | 'red'; + pages: DocsPage[]; +} + +export interface DocsPage { + title: string; + slug: string; + section: string; +} + +export const docsConfig: DocsLibrary[] = [ + { + id: 'agent', + title: 'Agent', + description: 'Streaming state management for LangGraph agents', + sections: [ + // Getting Started, Guides, Concepts, API Reference (existing pages) + ], + }, + { + id: 'render', + title: 'Render', + description: 'Declarative UI rendering from JSON specifications', + sections: [ + // Getting Started, Guides, API Reference + ], + }, + { + id: 'chat', + title: 'Chat', + description: 'Pre-built chat UI components for agent interfaces', + sections: [ + // Getting Started, Guides, Components, API Reference + ], + }, +]; +``` + +Helper functions gain a `library` parameter: + +- `getLibraryConfig(library: LibraryId): DocsLibrary | undefined` +- `findDocsPage(library: LibraryId, section: string, slug: string): DocsPage | undefined` +- `getPrevNextPages(library: LibraryId, section: string, slug: string): { prev, next }` +- `getAllDocSlugs(): { library, section, slug }[]` — iterates all libraries + +## Content Directory + +``` +content/docs/ +├── agent/ +│ ├── getting-started/ +│ │ ├── introduction.mdx +│ │ ├── quickstart.mdx +│ │ └── installation.mdx +│ ├── guides/ +│ │ ├── streaming.mdx +│ │ ├── persistence.mdx +│ │ ├── interrupts.mdx +│ │ ├── memory.mdx +│ │ ├── time-travel.mdx +│ │ ├── subgraphs.mdx +│ │ ├── testing.mdx +│ │ └── deployment.mdx +│ ├── concepts/ +│ │ ├── angular-signals.mdx +│ │ ├── langgraph-basics.mdx +│ │ ├── agent-architecture.mdx +│ │ └── state-management.mdx +│ └── api/ +│ ├── agent.mdx +│ ├── provide-agent.mdx +│ ├── fetch-stream-transport.mdx +│ ├── mock-stream-transport.mdx +│ └── api-docs.json +├── render/ +│ ├── getting-started/ +│ │ ├── introduction.mdx +│ │ ├── quickstart.mdx +│ │ └── installation.mdx +│ ├── guides/ +│ │ ├── registry.mdx +│ │ ├── state-store.mdx +│ │ ├── specs.mdx +│ │ └── events.mdx +│ └── api/ +│ ├── render-spec-component.mdx +│ ├── define-angular-registry.mdx +│ ├── signal-state-store.mdx +│ └── provide-render.mdx +└── chat/ + ├── getting-started/ + │ ├── introduction.mdx + │ ├── quickstart.mdx + │ └── installation.mdx + ├── guides/ + │ ├── theming.mdx + │ ├── markdown.mdx + │ ├── generative-ui.mdx + │ └── configuration.mdx + ├── components/ + │ ├── chat.mdx + │ ├── chat-messages.mdx + │ ├── chat-input.mdx + │ ├── chat-interrupt-panel.mdx + │ ├── chat-tool-call-card.mdx + │ ├── chat-subagent-card.mdx + │ └── chat-debug.mdx + └── api/ + ├── provide-chat.mdx + ├── chat-config.mdx + └── create-mock-stream-resource-ref.mdx +``` + +## Routing + +### Before + +``` +app/docs/[[...slug]]/page.tsx -> /docs/[section]/[slug] +``` + +### After + +``` +app/docs/page.tsx -> /docs (landing page) +app/docs/[library]/[section]/[slug]/page.tsx -> /docs/agent/guides/streaming +``` + +The dynamic route extracts `library`, `section`, and `slug` from params. The `library` param is validated against `docsConfig` library IDs. + +## Content Loader (docs.ts) + +Renamed from `docs-new.ts`. Changes: + +```ts +const resolveContentDir = (library: string): string => { + const workspacePath = path.join(process.cwd(), 'apps', 'website', 'content', 'docs', library); + if (fs.existsSync(workspacePath)) return workspacePath; + return path.join(process.cwd(), 'content', 'docs', library); +}; + +export function getDocBySlug(library: string, section: string, slug: string): ResolvedDoc | null { + // Validates against config, resolves from content/docs//
/.mdx +} + +export function getAllDocSlugs(): { library: string; section: string; slug: string }[] { + // Iterates all libraries from docsConfig +} +``` + +## Sidebar (DocsSidebar) + +Renamed from `DocsSidebarNew`. Changes: + +**New props:** +```ts +interface Props { + activeLibrary: LibraryId; + activeSection: string; + activeSlug: string; +} +``` + +**Dropdown selector:** Positioned below the search trigger, above section groups. Displays current library name. On click, shows a popover/dropdown with three options (Agent, Render, Chat). Selection navigates to that library's first page via `useRouter()`. + +**Section groups:** Rendered from `getLibraryConfig(activeLibrary).sections` instead of the flat `docsConfig` array. Same `SectionGroup` component, different data source. + +**Link paths:** Change from `/docs/${section}/${slug}` to `/docs/${activeLibrary}/${section}/${slug}`. + +## Mobile Nav (DocsMobileNav) + +Same dropdown treatment as sidebar — library selector above the section list in the drawer. Gains `activeLibrary` prop. + +## Docs Landing Page (/docs) + +Standalone React page (`app/docs/page.tsx`). No MDX. + +Content: +- Headline introducing Angular Stream Resource +- Three cards (one per library) with title, description, and "Get started" link +- Visual indication of library relationships (agent is core, render + chat build on it) +- Uses existing design tokens and glass styling + +## Prev/Next Navigation (DocsPrevNext) + +Scoped within a library — prev/next only links to pages in the same library. Uses `getPrevNextPages(library, section, slug)`. + +## Search (DocsSearch) + +Indexes across all libraries. Search results show a library badge/label so users know which library a result belongs to. + +## Top Nav Updates + +- "Docs" link: `/docs` (landing page) +- "API" link: `/docs/agent/api/agent` + +## File Renames + +| Before | After | +|--------|-------| +| `content/docs-v2/` | `content/docs/agent/` (move + rename) | +| `src/lib/docs-new.ts` | `src/lib/docs.ts` | +| `DocsSidebarNew` | `DocsSidebar` | +| `MdxRendererNew` | `MdxRenderer` | +| All imports referencing the above | Updated accordingly | + +## Content Authoring (Zero-Shot) + +All placeholder MDX pages for render and chat will be authored with real content in this same effort, derived from reading each library's source code. This includes Getting Started guides, concept guides, component docs, and API reference pages. + +## Out of Scope + +- API docs JSON generation for render and chat +- Versioned docs +- Cross-library search ranking/weighting From 34e784cf01468163b8565bb38bda93279d3ebd40 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Apr 2026 22:03:46 -0700 Subject: [PATCH 2/8] docs: add multi-library docs implementation plan Co-Authored-By: Claude Opus 4.6 (1M context) --- .../plans/2026-04-06-multi-library-docs.md | 1298 +++++++++++++++++ 1 file changed, 1298 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-06-multi-library-docs.md diff --git a/docs/superpowers/plans/2026-04-06-multi-library-docs.md b/docs/superpowers/plans/2026-04-06-multi-library-docs.md new file mode 100644 index 000000000..884d1cbe0 --- /dev/null +++ b/docs/superpowers/plans/2026-04-06-multi-library-docs.md @@ -0,0 +1,1298 @@ +# Multi-Library Documentation Architecture — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Expand the docs website to support agent, render, and chat libraries with independent sections, a shared landing page, dropdown library selector, and full zero-shot content for all three libraries. + +**Architecture:** Config-driven multi-library approach. Extend `docs-config.ts` with a `DocsLibrary` type keyed by library ID. Dynamic route changes from `[[...slug]]` to `[library]/[section]/[slug]`. Content moves from `content/docs-v2/` to `content/docs//`. Sidebar gains a dropdown library selector. + +**Tech Stack:** Next.js App Router, MDX (next-mdx-remote), TypeScript, Tailwind CSS, @cacheplane/design-tokens + +--- + +### Task 1: Move content directory and rename files + +**Files:** +- Move: `apps/website/content/docs-v2/*` → `apps/website/content/docs/agent/*` +- Rename: `apps/website/src/lib/docs-new.ts` → `apps/website/src/lib/docs.ts` +- Modify: all imports referencing `docs-new` + +- [ ] **Step 1: Move content directory** + +```bash +cd apps/website/content +mkdir -p docs/agent +cp -r docs-v2/* docs/agent/ +rm -rf docs-v2 +``` + +- [ ] **Step 2: Rename docs-new.ts to docs.ts** + +```bash +cd apps/website/src/lib +mv docs-new.ts docs.ts +``` + +- [ ] **Step 3: Update imports referencing docs-new** + +In `apps/website/src/app/docs/[[...slug]]/page.tsx`, change: +```ts +// Before +import { getDocBySlug, getAllDocSlugs } from '../../../lib/docs-new'; +// After +import { getDocBySlug, getAllDocSlugs } from '../../../../lib/docs'; +``` + +Note: This import path will change again in Task 3 when we restructure the route, but we fix it now so the build stays green. + +- [ ] **Step 4: Rename DocsSidebarNew to DocsSidebar** + +Rename `apps/website/src/components/docs/DocsSidebarNew.tsx` to `DocsSidebar.tsx`. Update the export name inside the file from `DocsSidebarNew` to `DocsSidebar`. Update the import in `apps/website/src/app/docs/[[...slug]]/page.tsx`. + +- [ ] **Step 5: Rename MdxRendererNew to MdxRenderer** + +In `apps/website/src/components/docs/MdxRenderer.tsx`, rename the exported function from `MdxRendererNew` to `MdxRenderer`. Update its interface from `NewProps` to `MdxRendererProps`. Update the import in `apps/website/src/app/docs/[[...slug]]/page.tsx`. + +- [ ] **Step 6: Update docs.ts content directory path** + +In `apps/website/src/lib/docs.ts`, update `resolveContentDir`: +```ts +const resolveContentDir = (): string => { + const workspacePath = path.join(process.cwd(), 'apps', 'website', 'content', 'docs'); + if (fs.existsSync(workspacePath)) return workspacePath; + return path.join(process.cwd(), 'content', 'docs'); +}; +``` + +Note: This still returns the `content/docs` directory (not library-scoped yet). Task 2 will add the library parameter. + +- [ ] **Step 7: Verify build passes** + +```bash +npx nx build website +``` + +Expected: Build succeeds with no errors. + +- [ ] **Step 8: Commit** + +```bash +git add -A +git commit -m "refactor: move docs-v2 to docs/agent, rename docs-new and component suffixes" +``` + +--- + +### Task 2: Refactor docs-config.ts with multi-library types + +**Files:** +- Modify: `apps/website/src/lib/docs-config.ts` +- Modify: `apps/website/src/lib/docs.ts` + +- [ ] **Step 1: Rewrite docs-config.ts** + +Replace the entire file with: + +```ts +export type LibraryId = 'agent' | 'render' | 'chat'; + +export interface DocsPage { + title: string; + slug: string; + section: string; +} + +export interface DocsSection { + title: string; + id: string; + color: 'blue' | 'red'; + pages: DocsPage[]; +} + +export interface DocsLibrary { + id: LibraryId; + title: string; + description: string; + sections: DocsSection[]; +} + +export const docsConfig: DocsLibrary[] = [ + { + id: 'agent', + title: 'Agent', + description: 'Streaming state management for LangGraph agents', + sections: [ + { + title: 'Getting Started', + id: 'getting-started', + color: 'blue', + pages: [ + { title: 'Introduction', slug: 'introduction', section: 'getting-started' }, + { title: 'Quick Start', slug: 'quickstart', section: 'getting-started' }, + { title: 'Installation', slug: 'installation', section: 'getting-started' }, + ], + }, + { + title: 'Guides', + id: 'guides', + color: 'blue', + pages: [ + { title: 'Streaming', slug: 'streaming', section: 'guides' }, + { title: 'Persistence', slug: 'persistence', section: 'guides' }, + { title: 'Interrupts', slug: 'interrupts', section: 'guides' }, + { title: 'Memory', slug: 'memory', section: 'guides' }, + { title: 'Time Travel', slug: 'time-travel', section: 'guides' }, + { title: 'Subgraphs', slug: 'subgraphs', section: 'guides' }, + { title: 'Testing', slug: 'testing', section: 'guides' }, + { title: 'Deployment', slug: 'deployment', section: 'guides' }, + ], + }, + { + title: 'Concepts', + id: 'concepts', + color: 'red', + pages: [ + { title: 'Angular Signals', slug: 'angular-signals', section: 'concepts' }, + { title: 'LangGraph Basics', slug: 'langgraph-basics', section: 'concepts' }, + { title: 'Agent Architecture', slug: 'agent-architecture', section: 'concepts' }, + { title: 'State Management', slug: 'state-management', section: 'concepts' }, + ], + }, + { + title: 'API Reference', + id: 'api', + color: 'blue', + pages: [ + { title: 'agent()', slug: 'agent', section: 'api' }, + { title: 'provideAgent()', slug: 'provide-agent', section: 'api' }, + { title: 'FetchStreamTransport', slug: 'fetch-stream-transport', section: 'api' }, + { title: 'MockAgentTransport', slug: 'mock-stream-transport', section: 'api' }, + ], + }, + ], + }, + { + id: 'render', + title: 'Render', + description: 'Declarative UI rendering from JSON specifications', + sections: [ + { + title: 'Getting Started', + id: 'getting-started', + color: 'blue', + pages: [ + { title: 'Introduction', slug: 'introduction', section: 'getting-started' }, + { title: 'Quick Start', slug: 'quickstart', section: 'getting-started' }, + { title: 'Installation', slug: 'installation', section: 'getting-started' }, + ], + }, + { + title: 'Guides', + id: 'guides', + color: 'blue', + pages: [ + { title: 'Component Registry', slug: 'registry', section: 'guides' }, + { title: 'State Store', slug: 'state-store', section: 'guides' }, + { title: 'Specs & Elements', slug: 'specs', section: 'guides' }, + { title: 'Events & Handlers', slug: 'events', section: 'guides' }, + ], + }, + { + title: 'API Reference', + id: 'api', + color: 'blue', + pages: [ + { title: 'RenderSpecComponent', slug: 'render-spec-component', section: 'api' }, + { title: 'defineAngularRegistry()', slug: 'define-angular-registry', section: 'api' }, + { title: 'signalStateStore()', slug: 'signal-state-store', section: 'api' }, + { title: 'provideRender()', slug: 'provide-render', section: 'api' }, + ], + }, + ], + }, + { + id: 'chat', + title: 'Chat', + description: 'Pre-built chat UI components for agent interfaces', + sections: [ + { + title: 'Getting Started', + id: 'getting-started', + color: 'blue', + pages: [ + { title: 'Introduction', slug: 'introduction', section: 'getting-started' }, + { title: 'Quick Start', slug: 'quickstart', section: 'getting-started' }, + { title: 'Installation', slug: 'installation', section: 'getting-started' }, + ], + }, + { + title: 'Guides', + id: 'guides', + color: 'blue', + pages: [ + { title: 'Theming', slug: 'theming', section: 'guides' }, + { title: 'Markdown Rendering', slug: 'markdown', section: 'guides' }, + { title: 'Generative UI', slug: 'generative-ui', section: 'guides' }, + { title: 'Configuration', slug: 'configuration', section: 'guides' }, + ], + }, + { + title: 'Components', + id: 'components', + color: 'red', + pages: [ + { title: 'ChatComponent', slug: 'chat', section: 'components' }, + { title: 'ChatMessages', slug: 'chat-messages', section: 'components' }, + { title: 'ChatInput', slug: 'chat-input', section: 'components' }, + { title: 'ChatInterruptPanel', slug: 'chat-interrupt-panel', section: 'components' }, + { title: 'ChatToolCallCard', slug: 'chat-tool-call-card', section: 'components' }, + { title: 'ChatSubagentCard', slug: 'chat-subagent-card', section: 'components' }, + { title: 'ChatDebug', slug: 'chat-debug', section: 'components' }, + ], + }, + { + title: 'API Reference', + id: 'api', + color: 'blue', + pages: [ + { title: 'provideChat()', slug: 'provide-chat', section: 'api' }, + { title: 'ChatConfig', slug: 'chat-config', section: 'api' }, + { title: 'createMockAgentRef()', slug: 'create-mock-agent-ref', section: 'api' }, + ], + }, + ], + }, +]; + +export function getLibraryConfig(libraryId: string): DocsLibrary | undefined { + return docsConfig.find((l) => l.id === libraryId); +} + +export function getLibraryPages(libraryId: string): DocsPage[] { + const lib = getLibraryConfig(libraryId); + if (!lib) return []; + return lib.sections.flatMap((s) => s.pages); +} + +export const allDocsPages: DocsPage[] = docsConfig.flatMap((l) => l.sections.flatMap((s) => s.pages)); + +export function findDocsPage(library: string, section: string, slug: string): DocsPage | undefined { + return getLibraryPages(library).find((p) => p.section === section && p.slug === slug); +} + +export function getPrevNextPages(library: string, section: string, slug: string): { prev: DocsPage | null; next: DocsPage | null } { + const pages = getLibraryPages(library); + const idx = pages.findIndex((p) => p.section === section && p.slug === slug); + return { + prev: idx > 0 ? pages[idx - 1] : null, + next: idx < pages.length - 1 ? pages[idx + 1] : null, + }; +} + +export function getDocsSection(library: string, sectionId: string): DocsSection | undefined { + const lib = getLibraryConfig(library); + return lib?.sections.find((s) => s.id === sectionId); +} +``` + +- [ ] **Step 2: Update docs.ts to accept library parameter** + +Replace `apps/website/src/lib/docs.ts` with: + +```ts +import fs from 'fs'; +import path from 'path'; +import { type DocsPage, getLibraryPages } from './docs-config'; + +const resolveContentDir = (library: string): string => { + const workspacePath = path.join(process.cwd(), 'apps', 'website', 'content', 'docs', library); + if (fs.existsSync(workspacePath)) return workspacePath; + return path.join(process.cwd(), 'content', 'docs', library); +}; + +export interface ResolvedDoc { + page: DocsPage; + content: string; + title: string; +} + +export function getDocBySlug(library: string, section: string, slug: string): ResolvedDoc | null { + const pages = getLibraryPages(library); + const page = pages.find((p) => p.section === section && p.slug === slug); + if (!page) return null; + + const dir = resolveContentDir(library); + const filePath = path.join(dir, section, `${slug}.mdx`); + if (!fs.existsSync(filePath)) return null; + + const content = fs.readFileSync(filePath, 'utf8'); + const titleMatch = content.match(/^#\s+(.+)$/m); + return { + page, + content, + title: titleMatch?.[1] ?? page.title, + }; +} + +export function getAllDocSlugs(): { library: string; section: string; slug: string }[] { + const { docsConfig } = require('./docs-config'); + return docsConfig.flatMap((lib: any) => + lib.sections.flatMap((s: any) => + s.pages.map((p: any) => ({ library: lib.id, section: p.section, slug: p.slug })) + ) + ); +} +``` + +Wait — avoid `require`. Use the proper import approach: + +```ts +import fs from 'fs'; +import path from 'path'; +import { docsConfig, type DocsPage, getLibraryPages } from './docs-config'; + +const resolveContentDir = (library: string): string => { + const workspacePath = path.join(process.cwd(), 'apps', 'website', 'content', 'docs', library); + if (fs.existsSync(workspacePath)) return workspacePath; + return path.join(process.cwd(), 'content', 'docs', library); +}; + +export interface ResolvedDoc { + page: DocsPage; + content: string; + title: string; +} + +export function getDocBySlug(library: string, section: string, slug: string): ResolvedDoc | null { + const pages = getLibraryPages(library); + const page = pages.find((p) => p.section === section && p.slug === slug); + if (!page) return null; + + const dir = resolveContentDir(library); + const filePath = path.join(dir, section, `${slug}.mdx`); + if (!fs.existsSync(filePath)) return null; + + const content = fs.readFileSync(filePath, 'utf8'); + const titleMatch = content.match(/^#\s+(.+)$/m); + return { + page, + content, + title: titleMatch?.[1] ?? page.title, + }; +} + +export function getAllDocSlugs(): { library: string; section: string; slug: string }[] { + return docsConfig.flatMap((lib) => + lib.sections.flatMap((s) => + s.pages.map((p) => ({ library: lib.id, section: p.section, slug: p.slug })) + ) + ); +} +``` + +- [ ] **Step 3: Commit** + +```bash +git add -A +git commit -m "feat: add multi-library types to docs-config, library-scoped docs.ts" +``` + +--- + +### Task 3: Restructure routing + +**Files:** +- Delete: `apps/website/src/app/docs/[[...slug]]/page.tsx` +- Create: `apps/website/src/app/docs/page.tsx` (landing page — placeholder for now) +- Create: `apps/website/src/app/docs/[library]/[section]/[slug]/page.tsx` + +- [ ] **Step 1: Delete old catch-all route** + +```bash +rm -rf apps/website/src/app/docs/\[\[...slug\]\] +``` + +- [ ] **Step 2: Create docs landing page placeholder** + +Create `apps/website/src/app/docs/page.tsx`: + +```tsx +import Link from 'next/link'; +import { docsConfig } from '../../lib/docs-config'; +import { tokens } from '@cacheplane/design-tokens'; + +export default function DocsLandingPage() { + return ( +
+
+

+ Documentation +

+

+ Angular Stream Resource is a suite of libraries for building AI agent interfaces. + Choose a library to get started. +

+ +
+ {docsConfig.map((lib) => ( + +

+ {lib.title} +

+

+ {lib.description} +

+
+ Get started → +
+ + ))} +
+
+
+ ); +} +``` + +- [ ] **Step 3: Create new dynamic route page** + +Create `apps/website/src/app/docs/[library]/[section]/[slug]/page.tsx`: + +```tsx +import { notFound } from 'next/navigation'; +import { DocsSidebar } from '../../../../../components/docs/DocsSidebar'; +import { MdxRenderer } from '../../../../../components/docs/MdxRenderer'; +import { DocsSearch } from '../../../../../components/docs/DocsSearch'; +import { getDocBySlug, getAllDocSlugs } from '../../../../../lib/docs'; +import { ApiDocRenderer, type ApiDocEntry } from '../../../../../components/docs/ApiDocRenderer'; +import { DocsTOC } from '../../../../../components/docs/DocsTOC'; +import { DocsMobileNav } from '../../../../../components/docs/DocsMobileNav'; +import { extractHeadings } from '../../../../../lib/extract-headings'; +import { getLibraryConfig, type LibraryId } from '../../../../../lib/docs-config'; +import fs from 'fs'; +import path from 'path'; + +function loadApiDocs(library: string): ApiDocEntry[] { + const candidates = [ + path.join(process.cwd(), 'apps', 'website', 'content', 'docs', library, 'api', 'api-docs.json'), + path.join(process.cwd(), 'content', 'docs', library, 'api', 'api-docs.json'), + ]; + for (const p of candidates) { + if (fs.existsSync(p)) return JSON.parse(fs.readFileSync(p, 'utf8')); + } + return []; +} + +const API_NAME_MAP: Record> = { + agent: { + 'agent': 'agent', + 'provide-agent': 'provideAgent', + 'fetch-stream-transport': 'FetchStreamTransport', + 'mock-stream-transport': 'MockAgentTransport', + }, +}; + +export function generateStaticParams() { + return getAllDocSlugs().map(({ library, section, slug }) => ({ library, section, slug })); +} + +export default async function DocsPage({ params }: { params: Promise<{ library: string; section: string; slug: string }> }) { + const { library, section, slug } = await params; + + const libConfig = getLibraryConfig(library); + if (!libConfig) notFound(); + + const doc = getDocBySlug(library, section, slug); + if (!doc) notFound(); + + return ( +
+ + +
+
+
+ +
+ + {section === 'api' && (() => { + const entries = loadApiDocs(library); + const nameMap = API_NAME_MAP[library] ?? {}; + const target = nameMap[slug]; + const apiEntry = target ? entries.find((e: ApiDocEntry) => e.name === target) : null; + return apiEntry ? ( +
+ +
+ ) : null; + })()} +
+ +
+
+ ); +} +``` + +- [ ] **Step 4: Commit** + +```bash +git add -A +git commit -m "feat: restructure routing to /docs/[library]/[section]/[slug]" +``` + +--- + +### Task 4: Update sidebar, mobile nav, breadcrumb, prev/next, and search components + +**Files:** +- Modify: `apps/website/src/components/docs/DocsSidebar.tsx` +- Modify: `apps/website/src/components/docs/DocsMobileNav.tsx` +- Modify: `apps/website/src/components/docs/DocsBreadcrumb.tsx` +- Modify: `apps/website/src/components/docs/DocsPrevNext.tsx` +- Modify: `apps/website/src/components/docs/DocsSearch.tsx` +- Modify: `apps/website/src/components/docs/MdxRenderer.tsx` + +- [ ] **Step 1: Rewrite DocsSidebar.tsx with dropdown selector** + +Replace `apps/website/src/components/docs/DocsSidebar.tsx` with: + +```tsx +'use client'; +import { useState, useRef, useEffect } from 'react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { docsConfig, getLibraryConfig, type DocsSection, type LibraryId } from '../../lib/docs-config'; +import { tokens } from '@cacheplane/design-tokens'; + +interface Props { + activeLibrary: LibraryId; + activeSection: string; + activeSlug: string; +} + +function LibraryDropdown({ activeLibrary }: { activeLibrary: LibraryId }) { + const [open, setOpen] = useState(false); + const ref = useRef(null); + const router = useRouter(); + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false); + }; + document.addEventListener('mousedown', handler); + return () => document.removeEventListener('mousedown', handler); + }, []); + + const currentLib = getLibraryConfig(activeLibrary); + + return ( +
+ + + {open && ( +
+ {docsConfig.map((lib) => ( + + ))} +
+ )} +
+ ); +} + +function SectionGroup({ section, activeLibrary, activeSection, activeSlug }: { section: DocsSection; activeLibrary: LibraryId; activeSection: string; activeSlug: string }) { + const [open, setOpen] = useState(true); + const headerColor = section.color === 'red' ? tokens.colors.angularRed : tokens.colors.accent; + + return ( +
+ + + {open && ( + + )} +
+ ); +} + +export function DocsSidebar({ activeLibrary, activeSection, activeSlug }: Props) { + const libConfig = getLibraryConfig(activeLibrary); + + return ( + + ); +} +``` + +- [ ] **Step 2: Update DocsMobileNav.tsx** + +Replace `apps/website/src/components/docs/DocsMobileNav.tsx` with: + +```tsx +'use client'; +import { useState } from 'react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { docsConfig, getLibraryConfig, type LibraryId } from '../../lib/docs-config'; +import { tokens } from '@cacheplane/design-tokens'; + +export function DocsMobileNav({ activeLibrary, activeSection, activeSlug }: { activeLibrary: LibraryId; activeSection: string; activeSlug: string }) { + const [open, setOpen] = useState(false); + const router = useRouter(); + const libConfig = getLibraryConfig(activeLibrary); + + return ( +
+ + + {open && ( + + )} +
+ ); +} +``` + +- [ ] **Step 3: Update DocsBreadcrumb.tsx** + +Replace `apps/website/src/components/docs/DocsBreadcrumb.tsx` with: + +```tsx +import Link from 'next/link'; +import { tokens } from '@cacheplane/design-tokens'; +import { getDocsSection, getLibraryConfig, type LibraryId } from '../../lib/docs-config'; + +export function DocsBreadcrumb({ library, section, title }: { library: LibraryId; section: string; title: string }) { + const libConfig = getLibraryConfig(library); + const sectionData = getDocsSection(library, section); + return ( +
+ Docs + + {libConfig?.title ?? library} + + {sectionData?.title ?? section} + + {title} +
+ ); +} +``` + +- [ ] **Step 4: Update DocsPrevNext.tsx** + +Replace `apps/website/src/components/docs/DocsPrevNext.tsx` with: + +```tsx +import Link from 'next/link'; +import { tokens } from '@cacheplane/design-tokens'; +import { getPrevNextPages, type LibraryId } from '../../lib/docs-config'; + +export function DocsPrevNext({ library, section, slug }: { library: LibraryId; section: string; slug: string }) { + const { prev, next } = getPrevNextPages(library, section, slug); + + return ( +
+ {prev ? ( + +
+
← Previous
+
{prev.title}
+
+ + ) :
} + {next ? ( + +
+
Next →
+
{next.title}
+
+ + ) :
} +
+ ); +} +``` + +- [ ] **Step 5: Update DocsSearch.tsx** + +Replace `apps/website/src/components/docs/DocsSearch.tsx` with: + +```tsx +'use client'; +import { useState, useEffect, useRef, useCallback } from 'react'; +import { useRouter } from 'next/navigation'; +import { docsConfig, type LibraryId } from '../../lib/docs-config'; +import { tokens } from '@cacheplane/design-tokens'; + +interface SearchablePage { + title: string; + slug: string; + section: string; + library: LibraryId; + libraryTitle: string; +} + +const allSearchablePages: SearchablePage[] = docsConfig.flatMap((lib) => + lib.sections.flatMap((s) => + s.pages.map((p) => ({ + ...p, + library: lib.id, + libraryTitle: lib.title, + })) + ) +); + +export function DocsSearch({ library }: { library?: LibraryId }) { + const [open, setOpen] = useState(false); + const [query, setQuery] = useState(''); + const [selected, setSelected] = useState(0); + const inputRef = useRef(null); + const router = useRouter(); + + const results = query.length > 0 + ? allSearchablePages.filter((p) => + p.title.toLowerCase().includes(query.toLowerCase()) || + p.slug.toLowerCase().includes(query.toLowerCase()) || + p.section.toLowerCase().includes(query.toLowerCase()) || + p.libraryTitle.toLowerCase().includes(query.toLowerCase()) + ).slice(0, 8) + : allSearchablePages.filter((p) => !library || p.library === library).slice(0, 6); + + const handleKeyDown = useCallback((e: KeyboardEvent) => { + if ((e.metaKey || e.ctrlKey) && e.key === 'k') { + e.preventDefault(); + setOpen((o) => !o); + } + if (e.key === 'Escape') setOpen(false); + }, []); + + useEffect(() => { + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + }, [handleKeyDown]); + + useEffect(() => { + if (open) { + setQuery(''); + setSelected(0); + setTimeout(() => inputRef.current?.focus(), 50); + } + }, [open]); + + const navigate = (page: SearchablePage) => { + router.push(`/docs/${page.library}/${page.section}/${page.slug}`); + setOpen(false); + }; + + const handleInputKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'ArrowDown') { e.preventDefault(); setSelected((s) => Math.min(s + 1, results.length - 1)); } + if (e.key === 'ArrowUp') { e.preventDefault(); setSelected((s) => Math.max(s - 1, 0)); } + if (e.key === 'Enter' && results[selected]) { navigate(results[selected]); } + }; + + if (!open) return null; + + return ( +
setOpen(false)}> +
e.stopPropagation()} + style={{ + width: '100%', maxWidth: 520, + background: 'rgba(255,255,255,0.95)', + backdropFilter: `blur(${tokens.glass.blur})`, + border: `1px solid ${tokens.glass.border}`, + borderRadius: 12, + boxShadow: '0 16px 64px rgba(0,0,0,0.15)', + overflow: 'hidden', + }}> +
+ { setQuery(e.target.value); setSelected(0); }} + onKeyDown={handleInputKeyDown} + placeholder="Search documentation..." + style={{ + width: '100%', border: 'none', outline: 'none', + fontFamily: 'var(--font-inter)', fontSize: '0.95rem', + color: tokens.colors.textPrimary, background: 'transparent', + }} + /> +
+
+ {results.map((page, i) => ( + + ))} + {results.length === 0 && ( +
+ No results found +
+ )} +
+
+
+ ); +} +``` + +- [ ] **Step 6: Update MdxRenderer.tsx** + +In `apps/website/src/components/docs/MdxRenderer.tsx`: + +- Add `library` to the props interface +- Pass `library` to `DocsBreadcrumb` and `DocsPrevNext` +- Rename the interface from `NewProps` to `MdxRendererProps` +- Rename the function from `MdxRendererNew` to `MdxRenderer` + +```tsx +import { MDXRemote } from 'next-mdx-remote/rsc'; +import { tokens } from '../../../lib/design-tokens'; +import { Callout } from './mdx/Callout'; +import { Steps, Step } from './mdx/Steps'; +import { Tabs, Tab } from './mdx/Tabs'; +import { Card, CardGroup } from './mdx/Card'; +import { CodeGroup } from './mdx/CodeGroup'; +import { Pre } from './mdx/CodeBlock'; +import { FeatureChips } from './mdx/FeatureChips'; +import { ArchFlowDiagram } from './ArchFlowDiagram'; +import { DocsBreadcrumb } from './DocsBreadcrumb'; +import { DocsPrevNext } from './DocsPrevNext'; +import { type LibraryId } from '../../lib/docs-config'; +import rehypePrettyCode from 'rehype-pretty-code'; +import rehypeSlug from 'rehype-slug'; + +const mdxComponents = { + Callout, + Steps, + Step, + Tabs, + Tab, + Card, + CardGroup, + CodeGroup, + ArchFlowDiagram, + FeatureChips, + pre: Pre, +}; + +const rehypeOptions = { + theme: 'tokyo-night', + keepBackground: true, +}; + +interface MdxRendererProps { + source: string; + library: LibraryId; + section: string; + slug: string; + title: string; +} + +export function MdxRenderer({ source, library, section, slug, title }: MdxRendererProps) { + return ( +
+ +
+ +
+ +
+ ); +} +``` + +- [ ] **Step 7: Update Nav.tsx API link** + +In `apps/website/src/components/shared/Nav.tsx`, update the API link: + +```ts +// Before +{ label: 'API', href: '/docs/api/agent', external: false }, +// After +{ label: 'API', href: '/docs/agent/api/agent', external: false }, +``` + +- [ ] **Step 8: Verify build passes** + +```bash +npx nx build website +``` + +Expected: Build succeeds. Only agent pages will render (render/chat content doesn't exist yet). + +- [ ] **Step 9: Commit** + +```bash +git add -A +git commit -m "feat: add library dropdown selector, update all docs components for multi-lib" +``` + +--- + +### Task 5: Author render library docs content + +**Files:** +- Create: `apps/website/content/docs/render/getting-started/introduction.mdx` +- Create: `apps/website/content/docs/render/getting-started/quickstart.mdx` +- Create: `apps/website/content/docs/render/getting-started/installation.mdx` +- Create: `apps/website/content/docs/render/guides/registry.mdx` +- Create: `apps/website/content/docs/render/guides/state-store.mdx` +- Create: `apps/website/content/docs/render/guides/specs.mdx` +- Create: `apps/website/content/docs/render/guides/events.mdx` +- Create: `apps/website/content/docs/render/api/render-spec-component.mdx` +- Create: `apps/website/content/docs/render/api/define-angular-registry.mdx` +- Create: `apps/website/content/docs/render/api/signal-state-store.mdx` +- Create: `apps/website/content/docs/render/api/provide-render.mdx` + +Write all render library MDX content. Each file should: +- Start with an H1 title +- Use existing MDX components (Callout, Steps, Tabs, CodeGroup) where appropriate +- Include real code examples derived from the library's actual API +- Reference the `@cacheplane/render` package and `@json-render/core` dependency + +**Key source context for content authoring:** + +The render library exports: `RenderSpecComponent` (selector: `render-spec`), `RenderElementComponent` (selector: `render-element`, internal), `defineAngularRegistry(componentMap)`, `signalStateStore(initialState)`, `provideRender(config)`, `RENDER_CONTEXT`, `REPEAT_SCOPE`, `RENDER_CONFIG`. + +Types: `AngularRegistry` (get/names methods), `AngularComponentRenderer` (Type), `AngularComponentInputs` (bindings, emit, loading, childKeys, spec), `RenderConfig` (registry, store, functions, handlers), `RenderContext`, `RepeatScope` (item, index, basePath). + +The spec format comes from `@json-render/core`: `Spec` has `root` (key), `elements` (record of UIElement), `state` (initial state model). `UIElement` has `type` (component name), `props`, `children`, `visible`, `repeat` (statePath), `on` (event handlers). + +Peer deps: `@angular/core ^20`, `@angular/common ^20`, `@json-render/core ^0.16.0`. + +- [ ] **Step 1: Create all render docs content files** + +Create each file with full MDX content. The subagent should read the render library source at `libs/render/src/` to write accurate docs with real code examples. + +- [ ] **Step 2: Commit** + +```bash +git add apps/website/content/docs/render/ +git commit -m "docs: author render library documentation" +``` + +--- + +### Task 6: Author chat library docs content + +**Files:** +- Create: `apps/website/content/docs/chat/getting-started/introduction.mdx` +- Create: `apps/website/content/docs/chat/getting-started/quickstart.mdx` +- Create: `apps/website/content/docs/chat/getting-started/installation.mdx` +- Create: `apps/website/content/docs/chat/guides/theming.mdx` +- Create: `apps/website/content/docs/chat/guides/markdown.mdx` +- Create: `apps/website/content/docs/chat/guides/generative-ui.mdx` +- Create: `apps/website/content/docs/chat/guides/configuration.mdx` +- Create: `apps/website/content/docs/chat/components/chat.mdx` +- Create: `apps/website/content/docs/chat/components/chat-messages.mdx` +- Create: `apps/website/content/docs/chat/components/chat-input.mdx` +- Create: `apps/website/content/docs/chat/components/chat-interrupt-panel.mdx` +- Create: `apps/website/content/docs/chat/components/chat-tool-call-card.mdx` +- Create: `apps/website/content/docs/chat/components/chat-subagent-card.mdx` +- Create: `apps/website/content/docs/chat/components/chat-debug.mdx` +- Create: `apps/website/content/docs/chat/api/provide-chat.mdx` +- Create: `apps/website/content/docs/chat/api/chat-config.mdx` +- Create: `apps/website/content/docs/chat/api/create-mock-agent-ref.mdx` + +Write all chat library MDX content. Each file should: +- Start with an H1 title +- Use existing MDX components (Callout, Steps, Tabs, CodeGroup) where appropriate +- Include real code examples derived from the library's actual API +- Reference the `@cacheplane/chat` package + +**Key source context for content authoring:** + +Chat has two tiers: **Primitives** (single-responsibility) and **Compositions** (feature-complete). + +Primitives: `ChatMessagesComponent` (selector: `chat-messages`, inputs: messages, ref, config), `MessageTemplateDirective`, `ChatInputComponent` (selector: `chat-input`), `ChatTypingIndicatorComponent`, `ChatErrorComponent`, `ChatInterruptComponent`, `ChatToolCallsComponent`, `ChatSubagentsComponent`, `ChatThreadListComponent`, `ChatTimelineComponent`, `ChatGenerativeUiComponent`. + +Compositions: `ChatComponent` (selector: `chat-root`, inputs: ref), `ChatInterruptPanelComponent`, `ChatToolCallCardComponent`, `ChatSubagentCardComponent`, `ChatTimelineSliderComponent`, `ChatDebugComponent`. + +Provider: `provideChat(config: ChatConfig)` with `CHAT_CONFIG` injection token. `ChatConfig` has: `renderRegistry?: AngularRegistry`, `avatarLabel?: string`, `assistantName?: string`. + +Testing: `createMockAgentRef()` returns a mock `AgentRef` (previously `StreamResourceRef`) with writable signals for all properties. + +Styles: `CHAT_THEME_STYLES` (CSS variables), `CHAT_MARKDOWN_STYLES`, `renderMarkdown(md)`. + +Deps: `@angular/core`, `@angular/common`, `@angular/forms`, `@cacheplane/agent`, `@cacheplane/render`, `@langchain/core`, `@langchain/langgraph-sdk`, `marked`. + +- [ ] **Step 1: Create all chat docs content files** + +Create each file with full MDX content. The subagent should read the chat library source at `libs/chat/src/` to write accurate docs with real code examples. + +- [ ] **Step 2: Commit** + +```bash +git add apps/website/content/docs/chat/ +git commit -m "docs: author chat library documentation" +``` + +--- + +### Task 7: Update any remaining references and final build verification + +**Files:** +- Modify: `apps/website/src/app/llms.txt/route.ts` (if it references old doc paths) +- Modify: `apps/website/src/app/llms-full.txt/route.ts` (if it references old doc paths) +- Check: any other files referencing `docs-v2`, `docs-new`, `DocsSidebarNew`, or `MdxRendererNew` + +- [ ] **Step 1: Search for stale references** + +```bash +grep -r "docs-v2\|docs-new\|DocsSidebarNew\|MdxRendererNew\|NewProps" apps/website/src/ --include="*.ts" --include="*.tsx" -l +``` + +Fix any remaining references found. + +- [ ] **Step 2: Search for old URL patterns in content** + +```bash +grep -r "href=\"/docs/[a-z]" apps/website/src/ --include="*.ts" --include="*.tsx" | grep -v "/docs/agent\|/docs/render\|/docs/chat\|/docs\"" +``` + +Fix any old `/docs/section/slug` links that should now be `/docs/library/section/slug`. + +- [ ] **Step 3: Full build verification** + +```bash +npx nx build website +``` + +Expected: Clean build with all pages generated for all three libraries. + +- [ ] **Step 4: Commit** + +```bash +git add -A +git commit -m "fix: clean up stale references to old docs structure" +``` From 7b6b7543184836ffd66525d6a539971cf6d6ffe9 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Apr 2026 22:05:16 -0700 Subject: [PATCH 3/8] refactor: move docs-v2 to docs/agent, rename docs-new and component suffixes Co-Authored-By: Claude Opus 4.6 (1M context) --- .../{docs-v2 => docs/agent}/api/agent.mdx | 0 .../{docs-v2 => docs/agent}/api/api-docs.json | 0 .../agent}/api/fetch-stream-transport.mdx | 0 .../agent}/api/mock-stream-transport.mdx | 0 .../agent}/api/provide-agent.mdx | 0 .../agent}/concepts/agent-architecture.mdx | 0 .../agent}/concepts/angular-signals.mdx | 0 .../agent}/concepts/langgraph-basics.mdx | 0 .../agent}/concepts/state-management.mdx | 0 .../agent}/getting-started/installation.mdx | 0 .../agent}/getting-started/introduction.mdx | 0 .../agent}/getting-started/quickstart.mdx | 0 .../agent}/guides/deployment.mdx | 0 .../agent}/guides/interrupts.mdx | 0 .../{docs-v2 => docs/agent}/guides/memory.mdx | 0 .../agent}/guides/persistence.mdx | 0 .../agent}/guides/streaming.mdx | 0 .../agent}/guides/subgraphs.mdx | 0 .../agent}/guides/testing.mdx | 0 .../agent}/guides/time-travel.mdx | 0 apps/website/scripts/generate-api-docs.ts | 4 +- .../website/src/app/docs/[[...slug]]/page.tsx | 14 +-- .../{DocsSidebarNew.tsx => DocsSidebar.tsx} | 2 +- .../src/components/docs/MdxRenderer.tsx | 4 +- apps/website/src/lib/docs-new.ts | 36 ------- apps/website/src/lib/docs.spec.ts | 2 +- apps/website/src/lib/docs.ts | 94 ++++--------------- 27 files changed, 29 insertions(+), 127 deletions(-) rename apps/website/content/{docs-v2 => docs/agent}/api/agent.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/api/api-docs.json (100%) rename apps/website/content/{docs-v2 => docs/agent}/api/fetch-stream-transport.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/api/mock-stream-transport.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/api/provide-agent.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/concepts/agent-architecture.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/concepts/angular-signals.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/concepts/langgraph-basics.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/concepts/state-management.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/getting-started/installation.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/getting-started/introduction.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/getting-started/quickstart.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/deployment.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/interrupts.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/memory.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/persistence.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/streaming.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/subgraphs.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/testing.mdx (100%) rename apps/website/content/{docs-v2 => docs/agent}/guides/time-travel.mdx (100%) rename apps/website/src/components/docs/{DocsSidebarNew.tsx => DocsSidebar.tsx} (98%) delete mode 100644 apps/website/src/lib/docs-new.ts diff --git a/apps/website/content/docs-v2/api/agent.mdx b/apps/website/content/docs/agent/api/agent.mdx similarity index 100% rename from apps/website/content/docs-v2/api/agent.mdx rename to apps/website/content/docs/agent/api/agent.mdx diff --git a/apps/website/content/docs-v2/api/api-docs.json b/apps/website/content/docs/agent/api/api-docs.json similarity index 100% rename from apps/website/content/docs-v2/api/api-docs.json rename to apps/website/content/docs/agent/api/api-docs.json diff --git a/apps/website/content/docs-v2/api/fetch-stream-transport.mdx b/apps/website/content/docs/agent/api/fetch-stream-transport.mdx similarity index 100% rename from apps/website/content/docs-v2/api/fetch-stream-transport.mdx rename to apps/website/content/docs/agent/api/fetch-stream-transport.mdx diff --git a/apps/website/content/docs-v2/api/mock-stream-transport.mdx b/apps/website/content/docs/agent/api/mock-stream-transport.mdx similarity index 100% rename from apps/website/content/docs-v2/api/mock-stream-transport.mdx rename to apps/website/content/docs/agent/api/mock-stream-transport.mdx diff --git a/apps/website/content/docs-v2/api/provide-agent.mdx b/apps/website/content/docs/agent/api/provide-agent.mdx similarity index 100% rename from apps/website/content/docs-v2/api/provide-agent.mdx rename to apps/website/content/docs/agent/api/provide-agent.mdx diff --git a/apps/website/content/docs-v2/concepts/agent-architecture.mdx b/apps/website/content/docs/agent/concepts/agent-architecture.mdx similarity index 100% rename from apps/website/content/docs-v2/concepts/agent-architecture.mdx rename to apps/website/content/docs/agent/concepts/agent-architecture.mdx diff --git a/apps/website/content/docs-v2/concepts/angular-signals.mdx b/apps/website/content/docs/agent/concepts/angular-signals.mdx similarity index 100% rename from apps/website/content/docs-v2/concepts/angular-signals.mdx rename to apps/website/content/docs/agent/concepts/angular-signals.mdx diff --git a/apps/website/content/docs-v2/concepts/langgraph-basics.mdx b/apps/website/content/docs/agent/concepts/langgraph-basics.mdx similarity index 100% rename from apps/website/content/docs-v2/concepts/langgraph-basics.mdx rename to apps/website/content/docs/agent/concepts/langgraph-basics.mdx diff --git a/apps/website/content/docs-v2/concepts/state-management.mdx b/apps/website/content/docs/agent/concepts/state-management.mdx similarity index 100% rename from apps/website/content/docs-v2/concepts/state-management.mdx rename to apps/website/content/docs/agent/concepts/state-management.mdx diff --git a/apps/website/content/docs-v2/getting-started/installation.mdx b/apps/website/content/docs/agent/getting-started/installation.mdx similarity index 100% rename from apps/website/content/docs-v2/getting-started/installation.mdx rename to apps/website/content/docs/agent/getting-started/installation.mdx diff --git a/apps/website/content/docs-v2/getting-started/introduction.mdx b/apps/website/content/docs/agent/getting-started/introduction.mdx similarity index 100% rename from apps/website/content/docs-v2/getting-started/introduction.mdx rename to apps/website/content/docs/agent/getting-started/introduction.mdx diff --git a/apps/website/content/docs-v2/getting-started/quickstart.mdx b/apps/website/content/docs/agent/getting-started/quickstart.mdx similarity index 100% rename from apps/website/content/docs-v2/getting-started/quickstart.mdx rename to apps/website/content/docs/agent/getting-started/quickstart.mdx diff --git a/apps/website/content/docs-v2/guides/deployment.mdx b/apps/website/content/docs/agent/guides/deployment.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/deployment.mdx rename to apps/website/content/docs/agent/guides/deployment.mdx diff --git a/apps/website/content/docs-v2/guides/interrupts.mdx b/apps/website/content/docs/agent/guides/interrupts.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/interrupts.mdx rename to apps/website/content/docs/agent/guides/interrupts.mdx diff --git a/apps/website/content/docs-v2/guides/memory.mdx b/apps/website/content/docs/agent/guides/memory.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/memory.mdx rename to apps/website/content/docs/agent/guides/memory.mdx diff --git a/apps/website/content/docs-v2/guides/persistence.mdx b/apps/website/content/docs/agent/guides/persistence.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/persistence.mdx rename to apps/website/content/docs/agent/guides/persistence.mdx diff --git a/apps/website/content/docs-v2/guides/streaming.mdx b/apps/website/content/docs/agent/guides/streaming.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/streaming.mdx rename to apps/website/content/docs/agent/guides/streaming.mdx diff --git a/apps/website/content/docs-v2/guides/subgraphs.mdx b/apps/website/content/docs/agent/guides/subgraphs.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/subgraphs.mdx rename to apps/website/content/docs/agent/guides/subgraphs.mdx diff --git a/apps/website/content/docs-v2/guides/testing.mdx b/apps/website/content/docs/agent/guides/testing.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/testing.mdx rename to apps/website/content/docs/agent/guides/testing.mdx diff --git a/apps/website/content/docs-v2/guides/time-travel.mdx b/apps/website/content/docs/agent/guides/time-travel.mdx similarity index 100% rename from apps/website/content/docs-v2/guides/time-travel.mdx rename to apps/website/content/docs/agent/guides/time-travel.mdx diff --git a/apps/website/scripts/generate-api-docs.ts b/apps/website/scripts/generate-api-docs.ts index bc35ece81..81f3dfa7e 100644 --- a/apps/website/scripts/generate-api-docs.ts +++ b/apps/website/scripts/generate-api-docs.ts @@ -126,7 +126,7 @@ async function main() { const entryPoint = candidates.find((p) => fs.existsSync(p)); if (!entryPoint) { console.warn('Library entry point not found — generating empty api-docs.json'); - const outDir = 'apps/website/content/docs-v2/api'; + const outDir = 'apps/website/content/docs/agent/api'; fs.mkdirSync(outDir, { recursive: true }); fs.writeFileSync(path.join(outDir, 'api-docs.json'), JSON.stringify([], null, 2)); return; @@ -152,7 +152,7 @@ async function main() { if (entry) entries.push(entry); } - const outDir = 'apps/website/content/docs-v2/api'; + const outDir = 'apps/website/content/docs/agent/api'; fs.mkdirSync(outDir, { recursive: true }); fs.writeFileSync(path.join(outDir, 'api-docs.json'), JSON.stringify(entries, null, 2)); console.log(`✓ api-docs.json written (${entries.length} entries)`); diff --git a/apps/website/src/app/docs/[[...slug]]/page.tsx b/apps/website/src/app/docs/[[...slug]]/page.tsx index 9c411fae2..a381476f3 100644 --- a/apps/website/src/app/docs/[[...slug]]/page.tsx +++ b/apps/website/src/app/docs/[[...slug]]/page.tsx @@ -1,8 +1,8 @@ import { notFound } from 'next/navigation'; -import { DocsSidebarNew } from '../../../components/docs/DocsSidebarNew'; -import { MdxRendererNew } from '../../../components/docs/MdxRenderer'; +import { DocsSidebar } from '../../../components/docs/DocsSidebar'; +import { MdxRenderer } from '../../../components/docs/MdxRenderer'; import { DocsSearch } from '../../../components/docs/DocsSearch'; -import { getDocBySlug, getAllDocSlugs } from '../../../lib/docs-new'; +import { getDocBySlug, getAllDocSlugs } from '../../../lib/docs'; import { ApiDocRenderer, type ApiDocEntry } from '../../../components/docs/ApiDocRenderer'; import { DocsTOC } from '../../../components/docs/DocsTOC'; import { DocsMobileNav } from '../../../components/docs/DocsMobileNav'; @@ -12,8 +12,8 @@ import path from 'path'; function loadApiDocs(): ApiDocEntry[] { const candidates = [ - path.join(process.cwd(), 'apps', 'website', 'content', 'docs-v2', 'api', 'api-docs.json'), - path.join(process.cwd(), 'content', 'docs-v2', 'api', 'api-docs.json'), + path.join(process.cwd(), 'apps', 'website', 'content', 'docs/agent', 'api', 'api-docs.json'), + path.join(process.cwd(), 'content', 'docs/agent', 'api', 'api-docs.json'), ]; for (const p of candidates) { if (fs.existsSync(p)) return JSON.parse(fs.readFileSync(p, 'utf8')); @@ -46,13 +46,13 @@ export default async function DocsPage({ params }: { params: Promise<{ slug?: st return (
- +
- + {section === 'api' && (() => { const entries = loadApiDocs(); const target = API_NAME_MAP[slug]; diff --git a/apps/website/src/components/docs/DocsSidebarNew.tsx b/apps/website/src/components/docs/DocsSidebar.tsx similarity index 98% rename from apps/website/src/components/docs/DocsSidebarNew.tsx rename to apps/website/src/components/docs/DocsSidebar.tsx index fc4471e42..21a0d342b 100644 --- a/apps/website/src/components/docs/DocsSidebarNew.tsx +++ b/apps/website/src/components/docs/DocsSidebar.tsx @@ -51,7 +51,7 @@ function SectionGroup({ section, activeSection, activeSlug }: { section: DocsSec ); } -export function DocsSidebarNew({ activeSection, activeSlug }: Props) { +export function DocsSidebar({ activeSection, activeSlug }: Props) { return (