doccupine 0.0.63 → 0.0.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +4 -3
  2. package/dist/lib/structures.js +2 -0
  3. package/dist/templates/app/theme.d.ts +3 -1
  4. package/dist/templates/app/theme.js +17 -15
  5. package/dist/templates/components/Chat.d.ts +1 -1
  6. package/dist/templates/components/Chat.js +251 -158
  7. package/dist/templates/components/DocsSideBar.d.ts +1 -1
  8. package/dist/templates/components/DocsSideBar.js +34 -11
  9. package/dist/templates/components/SideBar.d.ts +1 -1
  10. package/dist/templates/components/SideBar.js +12 -2
  11. package/dist/templates/components/layout/Accordion.d.ts +1 -1
  12. package/dist/templates/components/layout/Accordion.js +1 -1
  13. package/dist/templates/components/layout/ActionBar.d.ts +1 -1
  14. package/dist/templates/components/layout/ActionBar.js +15 -60
  15. package/dist/templates/components/layout/Callout.d.ts +1 -1
  16. package/dist/templates/components/layout/Callout.js +1 -1
  17. package/dist/templates/components/layout/Card.d.ts +1 -1
  18. package/dist/templates/components/layout/Card.js +26 -7
  19. package/dist/templates/components/layout/Columns.d.ts +1 -1
  20. package/dist/templates/components/layout/Columns.js +1 -1
  21. package/dist/templates/components/layout/DocsComponents.d.ts +1 -1
  22. package/dist/templates/components/layout/DocsComponents.js +37 -11
  23. package/dist/templates/components/layout/DocsNavigation.d.ts +1 -1
  24. package/dist/templates/components/layout/DocsNavigation.js +3 -2
  25. package/dist/templates/components/layout/Field.d.ts +1 -1
  26. package/dist/templates/components/layout/Field.js +1 -1
  27. package/dist/templates/components/layout/Footer.d.ts +1 -1
  28. package/dist/templates/components/layout/Footer.js +28 -6
  29. package/dist/templates/components/layout/Header.d.ts +1 -1
  30. package/dist/templates/components/layout/Header.js +10 -12
  31. package/dist/templates/components/layout/SharedStyles.d.ts +1 -1
  32. package/dist/templates/components/layout/SharedStyles.js +26 -2
  33. package/dist/templates/components/layout/StaticLinks.d.ts +1 -1
  34. package/dist/templates/components/layout/StaticLinks.js +7 -3
  35. package/dist/templates/components/layout/Steps.d.ts +1 -1
  36. package/dist/templates/components/layout/Steps.js +7 -2
  37. package/dist/templates/components/layout/Tabs.d.ts +1 -1
  38. package/dist/templates/components/layout/Tabs.js +2 -2
  39. package/dist/templates/components/layout/Update.d.ts +1 -1
  40. package/dist/templates/components/layout/Update.js +1 -1
  41. package/dist/templates/mdx/ai-assistant.mdx.d.ts +1 -1
  42. package/dist/templates/mdx/ai-assistant.mdx.js +8 -0
  43. package/dist/templates/mdx/callouts.mdx.d.ts +1 -1
  44. package/dist/templates/mdx/callouts.mdx.js +6 -2
  45. package/dist/templates/mdx/cards.mdx.d.ts +1 -1
  46. package/dist/templates/mdx/cards.mdx.js +19 -3
  47. package/dist/templates/mdx/columns.mdx.d.ts +1 -1
  48. package/dist/templates/mdx/columns.mdx.js +2 -2
  49. package/dist/templates/mdx/commands.mdx.d.ts +1 -1
  50. package/dist/templates/mdx/commands.mdx.js +10 -2
  51. package/dist/templates/mdx/components.mdx.d.ts +1 -0
  52. package/dist/templates/mdx/components.mdx.js +56 -0
  53. package/dist/templates/mdx/deployment.mdx.d.ts +1 -1
  54. package/dist/templates/mdx/deployment.mdx.js +1 -1
  55. package/dist/templates/mdx/globals.mdx.d.ts +1 -1
  56. package/dist/templates/mdx/globals.mdx.js +5 -0
  57. package/dist/templates/mdx/index.mdx.d.ts +1 -1
  58. package/dist/templates/mdx/index.mdx.js +5 -5
  59. package/dist/templates/mdx/model-context-protocol.mdx.d.ts +1 -1
  60. package/dist/templates/mdx/model-context-protocol.mdx.js +2 -2
  61. package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
  62. package/dist/templates/mdx/navigation.mdx.js +1 -1
  63. package/dist/templates/mdx/platform/external-links.mdx.d.ts +1 -1
  64. package/dist/templates/mdx/platform/external-links.mdx.js +2 -0
  65. package/dist/templates/mdx/platform/fonts-settings.mdx.d.ts +1 -1
  66. package/dist/templates/mdx/platform/fonts-settings.mdx.js +8 -5
  67. package/dist/templates/mdx/platform/index.mdx.d.ts +1 -1
  68. package/dist/templates/mdx/platform/index.mdx.js +10 -1
  69. package/dist/templates/mdx/platform/site-settings.mdx.d.ts +1 -1
  70. package/dist/templates/mdx/platform/site-settings.mdx.js +4 -4
  71. package/dist/templates/mdx/sections.mdx.d.ts +1 -1
  72. package/dist/templates/mdx/sections.mdx.js +2 -2
  73. package/dist/templates/mdx/steps.mdx.d.ts +1 -1
  74. package/dist/templates/mdx/steps.mdx.js +4 -0
  75. package/dist/templates/mdx/tabs.mdx.d.ts +1 -1
  76. package/dist/templates/mdx/tabs.mdx.js +1 -1
  77. package/dist/templates/package.js +4 -4
  78. package/dist/templates/services/llm/types.d.ts +1 -1
  79. package/dist/templates/services/llm/types.js +1 -1
  80. package/dist/templates/services/mcp/server.d.ts +1 -1
  81. package/dist/templates/services/mcp/server.js +1 -1
  82. package/dist/templates/services/mcp/tools.d.ts +1 -1
  83. package/dist/templates/services/mcp/tools.js +1 -5
  84. package/dist/templates/utils/config.d.ts +1 -1
  85. package/dist/templates/utils/config.js +1 -1
  86. package/package.json +1 -1
@@ -1 +1 @@
1
- export declare const deploymentMdxTemplate = "---\ntitle: \"Deployment\"\ndescription: \"Deploy your documentation site with the Doccupine Platform or self-host on any platform that supports Next.js.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 10\n---\n# Deployment\nThe fastest way to deploy your documentation is with the [Doccupine Platform](https://www.doccupine.com). If you prefer to manage your own infrastructure, you can self-host the generated Next.js app on any platform.\n\n## Doccupine Platform\n\nSign up at [doccupine.com](https://www.doccupine.com) and connect your repository. Your documentation site is live in minutes - no build configuration, no infrastructure to manage.\n\n<Callout type=\"success\">\n The Doccupine Platform is the recommended way to deploy. It handles builds, hosting, SSL, and updates automatically so you can focus on writing documentation.\n</Callout>\n\n### What you get\n- **Automatic deployments** on every push to your repository\n- **Site customization** through a visual dashboard - no code changes needed\n- **Team collaboration** so your whole team can manage docs together\n- **Custom domains** with automatic SSL\n- **AI Assistant and MCP server** included out of the box, no API key required\n- **Zero maintenance** - no servers, no build pipelines, no dependency updates\n\n### Getting started\n1. Create an account at [doccupine.com](https://www.doccupine.com).\n2. Connect your GitHub repository.\n3. Your site is deployed automatically.\n\nEvery push to your repository triggers a new deployment. You can customize your site's appearance, domain, and settings from the dashboard.\n\n---\n\n## Self-hosting\n\nDoccupine generates a standard Next.js app, so you can deploy it anywhere that supports Node.js or Next.js.\n\n<Callout type=\"warning\">\n Deploy the generated website directory (the Next.js app), not your MDX source folder. In a monorepo, set the root directory to the generated site folder.\n</Callout>\n\n<Callout type=\"note\">\n Self-hosting requires you to manage your own build pipeline, hosting, SSL certificates, and AI provider API keys. For a hands-off experience, consider the [Doccupine Platform](https://www.doccupine.com).\n</Callout>\n\n### Popular hosting options\n\n- **Vercel** - native Next.js support, zero-config deploys. Connect your repo and set the root directory to the generated app folder.\n- **Netlify** - supports Next.js via the `@netlify/plugin-nextjs` adapter. Works with the standard `next build` output.\n- **AWS Amplify** - fully managed hosting with CI/CD. Supports Next.js SSR out of the box.\n- **Cloudflare Pages** - deploy using the `@cloudflare/next-on-pages` adapter for edge-based hosting.\n- **Docker** - build a container from the generated app using the standard [Next.js Docker example](https://github.com/vercel/next.js/tree/canary/examples/with-docker) and deploy to any container platform.\n- **Node.js server** - run `next build && next start` on any server or VPS with Node.js installed.\n\n### Troubleshooting\n- **Build failed** - check build logs. Ensure your lockfile and correct Node.js version are present.\n- **Missing content** - verify your MDX files and assets are in the repository.\n- **SSR issues on edge platforms** - some features (like the AI chat API routes) require a Node.js runtime. Check your platform's documentation for SSR/API route support.";
1
+ export declare const deploymentMdxTemplate = "---\ntitle: \"Deployment\"\ndescription: \"Deploy your documentation site with the Doccupine Platform or self-host on any platform that supports Next.js.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 10\n---\n# Deployment\nThe fastest way to deploy your documentation is with the [Doccupine Platform](https://www.doccupine.com). If you prefer to manage your own infrastructure, you can self-host the generated Next.js app on any platform.\n\n## Doccupine Platform\n\nSign up at [doccupine.com](https://www.doccupine.com) and connect your repository. Your documentation site is live in minutes - no build configuration, no infrastructure to manage.\n\n<Callout type=\"success\">\n The Doccupine Platform is the recommended way to deploy. It handles builds, hosting, SSL, and updates automatically so you can focus on writing documentation.\n</Callout>\n\n### What you get\n- **Automatic deployments** on every push to your repository\n- **Site customization** through a visual dashboard - no code changes needed\n- **Team collaboration** so your whole team can manage docs together\n- **Custom domains** with automatic SSL\n- **AI Assistant and MCP server** included out of the box, no API key required\n- **Zero maintenance** - no servers, no build pipelines, no dependency updates\n\n### Getting started\n1. Create an account at [doccupine.com](https://www.doccupine.com).\n2. Connect your GitHub repository.\n3. Your site is deployed automatically.\n\nEvery push to your repository triggers a new deployment. You can customize your site's appearance, domain, and settings from the dashboard. See the [Platform Overview](/platform) for a full walkthrough of the dashboard, editor, and configuration options.\n\n---\n\n## Self-hosting\n\nDoccupine generates a standard Next.js app, so you can deploy it anywhere that supports Node.js or Next.js.\n\n<Callout type=\"warning\">\n Deploy the generated website directory (the Next.js app), not your MDX source folder. In a monorepo, set the root directory to the generated site folder.\n</Callout>\n\n<Callout type=\"note\">\n Self-hosting requires you to manage your own build pipeline, hosting, SSL certificates, and AI provider API keys. For a hands-off experience, consider the [Doccupine Platform](https://www.doccupine.com).\n</Callout>\n\n### Popular hosting options\n\n- **Vercel** - native Next.js support, zero-config deploys. Connect your repo and set the root directory to the generated app folder.\n- **Netlify** - supports Next.js via the `@netlify/plugin-nextjs` adapter. Works with the standard `next build` output.\n- **AWS Amplify** - fully managed hosting with CI/CD. Supports Next.js SSR out of the box.\n- **Cloudflare Pages** - deploy using the `@cloudflare/next-on-pages` adapter for edge-based hosting.\n- **Docker** - build a container from the generated app using the standard [Next.js Docker example](https://github.com/vercel/next.js/tree/canary/examples/with-docker) and deploy to any container platform.\n- **Node.js server** - run `next build && next start` on any server or VPS with Node.js installed.\n\n### Troubleshooting\n- **Build failed** - check build logs. Ensure your lockfile and correct Node.js version are present.\n- **Missing content** - verify your MDX files and assets are in the repository.\n- **SSR issues on edge platforms** - some features (like the AI chat API routes) require a Node.js runtime. Check your platform's documentation for SSR/API route support.";
@@ -30,7 +30,7 @@ Sign up at [doccupine.com](https://www.doccupine.com) and connect your repositor
30
30
  2. Connect your GitHub repository.
31
31
  3. Your site is deployed automatically.
32
32
 
33
- Every push to your repository triggers a new deployment. You can customize your site's appearance, domain, and settings from the dashboard.
33
+ Every push to your repository triggers a new deployment. You can customize your site's appearance, domain, and settings from the dashboard. See the [Platform Overview](/platform) for a full walkthrough of the dashboard, editor, and configuration options.
34
34
 
35
35
  ---
36
36
 
@@ -1 +1 @@
1
- export declare const globalsMdxTemplate = "---\ntitle: \"Globals\"\ndescription: \"Configure global settings for your documentation.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 1\n---\n# Global Configuration\nUse a `config.json` file to define project\u2011wide metadata for your documentation site. These values are applied to every generated page unless a page overrides them in its own frontmatter.\n\n## config.json\nPlace a `config.json` at your project root (the same folder where you execute `npx doccupine`) to define global metadata for your documentation site.\n\n```json\n{\n \"name\": \"Doccupine\",\n \"description\": \"Doccupine is a free and open-source documentation platform. Write MDX, get a production-ready site with AI chat, built-in components, and an MCP server - in one command.\",\n \"icon\": \"https://docs.doccupine.com/favicon.ico\",\n \"image\": \"https://docs.doccupine.com/preview.png\"\n}\n```\n\n## Fields\n- **name**: The primary name of your documentation website. Displayed in the site title and used in various UI elements.\n- **description**: A concise summary of your project, used in site metadata (e.g., HTML meta description) and social previews when not overridden.\n- **icon**: The favicon for your site. You can provide a full URL or a relative path to an asset in your project.\n- **image**: The Open Graph image used when links to your docs are shared on social platforms. Accepts a full URL or a relative path.\n\n## Per-page overrides\nAny page can override global values by defining the matching key in its frontmatter. When present, the page's value takes precedence over `config.json` for that page only.\n\n| Frontmatter field | Overrides | Effect |\n|---|---|---|\n| **title** | - | Page title in metadata and Open Graph |\n| **description** | `description` | Meta description and Open Graph description |\n| **name** | `name` | Site name shown in the title suffix (e.g. \"Page - My Docs\") |\n| **icon** | `icon` | Favicon for this page |\n| **image** | `image` | Open Graph preview image |\n\n<Callout type=\"note\">\n If a key is not specified in a page's frontmatter, Doccupine falls back to the corresponding value in `config.json`.\n</Callout>\n\nExample frontmatter in an `.mdx` file:\n\n```text\n---\ntitle: \"My Feature\"\ndescription: \"A focused description just for this page.\"\nname: \"My Product Docs\"\nicon: \"/custom-favicon.ico\"\nimage: \"/custom-preview.png\"\ndate: \"2026-02-19\"\ncategory: \"Guides\"\n---\n```\n\n";
1
+ export declare const globalsMdxTemplate = "---\ntitle: \"Globals\"\ndescription: \"Configure global settings for your documentation.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 1\n---\n# Global Configuration\nUse a `config.json` file to define project\u2011wide metadata for your documentation site. These values are applied to every generated page unless a page overrides them in its own frontmatter.\n\n## config.json\nPlace a `config.json` at your project root (the same folder where you execute `npx doccupine`) to define global metadata for your documentation site.\n\n```json\n{\n \"name\": \"Doccupine\",\n \"description\": \"Doccupine is a free and open-source documentation platform. Write MDX, get a production-ready site with AI chat, built-in components, and an MCP server - in one command.\",\n \"icon\": \"https://docs.doccupine.com/favicon.ico\",\n \"image\": \"https://docs.doccupine.com/preview.png\"\n}\n```\n\n## Fields\nAll fields are optional. Doccupine uses sensible defaults when a field is not set.\n\n- **name**: The primary name of your documentation website. Displayed in the site title and used in various UI elements.\n- **description**: A concise summary of your project, used in site metadata (e.g., HTML meta description) and social previews when not overridden.\n- **icon**: The favicon for your site. You can provide a full URL or a relative path to an asset in your project.\n- **image**: The Open Graph image used when links to your docs are shared on social platforms. Accepts a full URL or a relative path.\n\n## Per-page overrides\nAny page can override global values by defining the matching key in its frontmatter. When present, the page's value takes precedence over `config.json` for that page only.\n\n| Frontmatter field | Overrides | Effect |\n|---|---|---|\n| **title** | - | Page title in metadata and Open Graph |\n| **description** | `description` | Meta description and Open Graph description |\n| **name** | `name` | Site name shown in the title suffix (e.g. \"Page - My Docs\") |\n| **icon** | `icon` | Favicon for this page |\n| **image** | `image` | Open Graph preview image |\n| **section** | - | Assigns the page to a [section](/sections) |\n| **sectionOrder** | - | Controls section position in the tab bar |\n| **sectionLabel** | - | Renames the default \"Docs\" tab (use on `index.mdx`) |\n\n<Callout type=\"note\">\n If a key is not specified in a page's frontmatter, Doccupine falls back to the corresponding value in `config.json`.\n</Callout>\n\nExample frontmatter in an `.mdx` file:\n\n```text\n---\ntitle: \"My Feature\"\ndescription: \"A focused description just for this page.\"\nname: \"My Product Docs\"\nicon: \"/custom-favicon.ico\"\nimage: \"/custom-preview.png\"\ndate: \"2026-02-19\"\ncategory: \"Guides\"\n---\n```\n\n";
@@ -23,6 +23,8 @@ Place a \`config.json\` at your project root (the same folder where you execute
23
23
  \`\`\`
24
24
 
25
25
  ## Fields
26
+ All fields are optional. Doccupine uses sensible defaults when a field is not set.
27
+
26
28
  - **name**: The primary name of your documentation website. Displayed in the site title and used in various UI elements.
27
29
  - **description**: A concise summary of your project, used in site metadata (e.g., HTML meta description) and social previews when not overridden.
28
30
  - **icon**: The favicon for your site. You can provide a full URL or a relative path to an asset in your project.
@@ -38,6 +40,9 @@ Any page can override global values by defining the matching key in its frontmat
38
40
  | **name** | \`name\` | Site name shown in the title suffix (e.g. "Page - My Docs") |
39
41
  | **icon** | \`icon\` | Favicon for this page |
40
42
  | **image** | \`image\` | Open Graph preview image |
43
+ | **section** | - | Assigns the page to a [section](/sections) |
44
+ | **sectionOrder** | - | Controls section position in the tab bar |
45
+ | **sectionLabel** | - | Renames the default "Docs" tab (use on \`index.mdx\`) |
41
46
 
42
47
  <Callout type="note">
43
48
  If a key is not specified in a page's frontmatter, Doccupine falls back to the corresponding value in \`config.json\`.
@@ -1 +1 @@
1
- export declare const indexMdxTemplate = "---\ntitle: \"Introduction\"\ndescription: \"Doccupine is a free and open-source documentation platform. Write MDX, get a production-ready site with AI chat, built-in components, and an MCP server - in one command.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 0\n---\n# Welcome to Doccupine\n\nDoccupine turns a folder of MDX files into a beautiful, production-ready documentation website. Write in standard Markdown, use any of the built-in components, and get a fully themed site with AI-powered search and automatic navigation - all from one command.\n\n```bash\nnpx doccupine\n```\n\nThat's it. Doccupine prompts you for a source directory, generates a Next.js site, and starts a dev server at `http://localhost:3000`. Every edit rebuilds instantly.\n\n<Callout type=\"info\">\n Want a managed experience instead? The [Doccupine Platform](/platform) gives you a browser-based editor, one-click publishing, custom domains, and team collaboration - no local setup needed.\n</Callout>\n\n## How it works\n\nYou write `.mdx` files using Markdown and built-in components like this one. Doccupine watches your files, generates pages, builds the sidebar from your frontmatter, and handles theming, AI chat, and deployment config for you.\n\nEverything on this page - the callout above, the cards below, the code block - is a live example of what your docs can look like out of the box.\n\n<Columns cols={2}>\n <Card title=\"Start writing\" icon=\"pencil\">\n Rich docs from day one. [14+ components](/headers-and-text) work out of the box - no imports needed.\n </Card>\n <Card title=\"Ship it\" icon=\"rocket\">\n Custom domains and team collaboration on the [Doccupine Platform](/platform), or [self-host](/deployment) anywhere.\n </Card>\n</Columns>\n\n## Configure your site\n\nDoccupine works with no configuration, but when you're ready to customize, everything is controlled through simple JSON files in your project root.\n\n- [Global settings](/globals) - Site name, description, favicon, and preview image via `config.json`\n- [Navigation](/navigation) - Override the auto-generated sidebar with `navigation.json`\n- [Theme](/theme) - Colors, logos, and dark mode palette via `theme.json`\n- [Fonts](/fonts) - Google Fonts or local font files via `fonts.json`\n- [AI Assistant](/ai-assistant) - Enable the built-in chat with your own API key\n- [MCP Server](/model-context-protocol) - Let AI tools search your docs through `/api/mcp`\n";
1
+ export declare const indexMdxTemplate = "---\ntitle: \"Introduction\"\ndescription: \"Doccupine is a free and open-source documentation platform. Write MDX, get a production-ready site with AI chat, built-in components, and an MCP server - in one command.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 0\n---\n# Welcome to Doccupine\n\nDoccupine turns a folder of MDX files into a beautiful, production-ready documentation website. Write in standard Markdown, use any of the built-in components, and get a fully themed site with AI-powered search and automatic navigation - all from one command.\n\n```bash\nnpx doccupine\n```\n\nThat's it. Doccupine prompts you for a source directory, generates your site, and starts a dev server at `http://localhost:3000`. Every edit rebuilds instantly.\n\n<Callout type=\"info\">\n Want a managed experience instead? The [Doccupine Platform](/platform) gives you a browser-based editor, one-click publishing, custom domains, and team collaboration - no local setup needed.\n</Callout>\n\n## How it works\n\nYou write `.mdx` files using Markdown and built-in components like this one. Doccupine watches your files, generates pages, builds the sidebar from your frontmatter, and handles theming, AI chat, and deployment config for you.\n\nEverything on this page - the callout above, the cards below, the code block - is a live example of what your docs can look like out of the box.\n\n<Columns cols={2}>\n <Card title=\"Start writing\" icon=\"pencil\" href=\"/components\">\n Rich docs from day one. 14+ components work out of the box - no imports needed.\n </Card>\n <Card title=\"Ship it\" icon=\"rocket\" href=\"/deployment\">\n Deploy to the Doccupine Platform or self-host on any platform that supports Next.js.\n </Card>\n</Columns>\n\n## Configure your site\n\nDoccupine works with no configuration, but when you're ready to customize, everything is controlled through simple JSON files in your project root.\n\n- [Global settings](/globals) - Site name, description, favicon, and preview image via `config.json`\n- [Navigation](/navigation) - Override the auto-generated sidebar with `navigation.json`\n- [Theme](/theme) - Colors, logos, and dark mode palette via `theme.json`\n- [Fonts](/fonts) - Google Fonts or local font files via `fonts.json`\n- [AI Assistant](/ai-assistant) - Enable the built-in chat with your own API key\n- [MCP Server](/model-context-protocol) - Let AI tools search your docs through `/api/mcp`\n";
@@ -15,7 +15,7 @@ Doccupine turns a folder of MDX files into a beautiful, production-ready documen
15
15
  npx doccupine
16
16
  \`\`\`
17
17
 
18
- That's it. Doccupine prompts you for a source directory, generates a Next.js site, and starts a dev server at \`http://localhost:3000\`. Every edit rebuilds instantly.
18
+ That's it. Doccupine prompts you for a source directory, generates your site, and starts a dev server at \`http://localhost:3000\`. Every edit rebuilds instantly.
19
19
 
20
20
  <Callout type="info">
21
21
  Want a managed experience instead? The [Doccupine Platform](/platform) gives you a browser-based editor, one-click publishing, custom domains, and team collaboration - no local setup needed.
@@ -28,11 +28,11 @@ You write \`.mdx\` files using Markdown and built-in components like this one. D
28
28
  Everything on this page - the callout above, the cards below, the code block - is a live example of what your docs can look like out of the box.
29
29
 
30
30
  <Columns cols={2}>
31
- <Card title="Start writing" icon="pencil">
32
- Rich docs from day one. [14+ components](/headers-and-text) work out of the box - no imports needed.
31
+ <Card title="Start writing" icon="pencil" href="/components">
32
+ Rich docs from day one. 14+ components work out of the box - no imports needed.
33
33
  </Card>
34
- <Card title="Ship it" icon="rocket">
35
- Custom domains and team collaboration on the [Doccupine Platform](/platform), or [self-host](/deployment) anywhere.
34
+ <Card title="Ship it" icon="rocket" href="/deployment">
35
+ Deploy to the Doccupine Platform or self-host on any platform that supports Next.js.
36
36
  </Card>
37
37
  </Columns>
38
38
 
@@ -1 +1 @@
1
- export declare const mcpMdxTemplate = "---\ntitle: \"Model Context Protocol\"\ndescription: \"Connect your Doccupine documentation to AI tools with an MCP server for enhanced AI-powered documentation search.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 9\n---\n# Model Context Protocol\nConnect your documentation to AI tools with a hosted MCP server.\n\nDoccupine automatically generates a Model Context Protocol (MCP) server from your documentation, making your content accessible to AI applications like Claude, Cursor, VS Code, and other MCP-compatible tools. Your MCP server exposes semantic search capabilities, allowing AI tools to query your documentation directly and provide accurate, context-aware answers.\n\n<Callout type=\"warning\">\n The MCP server requires the [AI Assistant](/ai-assistant) to be configured. Make sure you have set up your LLM provider and API keys before using the MCP server.\n</Callout>\n\n## About MCP servers\n\nThe Model Context Protocol (MCP) is an open protocol that creates standardized connections between AI applications and external services, like documentation. Doccupine generates an MCP server from your documentation, preparing your content for the broader AI ecosystem where any MCP client can connect to your documentation.\n\nYour MCP server exposes search and retrieval tools for AI applications to query your documentation. Your users must connect your MCP server to their preferred AI tools to access your documentation.\n\n### How MCP servers work\n\nWhen an AI tool has your documentation MCP server connected, the AI tool can search your documentation directly instead of making a generic web search in response to a user's prompt. Your MCP server provides access to all indexed content from your documentation site.\n\n* The LLM can proactively search your documentation while generating a response, not just when explicitly asked.\n* The LLM determines when to use the search tool based on the context of the conversation and the relevance of your documentation.\n* Each tool call happens during the generation process, so the LLM searches up-to-date information from your documentation to generate its response.\n\n### MCP compared to web search\n\nAI tools can search the web, but MCP provides distinct advantages for documentation.\n\n* **Direct source access**: Web search depends on what search engines have indexed, which may be stale or incomplete. MCP searches your current indexed documentation directly.\n* **Integrated workflow**: MCP allows the AI to search during response generation rather than performing a separate web search.\n* **Semantic search**: MCP uses vector embeddings for semantic similarity search, providing more relevant results than keyword-based web search.\n* **No search noise**: SEO and ranking algorithms influence web search results. MCP goes straight to your documentation content.\n\n## Access your MCP server\n\nDoccupine automatically generates an MCP server for your documentation and hosts it at your documentation URL with the `/api/mcp` path. For example, if your documentation is hosted at `https://example.com`, your MCP server is available at `https://example.com/api/mcp`.\n\nThe MCP server provides both a GET endpoint to discover available tools and a POST endpoint to execute tool calls.\n\n### Authentication\n\nYou can optionally protect your MCP server with an API key by setting the `DOCS_API_KEY` environment variable in your `.env` file:\n\n```bash\nDOCS_API_KEY=your-secret-key\n```\n\nWhen `DOCS_API_KEY` is set, all requests to `/api/mcp` must include an `Authorization` header with a Bearer token:\n\n```text\nAuthorization: Bearer your-secret-key\n```\n\nRequests without a valid token receive a `401 Unauthorized` response. When `DOCS_API_KEY` is not set, the MCP server is publicly accessible with no authentication required.\n\n<Callout type=\"note\">\n Authentication only applies to the `/api/mcp` endpoint. The `/api/rag` endpoint used by the built-in AI Assistant chat is not affected by this setting.\n</Callout>\n\n### API Endpoints\n\n#### GET /api/mcp\n\nReturns information about available tools and the current index status.\n\n**Response:**\n```json\n{\n \"tools\": [\n {\n \"name\": \"search_docs\",\n \"description\": \"Search through the documentation content using semantic search...\",\n \"inputSchema\": { ... }\n },\n ...\n ],\n \"index\": {\n \"ready\": true,\n \"chunkCount\": 150\n }\n}\n```\n\n#### POST /api/mcp\n\nExecutes an MCP tool call.\n\n**Request Body:**\n```json\n{\n \"tool\": \"search_docs\",\n \"params\": {\n \"query\": \"how to deploy\",\n \"limit\": 6\n }\n}\n```\n\n**Response:**\n```json\n{\n \"content\": [\n {\n \"path\": \"app/deployment/page.tsx\",\n \"uri\": \"docs://deployment\",\n \"score\": \"0.892\",\n \"text\": \"Deploy your Doccupine site as a Next.js application...\"\n },\n ...\n ]\n}\n```\n\n## Available Tools\n\nYour MCP server exposes three tools for interacting with your documentation:\n\n### search_docs\n\nSearch through the documentation content using semantic search. Returns relevant chunks of documentation based on the query using vector embeddings and cosine similarity.\n\n**Parameters:**\n- `query` (required): The search query to find relevant documentation\n- `limit` (optional): Maximum number of results to return (default: 6)\n\n**Example:**\n```json\n{\n \"tool\": \"search_docs\",\n \"params\": {\n \"query\": \"how to configure AI assistant\",\n \"limit\": 5\n }\n}\n```\n\n### get_doc\n\nGet the full content of a specific documentation page by its path.\n\n**Parameters:**\n- `path` (required): The file path to the documentation page (e.g., `app/getting-started/page.tsx`)\n\n**Example:**\n```json\n{\n \"tool\": \"get_doc\",\n \"params\": {\n \"path\": \"app/deployment/page.tsx\"\n }\n}\n```\n\n### list_docs\n\nList all available documentation pages, optionally filtered by directory.\n\n**Parameters:**\n- `directory` (optional): Optional directory to filter results (e.g., `components`)\n\n**Example:**\n```json\n{\n \"tool\": \"list_docs\",\n \"params\": {\n \"directory\": \"configuration\"\n }\n}\n```\n\n## How it works\n\nDoccupine's MCP server uses semantic search powered by vector embeddings to provide accurate, context-aware search results.\n\n### Indexing Process\n\n1. **Document Discovery**: The server scans your `app/` directory for all `page.tsx`, `page.ts`, `page.jsx`, and `page.js` files.\n2. **Content Extraction**: It extracts content from `const content =` declarations in your page files.\n3. **Chunking**: Large documents are split into chunks of approximately 1500 characters with 200 character overlap for better context preservation.\n4. **Embedding Generation**: Each chunk is converted to a vector embedding using your configured LLM provider's embedding model.\n5. **Index Building**: All embeddings are stored in memory for fast similarity search.\n\n### Search Process\n\n1. **Query Embedding**: The search query is converted to a vector embedding using the same embedding model.\n2. **Similarity Calculation**: Cosine similarity is calculated between the query embedding and all document chunk embeddings.\n3. **Ranking**: Results are sorted by similarity score (highest first).\n4. **Response**: The top N results (based on the limit parameter) are returned with their paths, URIs, scores, and text content.\n\n<Callout type=\"note\">\n The index is built automatically when the first search is performed. The index is stored in memory and persists for the lifetime of the server process. If you update your documentation, restart the server to rebuild the index.\n</Callout>\n\n## Use your MCP server\n\nYour users must connect your MCP server to their preferred AI tools.\n\n1. Make your MCP server URL publicly available.\n2. Users copy your MCP server URL and add it to their tools.\n3. Users access your documentation through their tools.\n\nThese are some of the ways you can help your users connect to your MCP server:\n\n<Tabs>\n <TabContent title=\"Claude\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the steps to connect it to Claude.\n 1. Navigate to the [Connectors](https://claude.ai/settings/connectors) page in the Claude settings.\n 2. Select **Add custom connector**.\n 3. Add your MCP server name and URL.\n 4. Select **Add**.\n 5. When using Claude, select the attachments button (the plus icon).\n 6. Select your MCP server.\n </Step>\n </Steps>\n See the [Model Context Protocol documentation](https://modelcontextprotocol.io/docs/tutorials/use-remote-mcp-server#connecting-to-a-remote-mcp-server) for more details.\n </TabContent>\n <TabContent title=\"Claude Code\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the command to connect it to Claude Code.\n ```bash\n claude mcp add --transport http <name> <url>\n ```\n </Step>\n </Steps>\n See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/mcp#installing-mcp-servers) for more details.\n </TabContent>\n <TabContent title=\"Cursor\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the steps to connect it to Cursor.\n 1. Use <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> on Windows) to open the command palette.\n 2. Search for \"Open MCP settings\".\n 3. Select **Add custom MCP**. This opens the `mcp.json` file.\n 4. In `mcp.json`, configure your server:\n ```json\n {\n \"mcpServers\": {\n \"<your-mcp-server-name>\": {\n \"url\": \"<your-mcp-server-url>\"\n }\n }\n }\n ```\n </Step>\n </Steps>\n See the [Cursor documentation](https://docs.cursor.com/en/context/mcp#installing-mcp-servers) for more details.\n </TabContent>\n <TabContent title=\"VS Code\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the steps to connect it to VS Code.\n 1. Create a `.vscode/mcp.json` file.\n 2. In `mcp.json`, configure your server:\n ```json\n {\n \"servers\": {\n \"<your-mcp-server-name>\": {\n \"type\": \"http\",\n \"url\": \"<your-mcp-server-url>\"\n }\n }\n }\n ```\n </Step>\n </Steps>\n See the [VS Code documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more details.\n </TabContent>\n</Tabs>\n\n## Requirements\n\nTo use the MCP server, you need to have the AI Assistant configured. The MCP server uses the same LLM configuration for generating embeddings.\n\n| Variable | Required | Description |\n|---|---|---|\n| `LLM_PROVIDER` | Yes | Your LLM provider (`openai`, `anthropic`, or `google`) |\n| `DOCS_API_KEY` | No | When set, requires Bearer token authentication on `/api/mcp` |\n\n<Callout type=\"warning\">\n The MCP server requires an LLM provider to be configured for generating embeddings. Make sure you have set up your AI Assistant with a valid API key before using the MCP server.\n</Callout>\n\nSee the [AI Assistant documentation](/ai-assistant) for configuration details.\n\n## Content indexing\n\nYour MCP server searches content extracted from your page files. The server automatically discovers and indexes all `page.tsx`, `page.ts`, `page.jsx`, and `page.js` files in your `app/` directory.\n\n### Content extraction\n\nThe server extracts content from `const content =` declarations in your page files. Make sure your documentation pages export a `content` constant with your markdown or MDX content.\n\n**Example:**\n```tsx\nexport const content = `\n# Getting Started\n\nWelcome to the documentation...\n`;\n```\n\n### Excluded directories\n\nThe following directories are automatically excluded from indexing:\n- `node_modules`\n- `.next`\n- `.git`\n- `api`\n\n## Troubleshooting\n\n### Index not building\n\nIf the index is not building, check:\n- Your LLM provider is configured correctly in your `.env` file\n- You have a valid API key set\n- Your documentation pages export a `content` constant\n\n### No search results\n\nIf searches return no results:\n- Verify that your documentation pages are in the `app/` directory\n- Check that your pages export a `content` constant\n- Ensure the index has been built (check the `index.ready` status via GET `/api/mcp`)\n\n### Slow search performance\n\nThe first search may be slower as it builds the index. Subsequent searches are fast as they use the in-memory index. If performance is consistently slow:\n- Check your embedding API response times\n- Consider reducing the number of documentation pages\n- Verify your server has sufficient memory\n\n### Cloudflare blocking MCP requests\n\nIf you use Cloudflare as a proxy in front of your documentation site, Cloudflare's bot protection may block server-to-server requests from AI tools like Claude.ai. This can cause MCP connections to fail silently or return errors.\n\nThere are two ways to resolve this:\n\n**Option 1: Disable the Cloudflare proxy (simplest)**\n\nIn your Cloudflare DNS settings, click the orange cloud icon next to your domain record to switch it to \"DNS only\" (grey cloud). This disables Cloudflare's proxy and bot protection for your domain, allowing MCP requests to reach your server directly.\n\n**Option 2: Add a Cloudflare WAF exception (keeps your custom domain proxied)**\n\nIn Cloudflare dashboard:\n\n1. Go to **Security > WAF**.\n2. Click **Create rule**.\n3. Set it up as:\n - **Rule name**: Allow MCP API\n - **Field**: URI Path\n - **Operator**: starts with\n - **Value**: `/api/mcp`\n - **Action**: Skip -- then check all remaining custom rules, Rate limiting rules, and Bot Fight Mode / Super Bot Fight Mode.\n4. Deploy the rule and make sure it is ordered first (above other rules).\n\n<Callout type=\"warning\">\n Also check **Security > Bots** in your Cloudflare dashboard. If \"Bot Fight Mode\" or \"Super Bot Fight Mode\" is enabled, that is very likely what is blocking server-to-server requests from AI tools.\n</Callout>\n\n## Best practices\n\n* **Keep content up-to-date**: Restart your server after updating documentation to rebuild the index with fresh content.\n* **Use descriptive queries**: More specific queries yield better semantic search results.\n* **Monitor index status**: Use the GET endpoint to check if your index is ready before performing searches.\n* **Optimize content structure**: Well-structured markdown with clear headings improves search relevance.";
1
+ export declare const mcpMdxTemplate = "---\ntitle: \"Model Context Protocol\"\ndescription: \"Connect your Doccupine documentation to AI tools with an MCP server for enhanced AI-powered documentation search.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 9\n---\n# Model Context Protocol\nConnect your documentation to AI tools with a hosted MCP server.\n\nDoccupine automatically generates a Model Context Protocol (MCP) server from your documentation, making your content accessible to AI applications like Claude, Cursor, VS Code, and other MCP-compatible tools. Your MCP server exposes semantic search capabilities, allowing AI tools to query your documentation directly and provide accurate, context-aware answers.\n\n<Callout type=\"warning\">\n The MCP server requires the [AI Assistant](/ai-assistant) to be configured. Make sure you have set up your LLM provider and API keys before using the MCP server.\n</Callout>\n\n## About MCP servers\n\nThe Model Context Protocol (MCP) is an open protocol that creates standardized connections between AI applications and external services, like documentation. Doccupine generates an MCP server from your documentation, preparing your content for the broader AI ecosystem where any MCP client can connect to your documentation.\n\nYour MCP server exposes search and retrieval tools for AI applications to query your documentation. Your users must connect your MCP server to their preferred AI tools to access your documentation.\n\n### How MCP servers work\n\nWhen an AI tool has your documentation MCP server connected, the AI tool can search your documentation directly instead of making a generic web search in response to a user's prompt. Your MCP server provides access to all indexed content from your documentation site.\n\n* The LLM can proactively search your documentation while generating a response, not just when explicitly asked.\n* The LLM determines when to use the search tool based on the context of the conversation and the relevance of your documentation.\n* Each tool call happens during the generation process, so the LLM searches up-to-date information from your documentation to generate its response.\n\n### MCP compared to web search\n\nAI tools can search the web, but MCP provides distinct advantages for documentation.\n\n* **Direct source access**: Web search depends on what search engines have indexed, which may be stale or incomplete. MCP searches your current indexed documentation directly.\n* **Integrated workflow**: MCP allows the AI to search during response generation rather than performing a separate web search.\n* **Semantic search**: MCP uses vector embeddings for semantic similarity search, providing more relevant results than keyword-based web search.\n* **No search noise**: SEO and ranking algorithms influence web search results. MCP goes straight to your documentation content.\n\n## Access your MCP server\n\nDoccupine automatically generates an MCP server for your documentation and hosts it at your documentation URL with the `/api/mcp` path. For example, if your documentation is hosted at `https://example.com`, your MCP server is available at `https://example.com/api/mcp`.\n\nThe MCP server provides both a GET endpoint to discover available tools and a POST endpoint to execute tool calls.\n\n### Authentication\n\nYou can optionally protect your MCP server with an API key by setting the `DOCS_API_KEY` environment variable in your `.env` file:\n\n```bash\nDOCS_API_KEY=your-secret-key\n```\n\nWhen `DOCS_API_KEY` is set, all requests to `/api/mcp` must include an `Authorization` header with a Bearer token:\n\n```text\nAuthorization: Bearer your-secret-key\n```\n\nRequests without a valid token receive a `401 Unauthorized` response. When `DOCS_API_KEY` is not set, the MCP server is publicly accessible with no authentication required.\n\n<Callout type=\"note\">\n Authentication only applies to the `/api/mcp` endpoint. The `/api/rag` endpoint used by the built-in AI Assistant chat is not affected by this setting.\n</Callout>\n\n### API Endpoints\n\n#### GET /api/mcp\n\nReturns information about available tools and the current index status.\n\n**Response:**\n```json\n{\n \"tools\": [\n {\n \"name\": \"search_docs\",\n \"description\": \"Search through the documentation content using semantic search...\",\n \"inputSchema\": { ... }\n },\n ...\n ],\n \"index\": {\n \"ready\": true,\n \"chunkCount\": 150\n }\n}\n```\n\n#### POST /api/mcp\n\nExecutes an MCP tool call.\n\n**Request Body:**\n```json\n{\n \"tool\": \"search_docs\",\n \"params\": {\n \"query\": \"how to deploy\",\n \"limit\": 6\n }\n}\n```\n\n**Response:**\n```json\n{\n \"content\": [\n {\n \"path\": \"app/deployment/page.tsx\",\n \"uri\": \"docs://deployment\",\n \"score\": \"0.892\",\n \"text\": \"Deploy your Doccupine site as a Next.js application...\"\n },\n ...\n ]\n}\n```\n\n## Available Tools\n\nYour MCP server exposes three tools for interacting with your documentation:\n\n### search_docs\n\nSearch through the documentation content using semantic search. Returns relevant chunks of documentation based on the query using vector embeddings and cosine similarity.\n\n**Parameters:**\n- `query` (required): The search query to find relevant documentation\n- `limit` (optional): Maximum number of results to return (default: 6)\n\n**Example:**\n```json\n{\n \"tool\": \"search_docs\",\n \"params\": {\n \"query\": \"how to configure AI assistant\",\n \"limit\": 5\n }\n}\n```\n\n### get_doc\n\nGet the full content of a specific documentation page by its path.\n\n**Parameters:**\n- `path` (required): The file path to the documentation page (e.g., `app/getting-started/page.tsx`)\n\n**Example:**\n```json\n{\n \"tool\": \"get_doc\",\n \"params\": {\n \"path\": \"app/deployment/page.tsx\"\n }\n}\n```\n\n### list_docs\n\nList all available documentation pages, optionally filtered by directory.\n\n**Parameters:**\n- `directory` (optional): Optional directory to filter results (e.g., `components`)\n\n**Example:**\n```json\n{\n \"tool\": \"list_docs\",\n \"params\": {\n \"directory\": \"configuration\"\n }\n}\n```\n\n## How it works\n\nDoccupine's MCP server uses semantic search powered by vector embeddings to provide accurate, context-aware search results.\n\n### Indexing Process\n\n1. **Document Discovery**: The server scans your `app/` directory for all `page.tsx`, `page.ts`, `page.jsx`, and `page.js` files.\n2. **Content Extraction**: It extracts content from `const content =` declarations in your page files.\n3. **Chunking**: Large documents are split into chunks of approximately 800 characters with 100 character overlap for better context preservation.\n4. **Embedding Generation**: Each chunk is converted to a vector embedding using your configured LLM provider's embedding model.\n5. **Index Building**: All embeddings are stored in memory for fast similarity search.\n\n### Search Process\n\n1. **Query Embedding**: The search query is converted to a vector embedding using the same embedding model.\n2. **Similarity Calculation**: Cosine similarity is calculated between the query embedding and all document chunk embeddings.\n3. **Ranking**: Results are sorted by similarity score (highest first).\n4. **Response**: The top N results (based on the limit parameter) are returned with their paths, URIs, scores, and text content.\n\n<Callout type=\"note\">\n The index is built automatically when the server starts. It is stored in memory and persists for the lifetime of the server process. If you update your documentation, restart the server to rebuild the index.\n</Callout>\n\n## Use your MCP server\n\nYour users must connect your MCP server to their preferred AI tools.\n\n1. Make your MCP server URL publicly available.\n2. Users copy your MCP server URL and add it to their tools.\n3. Users access your documentation through their tools.\n\nThese are some of the ways you can help your users connect to your MCP server:\n\n<Tabs>\n <TabContent title=\"Claude\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the steps to connect it to Claude.\n 1. Navigate to the [Connectors](https://claude.ai/settings/connectors) page in the Claude settings.\n 2. Select **Add custom connector**.\n 3. Add your MCP server name and URL.\n 4. Select **Add**.\n 5. When using Claude, select the attachments button (the plus icon).\n 6. Select your MCP server.\n </Step>\n </Steps>\n See the [Model Context Protocol documentation](https://modelcontextprotocol.io/docs/tutorials/use-remote-mcp-server#connecting-to-a-remote-mcp-server) for more details.\n </TabContent>\n <TabContent title=\"Claude Code\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the command to connect it to Claude Code.\n ```bash\n claude mcp add --transport http <name> <url>\n ```\n </Step>\n </Steps>\n See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/mcp#installing-mcp-servers) for more details.\n </TabContent>\n <TabContent title=\"Cursor\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the steps to connect it to Cursor.\n 1. Use <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> on Windows) to open the command palette.\n 2. Search for \"Open MCP settings\".\n 3. Select **Add custom MCP**. This opens the `mcp.json` file.\n 4. In `mcp.json`, configure your server:\n ```json\n {\n \"mcpServers\": {\n \"<your-mcp-server-name>\": {\n \"url\": \"<your-mcp-server-url>\"\n }\n }\n }\n ```\n </Step>\n </Steps>\n See the [Cursor documentation](https://docs.cursor.com/en/context/mcp#installing-mcp-servers) for more details.\n </TabContent>\n <TabContent title=\"VS Code\">\n <Steps>\n <Step title=\"Get your MCP server URL.\">\n Your MCP server URL is available at `https://your-domain.com/api/mcp`.\n </Step>\n <Step title=\"Publish your MCP server URL for your users.\">\n Create a guide for your users that includes your MCP server URL and the steps to connect it to VS Code.\n 1. Create a `.vscode/mcp.json` file.\n 2. In `mcp.json`, configure your server:\n ```json\n {\n \"servers\": {\n \"<your-mcp-server-name>\": {\n \"type\": \"http\",\n \"url\": \"<your-mcp-server-url>\"\n }\n }\n }\n ```\n </Step>\n </Steps>\n See the [VS Code documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more details.\n </TabContent>\n</Tabs>\n\n## Requirements\n\nTo use the MCP server, you need to have the AI Assistant configured. The MCP server uses the same LLM configuration for generating embeddings.\n\n| Variable | Required | Description |\n|---|---|---|\n| `LLM_PROVIDER` | Yes | Your LLM provider (`openai`, `anthropic`, or `google`) |\n| `DOCS_API_KEY` | No | When set, requires Bearer token authentication on `/api/mcp` |\n\n<Callout type=\"warning\">\n The MCP server requires an LLM provider to be configured for generating embeddings. Make sure you have set up your AI Assistant with a valid API key before using the MCP server.\n</Callout>\n\nSee the [AI Assistant documentation](/ai-assistant) for configuration details.\n\n## Content indexing\n\nYour MCP server searches content extracted from your page files. The server automatically discovers and indexes all `page.tsx`, `page.ts`, `page.jsx`, and `page.js` files in your `app/` directory.\n\n### Content extraction\n\nThe server extracts content from `const content =` declarations in your page files. Make sure your documentation pages export a `content` constant with your markdown or MDX content.\n\n**Example:**\n```tsx\nexport const content = `\n# Getting Started\n\nWelcome to the documentation...\n`;\n```\n\n### Excluded directories\n\nThe following directories are automatically excluded from indexing:\n- `node_modules`\n- `.next`\n- `.git`\n- `api`\n\n## Troubleshooting\n\n### Index not building\n\nIf the index is not building, check:\n- Your LLM provider is configured correctly in your `.env` file\n- You have a valid API key set\n- Your documentation pages export a `content` constant\n\n### No search results\n\nIf searches return no results:\n- Verify that your documentation pages are in the `app/` directory\n- Check that your pages export a `content` constant\n- Ensure the index has been built (check the `index.ready` status via GET `/api/mcp`)\n\n### Slow search performance\n\nThe first search may be slower as it builds the index. Subsequent searches are fast as they use the in-memory index. If performance is consistently slow:\n- Check your embedding API response times\n- Consider reducing the number of documentation pages\n- Verify your server has sufficient memory\n\n### Cloudflare blocking MCP requests\n\nIf you use Cloudflare as a proxy in front of your documentation site, Cloudflare's bot protection may block server-to-server requests from AI tools like Claude.ai. This can cause MCP connections to fail silently or return errors.\n\nThere are two ways to resolve this:\n\n**Option 1: Disable the Cloudflare proxy (simplest)**\n\nIn your Cloudflare DNS settings, click the orange cloud icon next to your domain record to switch it to \"DNS only\" (grey cloud). This disables Cloudflare's proxy and bot protection for your domain, allowing MCP requests to reach your server directly.\n\n**Option 2: Add a Cloudflare WAF exception (keeps your custom domain proxied)**\n\nIn Cloudflare dashboard:\n\n1. Go to **Security > WAF**.\n2. Click **Create rule**.\n3. Set it up as:\n - **Rule name**: Allow MCP API\n - **Field**: URI Path\n - **Operator**: starts with\n - **Value**: `/api/mcp`\n - **Action**: Skip -- then check all remaining custom rules, Rate limiting rules, and Bot Fight Mode / Super Bot Fight Mode.\n4. Deploy the rule and make sure it is ordered first (above other rules).\n\n<Callout type=\"warning\">\n Also check **Security > Bots** in your Cloudflare dashboard. If \"Bot Fight Mode\" or \"Super Bot Fight Mode\" is enabled, that is very likely what is blocking server-to-server requests from AI tools.\n</Callout>\n\n## Best practices\n\n* **Keep content up-to-date**: Restart your server after updating documentation to rebuild the index with fresh content.\n* **Use descriptive queries**: More specific queries yield better semantic search results.\n* **Monitor index status**: Use the GET endpoint to check if your index is ready before performing searches.\n* **Optimize content structure**: Well-structured markdown with clear headings improves search relevance.";
@@ -183,7 +183,7 @@ Doccupine's MCP server uses semantic search powered by vector embeddings to prov
183
183
 
184
184
  1. **Document Discovery**: The server scans your \`app/\` directory for all \`page.tsx\`, \`page.ts\`, \`page.jsx\`, and \`page.js\` files.
185
185
  2. **Content Extraction**: It extracts content from \`const content =\` declarations in your page files.
186
- 3. **Chunking**: Large documents are split into chunks of approximately 1500 characters with 200 character overlap for better context preservation.
186
+ 3. **Chunking**: Large documents are split into chunks of approximately 800 characters with 100 character overlap for better context preservation.
187
187
  4. **Embedding Generation**: Each chunk is converted to a vector embedding using your configured LLM provider's embedding model.
188
188
  5. **Index Building**: All embeddings are stored in memory for fast similarity search.
189
189
 
@@ -195,7 +195,7 @@ Doccupine's MCP server uses semantic search powered by vector embeddings to prov
195
195
  4. **Response**: The top N results (based on the limit parameter) are returned with their paths, URIs, scores, and text content.
196
196
 
197
197
  <Callout type="note">
198
- The index is built automatically when the first search is performed. The index is stored in memory and persists for the lifetime of the server process. If you update your documentation, restart the server to rebuild the index.
198
+ The index is built automatically when the server starts. It is stored in memory and persists for the lifetime of the server process. If you update your documentation, restart the server to rebuild the index.
199
199
  </Callout>
200
200
 
201
201
  ## Use your MCP server
@@ -1 +1 @@
1
- export declare const navigationMdxTemplate = "---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n# Navigation\nDoccupine builds your sidebar automatically from your MDX pages. By default, it reads the page frontmatter and groups pages into categories in the order you define. For larger docs, you can take full control with a `navigation.json` file.\n\n## Automatic navigation (default)\nWhen no custom navigation is provided, Doccupine generates a structure based on each page's frontmatter.\n\n### Frontmatter fields\n- **category**: The category name that groups the page in the sidebar.\n- **categoryOrder**: The position of the category within the sidebar. Lower numbers appear first.\n- **order**: The position of the page within its category. Lower numbers appear first.\n\n### Example frontmatter\n\n```text\n---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n```\n\nThis approach is great for small sets of documents. For larger projects, setting these fields on every page can become repetitive.\n\n## Custom navigation with navigation.json\nTo centrally define the entire sidebar, create a `navigation.json` at your project root (the same folder where you execute `npx doccupine`). When present, it takes priority over page frontmatter and fully controls the navigation structure.\n\n### Array format\nThe simplest format is an array of categories. When using [sections](/sections), this applies to the root section only.\n\n```json\n[\n {\n \"label\": \"General\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Getting Started\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n },\n {\n \"label\": \"Components\",\n \"links\": [\n { \"slug\": \"headers-and-text\", \"title\": \"Headers and Text\" },\n { \"slug\": \"lists-and-tables\", \"title\": \"Lists and tables\" },\n { \"slug\": \"code\", \"title\": \"Code\" },\n { \"slug\": \"accordion\", \"title\": \"Accordion\" },\n { \"slug\": \"tabs\", \"title\": \"Tabs\" },\n { \"slug\": \"cards\", \"title\": \"Cards\" },\n { \"slug\": \"buttons\", \"title\": \"Buttons\" },\n { \"slug\": \"callouts\", \"title\": \"Callouts\" },\n { \"slug\": \"images-and-embeds\", \"title\": \"Images and embeds\" },\n { \"slug\": \"icons\", \"title\": \"Icons\" },\n { \"slug\": \"fields\", \"title\": \"Fields\" },\n { \"slug\": \"update\", \"title\": \"Update\" },\n { \"slug\": \"columns\", \"title\": \"Columns\" },\n { \"slug\": \"steps\", \"title\": \"Steps\" }\n ]\n },\n {\n \"label\": \"Configuration\",\n \"links\": [\n { \"slug\": \"globals\", \"title\": \"Globals\" },\n { \"slug\": \"navigation\", \"title\": \"Navigation\" },\n { \"slug\": \"sections\", \"title\": \"Sections\" },\n { \"slug\": \"footer-links\", \"title\": \"Footer Links\" },\n { \"slug\": \"theme\", \"title\": \"Theme\" },\n { \"slug\": \"media-and-assets\", \"title\": \"Media and assets\" },\n { \"slug\": \"fonts\", \"title\": \"Fonts\" },\n { \"slug\": \"ai-assistant\", \"title\": \"AI Assistant\" },\n { \"slug\": \"model-context-protocol\", \"title\": \"Model Context Protocol\" },\n { \"slug\": \"deployment\", \"title\": \"Deployment\" }\n ]\n }\n]\n```\n\n### Object format (per-section)\nWhen using [sections](/sections), you can define navigation for each section by using an object keyed by section slug. Sections without a key fall back to auto-generated navigation from frontmatter.\n\n```json\n{\n \"\": [\n {\n \"label\": \"General\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Getting Started\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n }\n ],\n \"platform\": [\n {\n \"label\": \"Overview\",\n \"links\": [\n { \"slug\": \"platform/auth\", \"title\": \"Authentication\" },\n { \"slug\": \"platform/users\", \"title\": \"Users\" }\n ]\n }\n ]\n}\n```\n\nThe key `\"\"` controls the root section. Other keys match section slugs defined in `sections.json` or derived from frontmatter. See [Sections](/sections) for details on configuring sections.\n\n### Fields\n- **label**: The section header shown in the sidebar.\n- **links**: An array of page entries for that section.\n - **slug**: The MDX file slug (filename without extension). Use an empty string `\"\"` for `index.mdx`.\n - **title**: The display title in the navigation. This can differ from the page's `title` frontmatter.\n\n## Precedence and behavior\n\n<Callout type=\"note\">\n `navigation.json` takes priority over frontmatter. If present, it fully controls the sidebar structure for the sections it covers.\n</Callout>\n\n- Without `navigation.json`, the sidebar is built from page frontmatter: `category` -> grouped; `categoryOrder` -> category position; `order` -> page position.\n- When using the object format, sections not listed in `navigation.json` fall back to frontmatter-based navigation.\n- Pages without a `category` appear at the top level.\n\n## Tips\n- **Start simple**: Use frontmatter for small docs. Switch to `navigation.json` as the structure grows.\n- **Keep slugs consistent**: `slug` must match the MDX filename (e.g., `text.mdx` -> `text`).\n- **Control titles**: Use `title` in `navigation.json` to customize sidebar labels without changing page frontmatter.\n- **Per-section navigation**: Use the object format to define different sidebars for each section. Mix and match - define some sections explicitly and let others auto-generate.";
1
+ export declare const navigationMdxTemplate = "---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n# Navigation\nDoccupine builds your sidebar automatically from your MDX pages. By default, it reads the page frontmatter and groups pages into categories in the order you define. For larger docs, you can take full control with a `navigation.json` file.\n\n## Automatic navigation (default)\nWhen no custom navigation is provided, Doccupine generates a structure based on each page's frontmatter.\n\n### Frontmatter fields\n- **category**: The category name that groups the page in the sidebar.\n- **categoryOrder**: The position of the category within the sidebar. Lower numbers appear first.\n- **order**: The position of the page within its category. Lower numbers appear first.\n\n### Example frontmatter\n\n```text\n---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n```\n\nThis approach is great for small sets of documents. For larger projects, setting these fields on every page can become repetitive.\n\n## Custom navigation with navigation.json\nTo centrally define the entire sidebar, create a `navigation.json` at your project root (the same folder where you execute `npx doccupine`). When present, it takes priority over page frontmatter and fully controls the navigation structure.\n\n### Array format\nThe simplest format is an array of categories. When using [sections](/sections), this applies to the root section only.\n\n```json\n[\n {\n \"label\": \"General\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Getting Started\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n },\n {\n \"label\": \"Components\",\n \"links\": [\n { \"slug\": \"headers-and-text\", \"title\": \"Headers and Text\" },\n { \"slug\": \"lists-and-tables\", \"title\": \"Lists and tables\" },\n { \"slug\": \"code\", \"title\": \"Code\" },\n { \"slug\": \"accordion\", \"title\": \"Accordion\" },\n { \"slug\": \"tabs\", \"title\": \"Tabs\" },\n { \"slug\": \"cards\", \"title\": \"Cards\" },\n { \"slug\": \"buttons\", \"title\": \"Buttons\" },\n { \"slug\": \"callouts\", \"title\": \"Callouts\" },\n { \"slug\": \"image-and-embeds\", \"title\": \"Images and embeds\" },\n { \"slug\": \"icons\", \"title\": \"Icons\" },\n { \"slug\": \"fields\", \"title\": \"Fields\" },\n { \"slug\": \"update\", \"title\": \"Update\" },\n { \"slug\": \"columns\", \"title\": \"Columns\" },\n { \"slug\": \"steps\", \"title\": \"Steps\" }\n ]\n },\n {\n \"label\": \"Configuration\",\n \"links\": [\n { \"slug\": \"globals\", \"title\": \"Globals\" },\n { \"slug\": \"navigation\", \"title\": \"Navigation\" },\n { \"slug\": \"sections\", \"title\": \"Sections\" },\n { \"slug\": \"footer-links\", \"title\": \"Footer Links\" },\n { \"slug\": \"theme\", \"title\": \"Theme\" },\n { \"slug\": \"media-and-assets\", \"title\": \"Media and assets\" },\n { \"slug\": \"fonts\", \"title\": \"Fonts\" },\n { \"slug\": \"ai-assistant\", \"title\": \"AI Assistant\" },\n { \"slug\": \"model-context-protocol\", \"title\": \"Model Context Protocol\" },\n { \"slug\": \"deployment\", \"title\": \"Deployment\" }\n ]\n }\n]\n```\n\n### Object format (per-section)\nWhen using [sections](/sections), you can define navigation for each section by using an object keyed by section slug. Sections without a key fall back to auto-generated navigation from frontmatter.\n\n```json\n{\n \"\": [\n {\n \"label\": \"General\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Getting Started\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n }\n ],\n \"platform\": [\n {\n \"label\": \"Overview\",\n \"links\": [\n { \"slug\": \"platform/auth\", \"title\": \"Authentication\" },\n { \"slug\": \"platform/users\", \"title\": \"Users\" }\n ]\n }\n ]\n}\n```\n\nThe key `\"\"` controls the root section. Other keys match section slugs defined in `sections.json` or derived from frontmatter. See [Sections](/sections) for details on configuring sections.\n\n### Fields\n- **label**: The section header shown in the sidebar.\n- **links**: An array of page entries for that section.\n - **slug**: The MDX file slug (filename without extension). Use an empty string `\"\"` for `index.mdx`.\n - **title**: The display title in the navigation. This can differ from the page's `title` frontmatter.\n\n## Precedence and behavior\n\n<Callout type=\"note\">\n `navigation.json` takes priority over frontmatter. If present, it fully controls the sidebar structure for the sections it covers.\n</Callout>\n\n- Without `navigation.json`, the sidebar is built from page frontmatter: `category` -> grouped; `categoryOrder` -> category position; `order` -> page position.\n- When using the object format, sections not listed in `navigation.json` fall back to frontmatter-based navigation.\n- Pages without a `category` appear at the top level.\n\n## Tips\n- **Start simple**: Use frontmatter for small docs. Switch to `navigation.json` as the structure grows.\n- **Keep slugs consistent**: `slug` must match the MDX filename (e.g., `text.mdx` -> `text`).\n- **Control titles**: Use `title` in `navigation.json` to customize sidebar labels without changing page frontmatter.\n- **Per-section navigation**: Use the object format to define different sidebars for each section. Mix and match - define some sections explicitly and let others auto-generate.";
@@ -58,7 +58,7 @@ The simplest format is an array of categories. When using [sections](/sections),
58
58
  { "slug": "cards", "title": "Cards" },
59
59
  { "slug": "buttons", "title": "Buttons" },
60
60
  { "slug": "callouts", "title": "Callouts" },
61
- { "slug": "images-and-embeds", "title": "Images and embeds" },
61
+ { "slug": "image-and-embeds", "title": "Images and embeds" },
62
62
  { "slug": "icons", "title": "Icons" },
63
63
  { "slug": "fields", "title": "Fields" },
64
64
  { "slug": "update", "title": "Update" },
@@ -1 +1 @@
1
- export declare const platformExternalLinksMdxTemplate = "---\ntitle: \"External Links\"\ndescription: \"Add quick-access link buttons to your site's footer for GitHub, Discord, and other external resources.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 2\norder: 5\nsection: \"Platform\"\n---\n# External Links\nThe Footer Links settings page lets you add external link buttons to your documentation site's footer. These provide quick access to your project's GitHub repository, Discord server, social profiles, and other resources.\n\n## Adding a link\nClick **Add Link** and configure:\n\n- **Title** - the display text for the link\n- **URL** - the target URL\n- **Icon** (optional) - choose from one of the preset icons\n\n## Available icons\nYou can assign one of these icons to each link:\n\n- GitHub\n- Twitter / X\n- Discord\n- Slack\n- LinkedIn\n- YouTube\n- Website (globe)\n- Email\n- Docs (book)\n- Code\n- Package\n- RSS\n- Chat\n- Sponsor (heart)\n\nLeave the icon unset for a text-only link.\n\n## How it works\nLink settings are stored in `links.json` at the root of your repository:\n\n```json\n[\n {\n \"title\": \"GitHub\",\n \"url\": \"https://github.com/your-org/your-repo\",\n \"icon\": \"github\"\n },\n {\n \"title\": \"Discord\",\n \"url\": \"https://discord.gg/your-invite\",\n \"icon\": \"discord\"\n }\n]\n```";
1
+ export declare const platformExternalLinksMdxTemplate = "---\ntitle: \"External Links\"\ndescription: \"Add quick-access link buttons to your site's footer for GitHub, Discord, and other external resources.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 2\norder: 5\nsection: \"Platform\"\n---\n# External Links\nThe Footer Links settings page lets you add external link buttons to your documentation site's footer. These provide quick access to your project's GitHub repository, Discord server, social profiles, and other resources.\n\n## Adding a link\nClick **Add Link** and configure:\n\n- **Title** - the display text for the link\n- **URL** - the target URL\n- **Icon** (optional) - choose from one of the preset icons\n\n## Available icons\nYou can assign one of these icons to each link:\n\n- GitHub\n- Twitter / X\n- Discord\n- Slack\n- LinkedIn\n- YouTube\n- Website (globe)\n- Email\n- Docs (book)\n- Code\n- Package\n- RSS\n- Chat\n- Sponsor (heart)\n\nLeave the icon unset for a text-only link.\n\nIf you edit `links.json` directly, use [Lucide](https://lucide.dev/) icon names (e.g. `github`, `message-circle`, `heart`).\n\n## How it works\nLink settings are stored in `links.json` at the root of your repository:\n\n```json\n[\n {\n \"title\": \"GitHub\",\n \"url\": \"https://github.com/your-org/your-repo\",\n \"icon\": \"github\"\n },\n {\n \"title\": \"Discord\",\n \"url\": \"https://discord.gg/your-invite\",\n \"icon\": \"discord\"\n }\n]\n```";
@@ -37,6 +37,8 @@ You can assign one of these icons to each link:
37
37
 
38
38
  Leave the icon unset for a text-only link.
39
39
 
40
+ If you edit \`links.json\` directly, use [Lucide](https://lucide.dev/) icon names (e.g. \`github\`, \`message-circle\`, \`heart\`).
41
+
40
42
  ## How it works
41
43
  Link settings are stored in \`links.json\` at the root of your repository:
42
44
 
@@ -1 +1 @@
1
- export declare const platformFontsSettingsMdxTemplate = "---\ntitle: \"Fonts Settings\"\ndescription: \"Configure custom typography with Google Fonts or local font files.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 2\norder: 4\nsection: \"Platform\"\n---\n# Fonts Settings\nThe Fonts settings page lets you customize your documentation site's typography using Google Fonts or locally uploaded font files.\n\n## Google Fonts\nSelect a font from the full Google Fonts library:\n\n1. Type a font name to search the library.\n2. Select the **weights** you need (e.g., 400 for regular, 700 for bold). You can select multiple weights.\n3. Choose **subsets** for language support (latin, cyrillic, greek, vietnamese, etc.).\n\n<Callout type=\"note\">\n Only include the weights and subsets you actually use. Each addition increases page load time.\n</Callout>\n\n## Local fonts\nUpload your own font files for complete typographic control:\n\n1. Click **Add Font Source** to add a font file entry.\n2. Upload a font file (WOFF2, WOFF, TTF, OTF, or EOT format).\n3. Set the **weight** (e.g., 400, 700) and **style** (normal or italic).\n4. Add more sources for additional weights and styles.\n\nWOFF2 is recommended for the best compression and browser support.\n\n## How it works\nFont settings are stored in `fonts.json` at the root of your repository. Here's an example using Google Fonts:\n\n```json\n{\n \"type\": \"google\",\n \"name\": \"Inter\",\n \"weights\": [400, 500, 600, 700],\n \"subsets\": [\"latin\"]\n}\n```";
1
+ export declare const platformFontsSettingsMdxTemplate = "---\ntitle: \"Fonts Settings\"\ndescription: \"Configure custom typography with Google Fonts or local font files.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 2\norder: 4\nsection: \"Platform\"\n---\n# Fonts Settings\nThe Fonts settings page lets you customize your documentation site's typography using Google Fonts or locally uploaded font files.\n\n## Google Fonts\nSelect a font from the full Google Fonts library:\n\n1. Type a font name to search the library.\n2. Select the **weights** you need (e.g., 400 for regular, 700 for bold). You can select multiple weights.\n3. Choose **subsets** for language support (latin, cyrillic, greek, vietnamese, etc.).\n\n<Callout type=\"note\">\n Only include the weights and subsets you actually use. Each addition increases page load time.\n</Callout>\n\n## Local fonts\nUpload your own font files for complete typographic control:\n\n1. Click **Add Font Source** to add a font file entry.\n2. Upload a font file (WOFF2, WOFF, TTF, OTF, or EOT format).\n3. Set the **weight** (e.g., 400, 700) and **style** (normal or italic).\n4. Add more sources for additional weights and styles.\n\nWOFF2 is recommended for the best compression and browser support.\n\n## How it works\nFont settings are stored in `fonts.json` at the root of your repository. Here's an example using Google Fonts:\n\n```json\n{\n \"googleFont\": {\n \"fontName\": \"Inter\",\n \"subsets\": [\"latin\"],\n \"weight\": [\"400\", \"500\", \"600\", \"700\"]\n }\n}\n```\n\nSee the [Fonts](/fonts) page for the full configuration format, including local font support.";
@@ -36,9 +36,12 @@ Font settings are stored in \`fonts.json\` at the root of your repository. Here'
36
36
 
37
37
  \`\`\`json
38
38
  {
39
- "type": "google",
40
- "name": "Inter",
41
- "weights": [400, 500, 600, 700],
42
- "subsets": ["latin"]
39
+ "googleFont": {
40
+ "fontName": "Inter",
41
+ "subsets": ["latin"],
42
+ "weight": ["400", "500", "600", "700"]
43
+ }
43
44
  }
44
- \`\`\``;
45
+ \`\`\`
46
+
47
+ See the [Fonts](/fonts) page for the full configuration format, including local font support.`;
@@ -1 +1 @@
1
- export declare const platformIndexMdxTemplate = "---\ntitle: \"Platform Overview\"\ndescription: \"Learn how to use the Doccupine platform to create, customize, and deploy documentation websites.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 0\nsection: \"Platform\"\n---\n# Platform Overview\nThe Doccupine platform gives you everything you need to create, customize, and host beautiful documentation websites - all from your browser. No local setup, no CI pipelines, no infrastructure to manage.\n\n## What you get\n- **Browser-based editor** for writing and managing your documentation files\n- **One-click publishing** that commits to GitHub and deploys automatically\n- **Visual configuration** for themes, navigation, fonts, links, and more\n- **Custom domains** with automatic HTTPS\n- **AI assistant** built into every deployed site\n- **Team collaboration** with role-based access control\n\n## How it works\nDoccupine connects two core pieces behind the scenes:\n\n1. **GitHub** stores your documentation source files in a Git repository\n2. **Doccupine** builds, hosts, and serves your site globally - plus provides a dashboard for editing, configuring, and managing your project\n\nYou write MDX files, configure your site through visual settings pages, and hit Publish. Doccupine handles the rest.\n\n## Getting started\n\n1. **Sign up** at Doccupine and start your free 30-day trial - no credit card required.\n2. **Create a project** from the dashboard. Choose between a managed repository or connecting your own GitHub account.\n3. **Edit your docs** using the built-in file explorer and editor.\n4. **Configure your site** through the settings pages - theme, navigation, fonts, and more.\n5. **Publish** your changes with a single click.\n\n<Callout type=\"success\">\n Your documentation site is live the moment you create a project. Doccupine deploys a starter site automatically so you can see results immediately.\n</Callout>\n\n## Dashboard\nAfter signing in, the dashboard shows all your projects. You'll see two sections:\n\n- **Your Projects** - documentation sites you own, plus a button to create new ones\n- **Shared Projects** - sites that other users have invited you to collaborate on\n\nClick any project card to open it and start working.";
1
+ export declare const platformIndexMdxTemplate = "---\ntitle: \"Platform Overview\"\ndescription: \"Learn how to use the Doccupine platform to create, customize, and deploy documentation websites.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 0\nsection: \"Platform\"\n---\n# Platform Overview\nThe Doccupine platform gives you everything you need to create, customize, and host beautiful documentation websites - all from your browser. No local setup, no CI pipelines, no infrastructure to manage.\n\n## What you get\n- **Browser-based editor** for writing and managing your documentation files\n- **One-click publishing** that commits to GitHub and deploys automatically\n- **Visual configuration** for themes, navigation, fonts, links, and more\n- **Custom domains** with automatic HTTPS\n- **AI assistant** built into every deployed site\n- **Team collaboration** with role-based access control\n\n## How it works\nDoccupine connects two core pieces behind the scenes:\n\n1. **GitHub** stores your documentation source files in a Git repository\n2. **Doccupine** builds, hosts, and serves your site globally - plus provides a dashboard for editing, configuring, and managing your project\n\nYou write MDX files, configure your site through visual settings pages, and hit Publish. Doccupine handles the rest.\n\n## Getting started\n\n1. **Sign up** at Doccupine and start your free 30-day trial - no credit card required.\n2. **Create a project** from the dashboard. Choose between a managed repository or connecting your own GitHub account.\n3. **Edit your docs** using the built-in file explorer and editor.\n4. **Configure your site** through the settings pages - theme, navigation, fonts, and more.\n5. **Publish** your changes with a single click.\n\n<Callout type=\"success\">\n Your documentation site is live the moment you create a project. Doccupine deploys a starter site automatically so you can see results immediately.\n</Callout>\n\n## Dashboard\nAfter signing in, the dashboard shows all your projects. You'll see two sections:\n\n- **Your Projects** - documentation sites you own, plus a button to create new ones\n- **Shared Projects** - sites that other users have invited you to collaborate on\n\nClick any project card to open it and start working.\n\n<Columns cols={2}>\n <Card title=\"Sign Up\" icon=\"user-plus\" href=\"https://doccupine.com/sign-up\">\n Create your free account and start building documentation in minutes.\n </Card>\n <Card title=\"Sign In\" icon=\"log-in\" href=\"https://doccupine.com/sign-in\">\n Already have an account? Sign in to your dashboard.\n </Card>\n</Columns>";
@@ -44,4 +44,13 @@ After signing in, the dashboard shows all your projects. You'll see two sections
44
44
  - **Your Projects** - documentation sites you own, plus a button to create new ones
45
45
  - **Shared Projects** - sites that other users have invited you to collaborate on
46
46
 
47
- Click any project card to open it and start working.`;
47
+ Click any project card to open it and start working.
48
+
49
+ <Columns cols={2}>
50
+ <Card title="Sign Up" icon="user-plus" href="https://doccupine.com/sign-up">
51
+ Create your free account and start building documentation in minutes.
52
+ </Card>
53
+ <Card title="Sign In" icon="log-in" href="https://doccupine.com/sign-in">
54
+ Already have an account? Sign in to your dashboard.
55
+ </Card>
56
+ </Columns>`;
@@ -1 +1 @@
1
- export declare const platformSiteSettingsMdxTemplate = "---\ntitle: \"Site Settings\"\ndescription: \"Configure your documentation site's name, description, favicon, and preview image.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 2\norder: 0\nsection: \"Platform\"\n---\n# Site Settings\nThe Site settings page lets you configure the core metadata for your documentation site. These values are stored in `config.json` at the root of your repository.\n\n## Fields\n\n### Name\nThe name of your documentation site. This appears in the site header and browser tab title.\n\n### Description\nA short description of your documentation. Used in meta tags for search engine optimization and social media previews.\n\n### Favicon\nUpload a favicon image that appears in browser tabs. Supported formats include PNG, ICO, and SVG. Use the file upload button to select an image from your computer.\n\n### Preview image\nUpload an image used for social media and OpenGraph previews. This is the image that appears when your documentation URL is shared on platforms like Twitter, Slack, or Discord.\n\n<Callout type=\"note\">\n Changes to site settings are staged as pending changes, just like file edits. Click **Publish** to commit them to your repository and trigger a deploy.\n</Callout>\n\n## How it works\nBehind the scenes, the Site settings page reads and writes `config.json` in your repository. You can also edit this file directly in the file editor if you prefer.\n\n```json\n{\n \"name\": \"My Documentation\",\n \"description\": \"Documentation for my project\",\n \"favicon\": \"/favicon.png\",\n \"previewImage\": \"/preview.png\"\n}\n```";
1
+ export declare const platformSiteSettingsMdxTemplate = "---\ntitle: \"Site Settings\"\ndescription: \"Configure your documentation site's name, description, icon, and image.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 2\norder: 0\nsection: \"Platform\"\n---\n# Site Settings\nThe Site settings page lets you configure the core metadata for your documentation site. These values are stored in `config.json` at the root of your repository.\n\n## Fields\n\n### Name\nThe name of your documentation site. This appears in the site header and browser tab title.\n\n### Description\nA short description of your documentation. Used in meta tags for search engine optimization and social media previews.\n\n### Favicon\nUpload a favicon image that appears in browser tabs. Supported formats include PNG, ICO, and SVG. Use the file upload button to select an image from your computer.\n\n### Preview image\nUpload an image used for social media and OpenGraph previews. This is the image that appears when your documentation URL is shared on platforms like Twitter, Slack, or Discord.\n\n<Callout type=\"note\">\n Changes to site settings are staged as pending changes, just like file edits. Click **Publish** to commit them to your repository and trigger a deploy.\n</Callout>\n\n## How it works\nBehind the scenes, the Site settings page reads and writes `config.json` in your repository. You can also edit this file directly in the file editor if you prefer. See the [Globals](/globals) page for the full configuration reference.\n\n```json\n{\n \"name\": \"My Documentation\",\n \"description\": \"Documentation for my project\",\n \"icon\": \"/favicon.png\",\n \"image\": \"/preview.png\"\n}\n```";
@@ -1,6 +1,6 @@
1
1
  export const platformSiteSettingsMdxTemplate = `---
2
2
  title: "Site Settings"
3
- description: "Configure your documentation site's name, description, favicon, and preview image."
3
+ description: "Configure your documentation site's name, description, icon, and image."
4
4
  date: "2026-02-19"
5
5
  category: "Configuration"
6
6
  categoryOrder: 2
@@ -29,13 +29,13 @@ Upload an image used for social media and OpenGraph previews. This is the image
29
29
  </Callout>
30
30
 
31
31
  ## How it works
32
- Behind the scenes, the Site settings page reads and writes \`config.json\` in your repository. You can also edit this file directly in the file editor if you prefer.
32
+ Behind the scenes, the Site settings page reads and writes \`config.json\` in your repository. You can also edit this file directly in the file editor if you prefer. See the [Globals](/globals) page for the full configuration reference.
33
33
 
34
34
  \`\`\`json
35
35
  {
36
36
  "name": "My Documentation",
37
37
  "description": "Documentation for my project",
38
- "favicon": "/favicon.png",
39
- "previewImage": "/preview.png"
38
+ "icon": "/favicon.png",
39
+ "image": "/preview.png"
40
40
  }
41
41
  \`\`\``;
@@ -1 +1 @@
1
- export declare const sectionsMdxTemplate = "---\ntitle: \"Sections\"\ndescription: \"Split your documentation into top-level sections with independent sidebars.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 3\n---\n# Sections\nSections let you divide your documentation into separate top-level areas - for example \"Guides\", \"API Reference\", and \"SDKs\". Each section gets its own sidebar and appears as a horizontal tab bar below the site header.\n\n<Callout type=\"note\">\n Sections are entirely opt-in. If you don't configure them, nothing changes - your site works exactly as before with a single flat navigation.\n</Callout>\n\n## Automatic sections (frontmatter)\nThe simplest way to add sections is through page frontmatter. Add a `section` field to group pages, and an optional `sectionOrder` to control the order of sections in the bar.\n\n### Frontmatter fields\n- **section**: The display name for the section this page belongs to (e.g. \"API Reference\").\n- **sectionOrder**: Controls the position of the section in the bar. Lower numbers appear first.\n\nThe section slug is derived automatically from the label - lowercased with spaces replaced by hyphens. So \"API Reference\" becomes `api-reference`.\n\nPages without a `section` field stay at the root URL and appear under a default tab labeled \"Docs\". You can rename this tab with the `sectionLabel` field on your `index.mdx`:\n\n```text\n---\ntitle: \"Welcome\"\nsectionLabel: \"Guides\"\n---\n```\n\n### Directory-based organization\nYou can organize each section's files in a subdirectory that matches the section slug. When the directory name matches, Doccupine automatically assigns the files to that section and strips the directory from the URL.\n\n```text\ndocs/\n index.mdx\n getting-started.mdx\n platform/\n index.mdx -> /platform\n auth.mdx -> /platform/auth\n```\n\nWhere `platform/index.mdx` has:\n\n```text\n---\ntitle: \"Platform\"\nsection: \"Platform\"\nsectionOrder: 1\ncategory: \"Overview\"\n---\n```\n\nThe directory `platform/` matches the section slug `platform`, so it is stripped. `platform/index.mdx` serves at `/platform/` and `platform/auth.mdx` serves at `/platform/auth`.\n\n<Callout type=\"info\">\n Once a section exists, any file placed in a matching directory is automatically assigned to it - even without a `section` field in its own frontmatter. Only the first file needs `section` and `sectionOrder` to create the section. After that, the directory does the work.\n</Callout>\n\nFiles at the root level with a `section` field work too - they keep their full slug under the section prefix.\n\n### Section index pages\nIf a section has no index page (no file at its root URL), Doccupine generates a redirect to the first page in that section, sorted by `categoryOrder` then `order`.\n\n<Callout type=\"note\">\n You can override the auto-redirect by creating an `index.mdx` in the section's directory.\n</Callout>\n\n### Flat file example\nYou can also keep all files at the root and rely purely on frontmatter:\n\n```text\n---\ntitle: \"Authentication\"\nsection: \"API Reference\"\nsectionOrder: 2\ncategory: \"Auth\"\ncategoryOrder: 1\norder: 1\n---\n```\n\nThis page would be served at `/api-reference/authentication`.\n\n## Explicit sections with sections.json\nFor full control over slugs, create a `sections.json` file at your project root (the same folder where you run `npx doccupine`).\n\n### Minimal example\n\n```json\n[\n { \"label\": \"Docs\", \"slug\": \"\" },\n { \"label\": \"Platform\", \"slug\": \"platform\" }\n]\n```\n\nThis defines two sections. Pages are assigned automatically:\n- Files in a `platform/` directory belong to the \"Platform\" section (directory name matches slug).\n- Files with `section: \"Platform\"` in their frontmatter also belong to it.\n- Everything else stays in the root \"Docs\" section.\n\nNo `directory` field is needed when the directory name already matches the section slug.\n\n### Example with explicit directories\nWhen the directory name differs from the slug, use the `directory` field to map them:\n\n```json\n[\n { \"label\": \"Guides\", \"slug\": \"\", \"directory\": \"guides\" },\n { \"label\": \"API Reference\", \"slug\": \"api\", \"directory\": \"api-reference\" },\n { \"label\": \"SDKs\", \"slug\": \"sdks\", \"directory\": \"sdks\" }\n]\n```\n\n### Fields\n- **label**: The display name shown in the section bar.\n- **slug**: The URL prefix for this section. Use an empty string `\"\"` for the default section that serves at the root.\n- **directory** (optional): The subdirectory under your watch directory that contains this section's MDX files. Only needed when the directory name differs from the slug.\n\n### Directory structure example\nWith the explicit directory config above and a watch directory of `docs`, your files would look like:\n\n```text\ndocs/\n guides/\n index.mdx\n getting-started.mdx\n api-reference/\n authentication.mdx\n endpoints.mdx\n sdks/\n javascript.mdx\n python.mdx\n```\n\n## Section navigation\nEach section builds its own sidebar from the pages that belong to it. By default, pages are grouped by `category` and sorted by `categoryOrder` and `order` from frontmatter.\n\nFor explicit control, use `navigation.json` with the object format to define per-section navigation:\n\n```json\n{\n \"\": [\n { \"label\": \"General\", \"links\": [{ \"slug\": \"\", \"title\": \"Getting Started\" }] }\n ],\n \"platform\": [\n { \"label\": \"API\", \"links\": [{ \"slug\": \"platform/auth\", \"title\": \"Auth\" }] }\n ]\n}\n```\n\nKeys are section slugs. The root section uses `\"\"`. Sections without a key fall back to auto-generated navigation. See the Navigation page for the full format.\n\n## How pages are assigned to sections\nDoccupine checks these rules in order and uses the first match:\n\n1. **Explicit directory** - the file is inside a directory listed in a section's `directory` field.\n2. **Directory matches slug** - the file's parent directory matches a section slug (e.g. files in `platform/` match a section with `slug: \"platform\"`).\n3. **Frontmatter section field** - the file's `section` value matches a section label.\n4. **No match** - the page stays at the root.\n\n## Precedence for section discovery\n1. **sections.json exists** - Doccupine uses it to define available sections.\n2. **No sections.json but pages have `section` frontmatter** - Doccupine auto-discovers sections from the frontmatter. Sections update live as you add or remove the `section` field from files.\n3. **Neither** - No section bar appears. The site works exactly as before.\n\n## URL structure\nPages in the default section (with `slug: \"\"`) serve at the root:\n\n- Default section: `/getting-started`, `/installation`\n- Other sections: `/api/authentication`, `/sdks/javascript`\n\n<Callout type=\"info\">\n When a file is in a directory that matches its section slug, the directory is stripped so it doesn't appear twice. For example, `platform/auth.mdx` in the \"Platform\" section serves at `/platform/auth`, not `/platform/platform/auth`.\n</Callout>\n\n## sections.json vs navigation.json\nThese two config files serve different purposes and complement each other:\n\n- **sections.json** defines which sections exist - their labels, slugs, directory mappings, and order in the tab bar.\n- **navigation.json** controls the sidebar within each section - page ordering and grouping.\n\nYou can use either one independently. `sections.json` without `navigation.json` gives you sections with auto-generated sidebars. `navigation.json` without `sections.json` gives you custom sidebar ordering with frontmatter-discovered sections (or no sections at all).\n\n## Tips\n- **Start simple**: Add `section` and `sectionOrder` to a few pages to try it out. No config files needed.\n- **Use directories**: Organize each section's files in a directory that matches the section slug for clean URLs and a tidy file tree.\n- **Rename the default tab**: Add `sectionLabel: \"Your Label\"` to your `index.mdx` frontmatter. Defaults to \"Docs\" if omitted.\n- **Switch to sections.json**: When you need custom slugs or directory mappings that don't match section names, `sections.json` gives full control.\n- **Per-section navigation**: Use the object format in `navigation.json` to define custom sidebar ordering for specific sections.\n- **Independent sidebars**: Each section has its own sidebar. Previous/next navigation stays within the active section.";
1
+ export declare const sectionsMdxTemplate = "---\ntitle: \"Sections\"\ndescription: \"Split your documentation into top-level sections with independent sidebars.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 3\n---\n# Sections\nSections let you divide your documentation into separate top-level areas - for example \"Guides\", \"API Reference\", and \"SDKs\". Each section gets its own sidebar and appears as a horizontal tab bar below the site header.\n\n<Callout type=\"note\">\n Sections are entirely opt-in. If you don't configure them, nothing changes - your site works exactly as before with a single flat navigation.\n</Callout>\n\n## Automatic sections (frontmatter)\nThe simplest way to add sections is through page frontmatter. Add a `section` field to group pages, and an optional `sectionOrder` to control the order of sections in the bar.\n\n### Frontmatter fields\n- **section**: The display name for the section this page belongs to (e.g. \"API Reference\").\n- **sectionOrder**: Controls the position of the section in the bar. Lower numbers appear first.\n\nThe section slug is derived automatically from the label - lowercased with spaces replaced by hyphens. So \"API Reference\" becomes `api-reference`.\n\nPages without a `section` field stay at the root URL and appear under a default tab labeled \"Docs\". You can rename this tab with the `sectionLabel` field on your `index.mdx`:\n\n```text\n---\ntitle: \"Welcome\"\nsectionLabel: \"Guides\"\n---\n```\n\n### Directory-based organization\nYou can organize each section's files in a subdirectory that matches the section slug. When the directory name matches, Doccupine automatically assigns the files to that section and strips the directory from the URL.\n\n```text\ndocs/\n index.mdx\n getting-started.mdx\n platform/\n index.mdx -> /platform\n auth.mdx -> /platform/auth\n```\n\nWhere `platform/index.mdx` has:\n\n```text\n---\ntitle: \"Platform Overview\"\nsection: \"Platform\"\nsectionOrder: 1\ncategory: \"Getting Started\"\n---\n```\n\nThe directory `platform/` matches the section slug `platform`, so it is stripped. `platform/index.mdx` serves at `/platform/` and `platform/auth.mdx` serves at `/platform/auth`.\n\n<Callout type=\"info\">\n Once a section exists, any file placed in a matching directory is automatically assigned to it - even without a `section` field in its own frontmatter. Only the first file needs `section` and `sectionOrder` to create the section. After that, the directory does the work.\n</Callout>\n\nFiles at the root level with a `section` field work too - they keep their full slug under the section prefix.\n\n### Section index pages\nIf a section has no index page (no file at its root URL), Doccupine generates a redirect to the first page in that section, sorted by `categoryOrder` then `order`.\n\n<Callout type=\"note\">\n You can override the auto-redirect by creating an `index.mdx` in the section's directory.\n</Callout>\n\n### Flat file example\nYou can also keep all files at the root and rely purely on frontmatter:\n\n```text\n---\ntitle: \"Authentication\"\nsection: \"API Reference\"\nsectionOrder: 2\ncategory: \"Auth\"\ncategoryOrder: 1\norder: 1\n---\n```\n\nThis page would be served at `/api-reference/authentication`.\n\n## Explicit sections with sections.json\nFor full control over slugs, create a `sections.json` file at your project root (the same folder where you run `npx doccupine`).\n\n### Minimal example\n\n```json\n[\n { \"label\": \"Docs\", \"slug\": \"\" },\n { \"label\": \"Platform\", \"slug\": \"platform\" }\n]\n```\n\nThis defines two sections. Pages are assigned automatically:\n- Files in a `platform/` directory belong to the \"Platform\" section (directory name matches slug).\n- Files with `section: \"Platform\"` in their frontmatter also belong to it.\n- Everything else stays in the root \"Docs\" section.\n\nNo `directory` field is needed when the directory name already matches the section slug.\n\n### Example with explicit directories\nWhen the directory name differs from the slug, use the `directory` field to map them:\n\n```json\n[\n { \"label\": \"Guides\", \"slug\": \"\", \"directory\": \"guides\" },\n { \"label\": \"API Reference\", \"slug\": \"api\", \"directory\": \"api-reference\" },\n { \"label\": \"SDKs\", \"slug\": \"sdks\", \"directory\": \"sdks\" }\n]\n```\n\n### Fields\n- **label**: The display name shown in the section bar.\n- **slug**: The URL prefix for this section. Use an empty string `\"\"` for the default section that serves at the root.\n- **directory** (optional): The subdirectory under your watch directory that contains this section's MDX files. Only needed when the directory name differs from the slug.\n\n### Directory structure example\nWith the explicit directory config above and a watch directory of `docs`, your files would look like:\n\n```text\ndocs/\n guides/\n index.mdx\n getting-started.mdx\n api-reference/\n authentication.mdx\n endpoints.mdx\n sdks/\n javascript.mdx\n python.mdx\n```\n\n## Section navigation\nEach section builds its own sidebar from the pages that belong to it. By default, pages are grouped by `category` and sorted by `categoryOrder` and `order` from frontmatter.\n\nFor explicit control, use `navigation.json` with the object format to define per-section navigation:\n\n```json\n{\n \"\": [\n { \"label\": \"General\", \"links\": [{ \"slug\": \"\", \"title\": \"Getting Started\" }] }\n ],\n \"platform\": [\n { \"label\": \"API\", \"links\": [{ \"slug\": \"platform/auth\", \"title\": \"Auth\" }] }\n ]\n}\n```\n\nKeys are section slugs. The root section uses `\"\"`. Sections without a key fall back to auto-generated navigation. See the Navigation page for the full format.\n\n## How pages are assigned to sections\nDoccupine checks these rules in order and uses the first match:\n\n1. **Explicit directory** - the file is inside a directory listed in a section's `directory` field.\n2. **Directory matches slug** - the file's parent directory matches a section slug (e.g. files in `platform/` match a section with `slug: \"platform\"`).\n3. **Frontmatter section field** - the file's `section` value matches a section label.\n4. **No match** - the page stays at the root.\n\n## Precedence for section discovery\n1. **sections.json exists** - Doccupine uses it to define available sections.\n2. **No sections.json but pages have `section` frontmatter** - Doccupine auto-discovers sections from the frontmatter. Sections update live as you add or remove the `section` field from files.\n3. **Neither** - No section bar appears. The site works exactly as before.\n\n## URL structure\nPages in the default section (with `slug: \"\"`) serve at the root:\n\n- Default section: `/getting-started`, `/installation`\n- Other sections: `/api/authentication`, `/sdks/javascript`\n\n<Callout type=\"info\">\n When a file is in a directory that matches its section slug, the directory is stripped so it doesn't appear twice. For example, `platform/auth.mdx` in the \"Platform\" section serves at `/platform/auth`, not `/platform/platform/auth`.\n</Callout>\n\n## sections.json vs navigation.json\nThese two config files serve different purposes and complement each other:\n\n- **sections.json** defines which sections exist - their labels, slugs, directory mappings, and order in the tab bar.\n- **navigation.json** controls the sidebar within each section - page ordering and grouping.\n\nYou can use either one independently. `sections.json` without `navigation.json` gives you sections with auto-generated sidebars. `navigation.json` without `sections.json` gives you custom sidebar ordering with frontmatter-discovered sections (or no sections at all).\n\n## Tips\n- **Start simple**: Add `section` and `sectionOrder` to a few pages to try it out. No config files needed.\n- **Use directories**: Organize each section's files in a directory that matches the section slug for clean URLs and a tidy file tree.\n- **Rename the default tab**: Add `sectionLabel: \"Your Label\"` to your `index.mdx` frontmatter. Defaults to \"Docs\" if omitted.\n- **Switch to sections.json**: When you need custom slugs or directory mappings that don't match section names, `sections.json` gives full control.\n- **Per-section navigation**: Use the object format in `navigation.json` to define custom sidebar ordering for specific sections.\n- **Independent sidebars**: Each section has its own sidebar. Previous/next navigation stays within the active section.";
@@ -47,10 +47,10 @@ Where \`platform/index.mdx\` has:
47
47
 
48
48
  \`\`\`text
49
49
  ---
50
- title: "Platform"
50
+ title: "Platform Overview"
51
51
  section: "Platform"
52
52
  sectionOrder: 1
53
- category: "Overview"
53
+ category: "Getting Started"
54
54
  ---
55
55
  \`\`\`
56
56
 
@@ -1 +1 @@
1
- export declare const stepsMdxTemplate = "---\ntitle: \"Steps\"\ndescription: \"Guide readers step-by-step using the Steps component.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 13\n---\n# Steps\nGuide readers step-by-step using the Steps component.\n\nThe Steps component is perfect for organizing procedures or workflows in a clear sequence. Include as many individual steps as necessary to outline your process.\n\n## Steps Usage\nYou can use the `Steps` component to create a step-by-step guide. Each step is represented by a `Step` component, which includes a title and content.\n\n```mdx\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n```\n\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n\n## Properties\n\n<Field value=\"title\" type=\"string\" required>\n The title of the step.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the step.\n</Field>\n";
1
+ export declare const stepsMdxTemplate = "---\ntitle: \"Steps\"\ndescription: \"Guide readers step-by-step using the Steps component.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 13\n---\n# Steps\nGuide readers step-by-step using the Steps component.\n\nThe Steps component is perfect for organizing procedures or workflows in a clear sequence. Include as many individual steps as necessary to outline your process.\n\n## Steps Usage\nYou can use the `Steps` component to create a step-by-step guide. Each step is represented by a `Step` component, which includes a title and content.\n\n```mdx\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n```\n\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n\n## Properties\n\n<Field value=\"title\" type=\"string\" required>\n The title of the step.\n</Field>\n\n<Field value=\"icon\" type=\"string\">\n A [Lucide](https://lucide.dev/icons) icon name shown next to the step title.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the step.\n</Field>\n";
@@ -50,6 +50,10 @@ You can use the \`Steps\` component to create a step-by-step guide. Each step is
50
50
  The title of the step.
51
51
  </Field>
52
52
 
53
+ <Field value="icon" type="string">
54
+ A [Lucide](https://lucide.dev/icons) icon name shown next to the step title.
55
+ </Field>
56
+
53
57
  <Field value="children" type="node" required>
54
58
  The content of the step.
55
59
  </Field>
@@ -1 +1 @@
1
- export declare const tabsMdxTemplate = "---\ntitle: \"Tabs\"\ndescription: \"Use the Tabs component to display different content sections in a switchable panel layout.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 5\n---\n# Tabs\nUse the Tabs component to display different content sections in a switchable panel layout.\n\nTabs are useful for grouping related information while keeping the interface tidy. You can create as many tabs as needed, and each one can hold other components, text, or code snippets.\n\n## Tabs Usage\nYou can use the Tabs component directly within your MDX files without any import. The following example shows a basic usage:\n\n~~~mdx\n<Tabs>\n <TabContent title=\"First tab\">\n \u261D\uFE0F This is the content shown only when the first tab is active.\n\n Tabs can include all kinds of components. For example, a simple Java program:\n ```java\n class HelloWorld {\n public static void main(String[] args) {\n System.out.println(\"Hello, World!\");\n }\n }\n ```\n </TabContent>\n <TabContent title=\"Second tab\">\n \u270C\uFE0F Content inside this second tab is separate from the first.\n </TabContent>\n <TabContent title=\"Third tab\">\n \uD83D\uDCAA This third tab contains its own unique content.\n </TabContent>\n</Tabs>\n~~~\n\n<Tabs>\n <TabContent title=\"First tab\">\n \u261D\uFE0F This is the content shown only when the first tab is active.\n\n Tabs can include all kinds of components. For example, a simple Java program:\n ```java\n class HelloWorld {\n public static void main(String[] args) {\n System.out.println(\"Hello, World!\");\n }\n }\n ```\n </TabContent>\n <TabContent title=\"Second tab\" icon=\"leaf\">\n \u270C\uFE0F Content inside this second tab is separate from the first.\n </TabContent>\n <TabContent title=\"Third tab\">\n \uD83D\uDCAA This third tab contains its own unique content.\n </TabContent>\n</Tabs>\n\n## Properties\n\n<Field value=\"title\" type=\"string\">\n The title of the tab.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the tabs.\n</Field>";
1
+ export declare const tabsMdxTemplate = "---\ntitle: \"Tabs\"\ndescription: \"Use the Tabs component to display different content sections in a switchable panel layout.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 5\n---\n# Tabs\nUse the Tabs component to display different content sections in a switchable panel layout.\n\nTabs are useful for grouping related information while keeping the interface tidy. You can create as many tabs as needed, and each one can hold other components, text, or code snippets.\n\n## Tabs Usage\nYou can use the Tabs component directly within your MDX files without any import. The following example shows a basic usage:\n\n~~~mdx\n<Tabs>\n <TabContent title=\"First tab\">\n \u261D\uFE0F This is the content shown only when the first tab is active.\n\n Tabs can include all kinds of components. For example, a simple Java program:\n ```java\n class HelloWorld {\n public static void main(String[] args) {\n System.out.println(\"Hello, World!\");\n }\n }\n ```\n </TabContent>\n <TabContent title=\"Second tab\">\n \u270C\uFE0F Content inside this second tab is separate from the first.\n </TabContent>\n <TabContent title=\"Third tab\">\n \uD83D\uDCAA This third tab contains its own unique content.\n </TabContent>\n</Tabs>\n~~~\n\n<Tabs>\n <TabContent title=\"First tab\">\n \u261D\uFE0F This is the content shown only when the first tab is active.\n\n Tabs can include all kinds of components. For example, a simple Java program:\n ```java\n class HelloWorld {\n public static void main(String[] args) {\n System.out.println(\"Hello, World!\");\n }\n }\n ```\n </TabContent>\n <TabContent title=\"Second tab\">\n \u270C\uFE0F Content inside this second tab is separate from the first.\n </TabContent>\n <TabContent title=\"Third tab\">\n \uD83D\uDCAA This third tab contains its own unique content.\n </TabContent>\n</Tabs>\n\n## Properties\n\n<Field value=\"title\" type=\"string\">\n The title of the tab.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the tabs.\n</Field>";
@@ -50,7 +50,7 @@ You can use the Tabs component directly within your MDX files without any import
50
50
  }
51
51
  \`\`\`
52
52
  </TabContent>
53
- <TabContent title="Second tab" icon="leaf">
53
+ <TabContent title="Second tab">
54
54
  ✌️ Content inside this second tab is separate from the first.
55
55
  </TabContent>
56
56
  <TabContent title="Third tab">
@@ -10,10 +10,10 @@ export const packageJsonTemplate = JSON.stringify({
10
10
  format: "prettier --write .",
11
11
  },
12
12
  dependencies: {
13
- "@langchain/anthropic": "^1.3.18",
14
- "@langchain/core": "^1.1.26",
15
- "@langchain/google-genai": "^2.1.19",
16
- "@langchain/openai": "^1.2.8",
13
+ "@langchain/anthropic": "^1.3.19",
14
+ "@langchain/core": "^1.1.27",
15
+ "@langchain/google-genai": "^2.1.20",
16
+ "@langchain/openai": "^1.2.9",
17
17
  "@mdx-js/react": "^3.1.1",
18
18
  "@modelcontextprotocol/sdk": "^1.26.0",
19
19
  "cherry-styled-components": "^0.1.12",
@@ -1 +1 @@
1
- export declare const llmTypesTemplate = "export type LLMProvider = \"openai\" | \"anthropic\" | \"google\";\n\nexport interface LLMConfig {\n provider: LLMProvider;\n chatModel: string;\n embeddingModel: string;\n temperature: number;\n}\n\nexport interface ProviderModels {\n chat: string;\n embedding: string;\n}\n\nexport type ProviderDefaults = Record<LLMProvider, ProviderModels>;\n";
1
+ export declare const llmTypesTemplate = "export type LLMProvider = \"openai\" | \"anthropic\" | \"google\";\n\nexport interface LLMConfig {\n provider: LLMProvider;\n chatModel: string;\n embeddingModel: string;\n temperature: number;\n}\n\ninterface ProviderModels {\n chat: string;\n embedding: string;\n}\n\nexport type ProviderDefaults = Record<LLMProvider, ProviderModels>;\n";
@@ -7,7 +7,7 @@ export interface LLMConfig {
7
7
  temperature: number;
8
8
  }
9
9
 
10
- export interface ProviderModels {
10
+ interface ProviderModels {
11
11
  chat: string;
12
12
  embedding: string;
13
13
  }
@@ -1 +1 @@
1
- export declare const mcpServerTemplate = "import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n listDocs,\n getDoc,\n getAllDocsChunks,\n DOCS_TOOLS,\n} from \"@/services/mcp/tools\";\nimport { getLLMConfig, createEmbeddings } from \"@/services/llm\";\nimport type { DocsChunk } from \"@/services/mcp/types\";\n\n/**\n * In-memory cache for document embeddings.\n * Built once at server startup since docs are static.\n */\nlet docsIndex: {\n ready: boolean;\n building: boolean;\n chunks: (DocsChunk & { embedding: number[] })[];\n} = {\n ready: false,\n building: false,\n chunks: [],\n};\n\n/** Resolves when the initial index build completes */\nlet indexReady: Promise<void> | null = null;\n\n/**\n * Cosine similarity between two vectors\n */\nfunction cosineSim(a: number[], b: number[]): number {\n let dot = 0,\n na = 0,\n nb = 0;\n for (let i = 0; i < a.length; i++) {\n const x = a[i];\n const y = b[i];\n dot += x * y;\n na += x * x;\n nb += y * y;\n }\n if (na === 0 || nb === 0) return 0;\n return dot / (Math.sqrt(na) * Math.sqrt(nb));\n}\n\n/**\n * Build or rebuild the documentation index\n */\nexport async function buildDocsIndex(force = false): Promise<void> {\n if (docsIndex.building) return;\n if (docsIndex.ready && !force) return;\n\n docsIndex.building = true;\n try {\n const chunks = await getAllDocsChunks();\n\n if (chunks.length === 0) {\n docsIndex.chunks = [];\n docsIndex.ready = true;\n return;\n }\n\n const config = getLLMConfig();\n const embeddings = createEmbeddings(config);\n\n // Process embeddings in small batches to avoid exceeding token limits\n const BATCH_SIZE = 10;\n const texts = chunks.map((c) => c.text);\n const vectors: number[][] = [];\n\n for (let i = 0; i < texts.length; i += BATCH_SIZE) {\n const batch = texts.slice(i, i + BATCH_SIZE);\n const batchVectors = await embeddings.embedDocuments(batch);\n vectors.push(...batchVectors);\n }\n\n docsIndex.chunks = chunks.map((c, i) => ({\n ...c,\n embedding: vectors[i],\n }));\n docsIndex.ready = true;\n } catch (error) {\n // Reset so the next call to ensureDocsIndex retries\n indexReady = null;\n throw error;\n } finally {\n docsIndex.building = false;\n }\n}\n\n/**\n * Ensure the docs index is ready.\n * On first call, triggers the build; subsequent calls wait for the same promise.\n */\nexport async function ensureDocsIndex(force = false): Promise<void> {\n if (force) {\n // Wait for any in-flight build before starting a forced rebuild\n if (docsIndex.building && indexReady) {\n await indexReady.catch(() => {});\n }\n docsIndex.ready = false;\n docsIndex.chunks = [];\n indexReady = buildDocsIndex(true);\n return indexReady;\n }\n if (!indexReady) {\n indexReady = buildDocsIndex();\n }\n return indexReady;\n}\n\n// Eagerly start building the index on server startup (docs are static)\nindexReady = buildDocsIndex();\n\n/** Cached embeddings instance for search queries */\nlet cachedEmbeddings: ReturnType<typeof createEmbeddings> | null = null;\n\nfunction getEmbeddings() {\n if (!cachedEmbeddings) {\n cachedEmbeddings = createEmbeddings(getLLMConfig());\n }\n return cachedEmbeddings;\n}\n\n/**\n * Search documents using semantic similarity\n */\nexport async function searchDocs(\n query: string,\n limit = 6,\n): Promise<{ chunk: DocsChunk; score: number }[]> {\n await ensureDocsIndex();\n\n const queryVector = await getEmbeddings().embedQuery(query);\n\n const scored = docsIndex.chunks\n .map((c) => ({\n chunk: { id: c.id, text: c.text, path: c.path, uri: c.uri },\n score: cosineSim(queryVector, c.embedding),\n }))\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n\n return scored;\n}\n\n/**\n * Get the current index status\n */\nexport function getIndexStatus(): { ready: boolean; chunkCount: number } {\n return {\n ready: docsIndex.ready,\n chunkCount: docsIndex.chunks.length,\n };\n}\n\n/**\n * Create and configure the MCP server with documentation tools\n */\nexport function createMCPServer(): McpServer {\n const server = new McpServer({\n name: \"docs-server\",\n version: \"1.0.0\",\n });\n\n // Register the search_docs tool\n server.tool(\n \"search_docs\",\n DOCS_TOOLS[0].description,\n {\n query: z\n .string()\n .describe(\"The search query to find relevant documentation\"),\n limit: z\n .number()\n .optional()\n .describe(\"Maximum number of results to return (default: 6)\"),\n },\n async ({ query, limit }) => {\n const results = await searchDocs(query, limit ?? 6);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(\n results.map(({ chunk, score }) => ({\n path: chunk.path,\n uri: chunk.uri,\n score: score.toFixed(3),\n text: chunk.text,\n })),\n null,\n 2,\n ),\n },\n ],\n };\n },\n );\n\n // Register the get_doc tool\n server.tool(\n \"get_doc\",\n DOCS_TOOLS[1].description,\n {\n path: z.string().describe(\"The file path to the documentation page\"),\n },\n async ({ path }) => {\n const doc = await getDoc({ path });\n if (!doc) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: \"Document not found\" }),\n },\n ],\n isError: true,\n };\n }\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(doc, null, 2),\n },\n ],\n };\n },\n );\n\n // Register the list_docs tool\n server.tool(\n \"list_docs\",\n DOCS_TOOLS[2].description,\n {\n directory: z\n .string()\n .optional()\n .describe(\"Optional directory to filter results\"),\n },\n async ({ directory }) => {\n const docs = await listDocs({ directory });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(\n docs.map((d) => ({\n name: d.name,\n path: d.path,\n uri: d.uri,\n })),\n null,\n 2,\n ),\n },\n ],\n };\n },\n );\n\n // Register documentation as resources\n server.resource(\"docs://list\", \"docs://list\", async () => {\n const docs = await listDocs();\n return {\n contents: [\n {\n uri: \"docs://list\",\n text: JSON.stringify(\n docs.map((d) => ({ name: d.name, path: d.path, uri: d.uri })),\n null,\n 2,\n ),\n },\n ],\n };\n });\n\n return server;\n}\n";
1
+ export declare const mcpServerTemplate = "import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n listDocs,\n getDoc,\n getAllDocsChunks,\n DOCS_TOOLS,\n} from \"@/services/mcp/tools\";\nimport { getLLMConfig, createEmbeddings } from \"@/services/llm\";\nimport type { DocsChunk } from \"@/services/mcp/types\";\n\n/**\n * In-memory cache for document embeddings.\n * Built once at server startup since docs are static.\n */\nlet docsIndex: {\n ready: boolean;\n building: boolean;\n chunks: (DocsChunk & { embedding: number[] })[];\n} = {\n ready: false,\n building: false,\n chunks: [],\n};\n\n/** Resolves when the initial index build completes */\nlet indexReady: Promise<void> | null = null;\n\n/**\n * Cosine similarity between two vectors\n */\nfunction cosineSim(a: number[], b: number[]): number {\n let dot = 0,\n na = 0,\n nb = 0;\n for (let i = 0; i < a.length; i++) {\n const x = a[i];\n const y = b[i];\n dot += x * y;\n na += x * x;\n nb += y * y;\n }\n if (na === 0 || nb === 0) return 0;\n return dot / (Math.sqrt(na) * Math.sqrt(nb));\n}\n\n/**\n * Build or rebuild the documentation index\n */\nasync function buildDocsIndex(force = false): Promise<void> {\n if (docsIndex.building) return;\n if (docsIndex.ready && !force) return;\n\n docsIndex.building = true;\n try {\n const chunks = await getAllDocsChunks();\n\n if (chunks.length === 0) {\n docsIndex.chunks = [];\n docsIndex.ready = true;\n return;\n }\n\n const config = getLLMConfig();\n const embeddings = createEmbeddings(config);\n\n // Process embeddings in small batches to avoid exceeding token limits\n const BATCH_SIZE = 10;\n const texts = chunks.map((c) => c.text);\n const vectors: number[][] = [];\n\n for (let i = 0; i < texts.length; i += BATCH_SIZE) {\n const batch = texts.slice(i, i + BATCH_SIZE);\n const batchVectors = await embeddings.embedDocuments(batch);\n vectors.push(...batchVectors);\n }\n\n docsIndex.chunks = chunks.map((c, i) => ({\n ...c,\n embedding: vectors[i],\n }));\n docsIndex.ready = true;\n } catch (error) {\n // Reset so the next call to ensureDocsIndex retries\n indexReady = null;\n throw error;\n } finally {\n docsIndex.building = false;\n }\n}\n\n/**\n * Ensure the docs index is ready.\n * On first call, triggers the build; subsequent calls wait for the same promise.\n */\nexport async function ensureDocsIndex(force = false): Promise<void> {\n if (force) {\n // Wait for any in-flight build before starting a forced rebuild\n if (docsIndex.building && indexReady) {\n await indexReady.catch(() => {});\n }\n docsIndex.ready = false;\n docsIndex.chunks = [];\n indexReady = buildDocsIndex(true);\n return indexReady;\n }\n if (!indexReady) {\n indexReady = buildDocsIndex();\n }\n return indexReady;\n}\n\n// Eagerly start building the index on server startup (docs are static)\nindexReady = buildDocsIndex();\n\n/** Cached embeddings instance for search queries */\nlet cachedEmbeddings: ReturnType<typeof createEmbeddings> | null = null;\n\nfunction getEmbeddings() {\n if (!cachedEmbeddings) {\n cachedEmbeddings = createEmbeddings(getLLMConfig());\n }\n return cachedEmbeddings;\n}\n\n/**\n * Search documents using semantic similarity\n */\nexport async function searchDocs(\n query: string,\n limit = 6,\n): Promise<{ chunk: DocsChunk; score: number }[]> {\n await ensureDocsIndex();\n\n const queryVector = await getEmbeddings().embedQuery(query);\n\n const scored = docsIndex.chunks\n .map((c) => ({\n chunk: { id: c.id, text: c.text, path: c.path, uri: c.uri },\n score: cosineSim(queryVector, c.embedding),\n }))\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n\n return scored;\n}\n\n/**\n * Get the current index status\n */\nexport function getIndexStatus(): { ready: boolean; chunkCount: number } {\n return {\n ready: docsIndex.ready,\n chunkCount: docsIndex.chunks.length,\n };\n}\n\n/**\n * Create and configure the MCP server with documentation tools\n */\nexport function createMCPServer(): McpServer {\n const server = new McpServer({\n name: \"docs-server\",\n version: \"1.0.0\",\n });\n\n // Register the search_docs tool\n server.tool(\n \"search_docs\",\n DOCS_TOOLS[0].description,\n {\n query: z\n .string()\n .describe(\"The search query to find relevant documentation\"),\n limit: z\n .number()\n .optional()\n .describe(\"Maximum number of results to return (default: 6)\"),\n },\n async ({ query, limit }) => {\n const results = await searchDocs(query, limit ?? 6);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(\n results.map(({ chunk, score }) => ({\n path: chunk.path,\n uri: chunk.uri,\n score: score.toFixed(3),\n text: chunk.text,\n })),\n null,\n 2,\n ),\n },\n ],\n };\n },\n );\n\n // Register the get_doc tool\n server.tool(\n \"get_doc\",\n DOCS_TOOLS[1].description,\n {\n path: z.string().describe(\"The file path to the documentation page\"),\n },\n async ({ path }) => {\n const doc = await getDoc({ path });\n if (!doc) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: \"Document not found\" }),\n },\n ],\n isError: true,\n };\n }\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(doc, null, 2),\n },\n ],\n };\n },\n );\n\n // Register the list_docs tool\n server.tool(\n \"list_docs\",\n DOCS_TOOLS[2].description,\n {\n directory: z\n .string()\n .optional()\n .describe(\"Optional directory to filter results\"),\n },\n async ({ directory }) => {\n const docs = await listDocs({ directory });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(\n docs.map((d) => ({\n name: d.name,\n path: d.path,\n uri: d.uri,\n })),\n null,\n 2,\n ),\n },\n ],\n };\n },\n );\n\n // Register documentation as resources\n server.resource(\"docs://list\", \"docs://list\", async () => {\n const docs = await listDocs();\n return {\n contents: [\n {\n uri: \"docs://list\",\n text: JSON.stringify(\n docs.map((d) => ({ name: d.name, path: d.path, uri: d.uri })),\n null,\n 2,\n ),\n },\n ],\n };\n });\n\n return server;\n}\n";
@@ -47,7 +47,7 @@ function cosineSim(a: number[], b: number[]): number {
47
47
  /**
48
48
  * Build or rebuild the documentation index
49
49
  */
50
- export async function buildDocsIndex(force = false): Promise<void> {
50
+ async function buildDocsIndex(force = false): Promise<void> {
51
51
  if (docsIndex.building) return;
52
52
  if (docsIndex.ready && !force) return;
53
53