Skip to content

docs: migrate to Fumadocs (44 pages, 12 sections, ADR 0007)#277

Open
EmersonBraun wants to merge 7 commits intomainfrom
foundation/fumadocs-spike
Open

docs: migrate to Fumadocs (44 pages, 12 sections, ADR 0007)#277
EmersonBraun wants to merge 7 commits intomainfrom
foundation/fumadocs-spike

Conversation

@EmersonBraun
Copy link
Copy Markdown
Owner

@EmersonBraun EmersonBraun commented Apr 14, 2026

Summary

Full migration from Docusaurus to Fumadocs. The spike (initial commit) plus the migration commit ports every page from apps/docs to apps/docs-next and wires the root scripts.

Closes the spike portion of #238 — visual identity, i18n, recipes, and migration guides land in follow-up PRs as planned in Phase 0 (#211).

Decision recorded

docs/architecture/adrs/0007-docs-platform-fumadocs.md — formal ADR documenting why Fumadocs over Nextra/Starlight/VitePress/Mintlify, what we accept, what's deferred.

Note: ADR 0007 references ADRs 0001-0006 from PRs #267 #270 #271 #272 #273 #274 (currently unmerged). The README index here lists them with status notes; will reconcile on rebase after they land.

What's in this PR

Scaffold (initial spike commit)

  • Next.js 16 + Fumadocs UI 16.7 + Fumadocs MDX 14.2 + Tailwind v4
  • Home page + docs shell + catch-all renderer + search API
  • Mental-model concept page + 6 ADR-linked stubs

Migration commit (this push)

  • All 12 sections from apps/docs/docs/* ported as MDX with cleaned frontmatter
  • 44 source pages → 49 destination pages (some sections gained intros via index.mdx)
  • 56 total routes including home, search, all subpaths
  • 11 Docusaurus-only <Component /> placeholders in examples replaced with explanatory callouts
  • 20 frontmatter values quoted to fix YAML parsing for @/:/backtick characters
  • Root pnpm docs now points at Fumadocs dev server
  • Old Docusaurus site preserved as pnpm docs:legacy

Verified

  • pnpm install clean
  • pnpm docs:build → 56 static pages, 0 errors
  • Smoke test: every section's representative page returns 200
  • Search API returns highlighted hits

Try locally

pnpm install
pnpm docs
# open http://localhost:3000

Compare side-by-side with the legacy site:

pnpm docs:legacy
# open http://localhost:3000 (Docusaurus port)

What lands in follow-up PRs

Tracked in Phase 0 (#211):

Test plan

  • Build succeeds (56 routes generated)
  • All representative routes return 200
  • Search API works
  • Mental-model page renders ASCII diagram + concept tables
  • Examples render with placeholder callouts (no JSX errors)
  • All 12 ported sections appear in sidebar
  • Reviewer: clone + pnpm docs, click around
  • Reviewer: spot-check 5 pages for content fidelity vs Docusaurus
  • Reviewer: confirm ADR 0007 reasoning lands

Refs #238 #211

Validates Fumadocs as the replacement for Docusaurus (apps/docs).
Sits in parallel — the existing site keeps serving traffic until the
migration is approved.

Stack:
- Next.js 16.2 (app router, Turbopack)
- Fumadocs UI 16.7 + Fumadocs MDX 14.2 + Fumadocs Core 16.7
- Tailwind v4 + fumadocs-ui/css/preset.css (neutral theme)
- React 19, TypeScript 5.5+

Structure:
- app/(home)/         landing page (hero + 3-feature grid)
- app/docs/           docs shell with Fumadocs sidebar + search
- app/api/search/     built-in search API (createFromSource)
- content/docs/       MDX content
  - index             welcome + substrate table
  - getting-started/  quickstart + installation (ported from Docusaurus)
  - concepts/         mental-model (full) + 6 stub pages linking to ADRs
- lib/source.ts       loader bound to .source/server
- mdx-components.tsx  default Fumadocs MDX components

Verified:
- pnpm install succeeds
- pnpm exec next build generates 14 static pages, 0 errors
- All routes 200 in production server (/, /docs, all sub-pages)
- Search API returns highlighted hits

Decision criteria comparison documented in apps/docs-next/README.md.

Not yet wired into root pnpm dev/build — install + run manually until
the spike is approved. Next steps if approved:
1. Port remaining sections from apps/docs
2. Decide i18n strategy (Crowdin vs freeze vs LLM-translate)
3. Set up docs.agentskit.io on Vercel
4. Archive apps/docs

Refs #238 #211
Ports the entire Docusaurus content tree to apps/docs-next:

Sections ported (from apps/docs/docs):
- adapters/        (1 page)
- agents/          (4 pages: tools, skills, runtime, delegation)
- chat-uis/        (4 pages: react, ink, components, theming)
- components/      (1 page)
- contributing/    (1 page)
- data-layer/      (3 pages: adapters, memory, rag)
- examples/        (12 pages)
- getting-started/ (read-this-first, for-ai-agents — quickstart and installation already authored fresh in #277)
- hooks/           (3 pages: useChat, useStream, useReactive)
- infrastructure/  (4 pages: cli, eval, observability, sandbox)
- packages/        (3 pages)
- theming/         (1 page)

Total: 56 routes generated, build clean, all routes return 200.

Frontmatter handling:
- Stripped Docusaurus 'sidebar_position' (replaced by meta.json ordering)
- Auto-extracted title from first H1 when missing
- Auto-extracted description from first paragraph when missing
- Quoted 20 frontmatter values containing @ : ` characters (would
  otherwise break YAML parsing)

Examples cleanup:
- Replaced 11 Docusaurus-only inline JSX placeholders (<SupportBot />,
  <RAGChat />, etc.) with explanatory callouts. The interactive sandboxes
  will be reintroduced in a follow-up using AgentsKit's own components
  (dogfooding moment).

Wiring:
- pnpm docs        → now points to docs-next (Fumadocs dev)
- pnpm docs:legacy → preserves the Docusaurus site for transition
- pnpm docs:build  → Fumadocs production build

Decision recorded in:
- docs/architecture/adrs/0007-docs-platform-fumadocs.md

What lands in follow-ups (Phase 0 #211):
- Visual identity (logo, OG image, custom Tailwind tokens)
- docs.agentskit.io domain wiring (depends on #235)
- i18n strategy decision (Crowdin / LLM / freeze)
- Recipes section (#229)
- Migration guides — Vercel AI / LangChain (#241, #242)
- Embedded docs assistant (RAG over docs)
- TypeDoc API reference integration
- Archive apps/docs once parity confirmed and traffic moved

Refs #238 #211
@EmersonBraun EmersonBraun changed the title spike: Fumadocs documentation site (apps/docs-next) docs: migrate to Fumadocs (44 pages, 12 sections, ADR 0007) Apr 14, 2026
Closes #228. Writes complete Concepts pages for adapter, tool, skill,
memory, retriever, runtime — replacing the placeholder stubs from #277.

Each page follows the same structure:
- One-paragraph definition (what it is, what it isn't)
- Minimal interface (TypeScript code block)
- Built-in usage example
- When to write your own
- Common pitfalls table
- Link to the canonical ADR for full invariants

Content density:
- adapter:    83 lines  (~600 words)
- tool:      139 lines  (~900 words)
- skill:     145 lines  (~950 words)
- memory:    118 lines  (~800 words)
- retriever: 130 lines  (~850 words)
- runtime:   176 lines  (~1100 words)

Built and verified: 56 routes, all 200 in production server.

Aligned with the manifesto principle 'docs are product, not afterthought'
and the load-bearing distinctions:
- Tool (what model calls) vs Skill (what model becomes)
- ChatMemory vs VectorMemory (split, not unified)
- Empty results vs error (the asymmetry across contracts)

Refs #228 #211
@EmersonBraun
Copy link
Copy Markdown
Owner Author

Concepts section complete (closes #228)

Replaced all 6 stub concept pages with full content (~5,200 words total):

  • adapter — built-in usage, stream chunks, terminal-chunk guarantee, when to write your own
  • tool — definition, schema validation, confirmation gates, streaming execution, declaration-only (MCP)
  • skill — what the model becomes vs calls, references not inline, delegation, onActivate escape hatch
  • memory — split contracts (ChatMemory + VectorMemory + EmbedFn), built-in backends table, replace-all save
  • retriever — single narrow interface, web search as retriever, composing for hybrid/rerank, errors throw
  • runtime — the conductor, hard step cap, tool resolution order, memory atomicity, observers read-only, delegation as tool, categorized errors

Each page: one-paragraph definition → minimal interface → built-in example → when to write your own → pitfalls table → ADR link.

Build verified: 56 routes, all 200. Same PR — pushed to foundation/fumadocs-spike.

Closes #229. Adds a Recipes section with 10 self-contained, copy-paste
recipes plus an index page, all wired into the sidebar.

Recipes (each end-to-end and runnable as written):
- rag-chat                 — streaming React chat grounded in your docs
- pdf-qa                   — CLI Q&A over a local PDF
- code-reviewer            — agent that reads diff, runs tests, posts review
- discord-bot              — bot with per-channel memory and tools
- research-team            — planner + researcher + writer multi-agent
- cost-guarded-chat        — abort the run when budget exceeded (observer)
- persistent-memory        — chat that remembers across processes
- confirmation-gated-tool  — security-critical tool with onConfirm
- custom-adapter           — wrap any LLM API in 30 lines (incl. mock pattern)
- eval-suite               — vitest-based agent quality scoring in CI

Each page follows the same shape:
- One-paragraph framing
- 'Install' line
- Working code (with KEY placeholder)
- 'Run it' command
- 'What's happening' / 'Why this works' explainer
- 'Tighten the recipe' for next steps
- 'Related' links to Concepts + sibling recipes

Notable design choices:
- Index has a table of recipes with elapsed-time estimates (5-15 min)
- All recipes link back to Concepts pages and ADRs for deeper reading
- 'Cost-guarded chat' demonstrates that observers + AbortController are
  enough — no special primitive needed
- 'Custom adapter' includes the deterministic mock-adapter pattern
- 'Eval suite' includes both hard-coded scoring AND llm-as-judge

Build: 67 routes, all 200. Recipes appear in the sidebar between
Concepts and Adapters.

Refs #229 #211
@EmersonBraun
Copy link
Copy Markdown
Owner Author

Recipes section added (closes #229)

Adds 10 self-contained, copy-paste recipes plus an index, wired into the sidebar between Concepts and Adapters:

Recipe Time What
rag-chat 5 min Streaming React chat grounded in your docs
pdf-qa 8 min CLI Q&A over a local PDF
code-reviewer 10 min Agent reads diff, runs tests, reviews
discord-bot 12 min Bot with per-channel memory + tools
research-team 15 min Planner + researcher + writer multi-agent
cost-guarded-chat 5 min Abort run when budget exceeded
persistent-memory 5 min Remember across sessions
confirmation-gated-tool 5 min Dangerous tool with human approval
custom-adapter 10 min Wrap any LLM API + mock-adapter pattern
eval-suite 10 min vitest-based agent quality in CI

Build: 67 routes, all 200. ~1100 lines of new MDX, no JSX components needed (pure markdown + code blocks).

Each recipe ends with 'Tighten the recipe' (next-level moves) and 'Related' (links to Concepts + sibling recipes) — keeps readers cross-linking through the substrate.

Closes #241. New 'Migrating' section in the sidebar with an index and
the full Vercel AI SDK → AgentsKit migration guide.

Content:
- TL;DR table mapping Vercel AI SDK exports to AgentsKit equivalents
  (streamText, useChat, tool, generateText, experimental_StreamData,
  provider helpers, route handler patterns)
- Six side-by-side migration examples:
  1. Basic streaming chat (client hook)
  2. Securing the API key (server action + route handler variants)
  3. Tool calling (Zod → JSON Schema 7 conversion)
  4. Multi-provider swap
  5. Agent runtime with memory + retrieval (biggest win)
  6. Multi-agent / delegation
  7. Observability / telemetry
- 'Where Vercel AI SDK still wins' — honest callouts:
  generateObject (until Fase 2), consumer chat SDK footprint,
  Vercel-ecosystem investment, v1.0 maturity today
- Incremental migration path (keep existing, add AgentsKit for new
  features, consolidate via the Adapter contract)

Design notes:
- Before/after code blocks preserve the 'recognize my code' feeling;
  no tricks, no cherry-picking
- Callouts cross-link to ADRs so readers can verify claims
- Index page previews LangChain and Mastra guides (follow-ups #242)
- Sidebar order: Getting Started → Concepts → Recipes → Migrating → ...

Refs #241 #211
@EmersonBraun
Copy link
Copy Markdown
Owner Author

Migration guide: Vercel AI SDK → AgentsKit (closes #241)

New 'Migrating' section with the full Vercel AI SDK guide.

Content:

  • TL;DR equivalence table (streamText, useChat, tool, generateText, etc.)
  • 7 side-by-side migration examples (basic chat → route handler → tools → provider swap → agent runtime → multi-agent → observability)
  • 'Where Vercel AI SDK still wins' honest section (generateObject today, consumer chat SDK footprint, Vercel ecosystem lock-in, v1.0 maturity)
  • Incremental migration path pivoting on the Adapter contract

Build: 69 routes, all 200.

Next migration targets (follow-up PRs):

Closes #242. New page in the Migrating section mapping LangChain.js
patterns to AgentsKit equivalents.

Content:
- TL;DR equivalence table (ChatOpenAI, .invoke/.stream, ChatPromptTemplate,
  StructuredTool, AgentExecutor, BufferMemory, VectorStore, RetrievalQAChain,
  RunnableSequence, LangGraph, callbacks)
- 9 side-by-side migration examples:
  1. Basic chat with streaming
  2. Prompts and templates (no template engine in core — plain JS works)
  3. Tool calling (Zod → JSON Schema 7 bridge)
  4. AgentExecutor → Runtime (biggest win, hard maxSteps cap)
  5. Memory hierarchy → split ChatMemory/VectorMemory
  6. Retrieval / RetrievalQAChain → RAG as a Retriever
  7. Chains / LCEL → plain JavaScript composition
  8. LangGraph → delegation (with honest deferral of durable execution)
  9. Callbacks → Observers
- 'Where LangChain.js still wins' — honest callouts:
  integrations catalog, LangSmith ecosystem, LangGraph today,
  one-library-many-solutions preference, team familiarity
- Incremental migration path (keep LangChain for existing pipelines,
  adopt AgentsKit for new features, port chat layer first)
- Dependency size check (du -sh) showing the 100-200 MB delta

Rationale for the 'honest win' section: LangChain still has the broadest
integration catalog and LangSmith is genuinely useful. Pretending
otherwise loses credibility. The README's 'when NOT to use AgentsKit'
principle applied to this specific migration.

Refs #242 #211
@EmersonBraun
Copy link
Copy Markdown
Owner Author

Migration guide: LangChain.js → AgentsKit (closes #242)

Same structure as the Vercel AI SDK guide. 9 side-by-side examples covering the full surface: ChatOpenAI, prompt templates, tools, AgentExecutor, memory, retrieval, LCEL chains, LangGraph, callbacks.

Honest section 'Where LangChain.js still wins' covers:

  • Integration catalog breadth
  • LangSmith ecosystem (observers make this integration straightforward but LangSmith-native features stay)
  • LangGraph for explicit state-machine workflows (durable execution lands in Fase 3)
  • 'One library, many solutions' preference
  • Team familiarity cost

Includes a du -sh dependency-size check readers can run to see the typical 100–200 MB delta.

Build: 70 routes, all 200.

Closes #243. Adds lightweight, privacy-respecting PostHog integration to
the Fumadocs docs site.

Design:
- Opt-in via NEXT_PUBLIC_POSTHOG_KEY. Unset means PostHog never loads —
  localhost, CI, and any deployment without the env var are telemetry-free.
- AnalyticsProvider wraps the app; no-op when key is absent.
- Captures $pageview on every Next.js route change (automatic capture
  disabled, manual via usePathname + useSearchParams so SPA navigation
  is tracked correctly).
- Captures $pageleave for time-on-page.
- Enriches $pageview with a 'section' property inferred from the path
  (home, getting-started, concepts, recipes, migrating, etc.) for easy
  funnel analysis.
- No identify(), no PII, no session recordings.
- Respects Do-Not-Track (respect_dnt: true).
- EU/US host selectable via NEXT_PUBLIC_POSTHOG_HOST.

Exports:
- AnalyticsProvider (used in app/layout.tsx)
- track(event, properties) helper for custom events; no-op when disabled

Docs:
- apps/docs-next/ANALYTICS.md — full audit trail of what's tracked,
  what isn't, enable/disable instructions, privacy notes
- apps/docs-next/.env.example — the two relevant env vars

Verified:
- Build clean, 70 routes all static
- Without key set, HTML contains zero PostHog references (grep 0)
- Suspense boundary around the provider avoids Next 16's
  useSearchParams prerender bailout

Refs #243 #211
@EmersonBraun
Copy link
Copy Markdown
Owner Author

PostHog analytics added (closes #243)

Opt-in, privacy-respecting analytics for the docs site.

How it works

  • Unset NEXT_PUBLIC_POSTHOG_KEY → PostHog never loads (localhost, CI, unset deployments are telemetry-free)
  • Set it (Vercel env) → $pageview + $pageleave captured with a section property inferred from the URL
  • respect_dnt: true and person_profiles: 'identified_only' — no PII, no session recordings, no identify()

Files

  • apps/docs-next/lib/analytics.tsx — provider + track() helper
  • apps/docs-next/app/layout.tsx — wraps the app with Suspense + provider
  • apps/docs-next/ANALYTICS.md — audit trail of what's tracked, privacy posture, enable/disable
  • apps/docs-next/.env.example — the two env vars

Verified

  • Build clean, 70 routes still static
  • Without key set, HTML contains zero PostHog references

Next steps (once live)

  • Add PostHog key to Vercel env for docs.agentskit.io
  • First useful event to add: docs.copy_code_block (informs which recipes readers actually use)
  • Dashboard: 'where do new visitors land first?'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant