doccupine 0.0.62 → 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 (170) hide show
  1. package/README.md +5 -4
  2. package/dist/index.d.ts +1 -3
  3. package/dist/index.js +46 -329
  4. package/dist/lib/config-manager.d.ts +12 -0
  5. package/dist/lib/config-manager.js +75 -0
  6. package/dist/lib/constants.d.ts +5 -0
  7. package/dist/lib/constants.js +5 -0
  8. package/dist/lib/layout.d.ts +30 -0
  9. package/dist/lib/layout.js +184 -0
  10. package/dist/lib/metadata.d.ts +11 -0
  11. package/dist/lib/metadata.js +52 -0
  12. package/dist/lib/structures.d.ts +2 -0
  13. package/dist/lib/structures.js +210 -0
  14. package/dist/lib/types.d.ts +30 -0
  15. package/dist/lib/types.js +1 -0
  16. package/dist/lib/utils.d.ts +4 -0
  17. package/dist/lib/utils.js +40 -0
  18. package/dist/metadata.d.ts +11 -0
  19. package/dist/metadata.js +52 -0
  20. package/dist/templates/app/layout.js +8 -7
  21. package/dist/templates/app/not-found.d.ts +1 -1
  22. package/dist/templates/app/not-found.js +3 -2
  23. package/dist/templates/app/theme.d.ts +3 -1
  24. package/dist/templates/app/theme.js +17 -15
  25. package/dist/templates/components/Chat.d.ts +1 -1
  26. package/dist/templates/components/Chat.js +257 -160
  27. package/dist/templates/components/DocsSideBar.d.ts +1 -1
  28. package/dist/templates/components/DocsSideBar.js +34 -11
  29. package/dist/templates/components/SectionNavProvider.d.ts +1 -1
  30. package/dist/templates/components/SectionNavProvider.js +2 -1
  31. package/dist/templates/components/SideBar.d.ts +1 -1
  32. package/dist/templates/components/SideBar.js +12 -2
  33. package/dist/templates/components/layout/Accordion.d.ts +1 -1
  34. package/dist/templates/components/layout/Accordion.js +1 -1
  35. package/dist/templates/components/layout/ActionBar.d.ts +1 -1
  36. package/dist/templates/components/layout/ActionBar.js +15 -60
  37. package/dist/templates/components/layout/Callout.d.ts +1 -1
  38. package/dist/templates/components/layout/Callout.js +1 -1
  39. package/dist/templates/components/layout/Card.d.ts +1 -1
  40. package/dist/templates/components/layout/Card.js +26 -7
  41. package/dist/templates/components/layout/Code.d.ts +1 -1
  42. package/dist/templates/components/layout/Code.js +0 -7
  43. package/dist/templates/components/layout/Columns.d.ts +1 -1
  44. package/dist/templates/components/layout/Columns.js +1 -1
  45. package/dist/templates/components/layout/DocsComponents.d.ts +1 -1
  46. package/dist/templates/components/layout/DocsComponents.js +44 -13
  47. package/dist/templates/components/layout/DocsNavigation.d.ts +1 -1
  48. package/dist/templates/components/layout/DocsNavigation.js +3 -2
  49. package/dist/templates/components/layout/Field.d.ts +1 -1
  50. package/dist/templates/components/layout/Field.js +1 -1
  51. package/dist/templates/components/layout/Footer.d.ts +1 -1
  52. package/dist/templates/components/layout/Footer.js +28 -6
  53. package/dist/templates/components/layout/Header.d.ts +1 -1
  54. package/dist/templates/components/layout/Header.js +10 -12
  55. package/dist/templates/components/layout/SharedStyles.d.ts +1 -1
  56. package/dist/templates/components/layout/SharedStyles.js +31 -730
  57. package/dist/templates/components/layout/StaticLinks.d.ts +1 -1
  58. package/dist/templates/components/layout/StaticLinks.js +22 -21
  59. package/dist/templates/components/layout/Steps.d.ts +1 -1
  60. package/dist/templates/components/layout/Steps.js +7 -2
  61. package/dist/templates/components/layout/Tabs.d.ts +1 -1
  62. package/dist/templates/components/layout/Tabs.js +2 -2
  63. package/dist/templates/components/layout/Update.d.ts +1 -1
  64. package/dist/templates/components/layout/Update.js +1 -1
  65. package/dist/templates/constants.d.ts +5 -0
  66. package/dist/templates/constants.js +5 -0
  67. package/dist/templates/env.example.d.ts +1 -1
  68. package/dist/templates/env.example.js +10 -8
  69. package/dist/templates/mdx/accordion.mdx.d.ts +1 -1
  70. package/dist/templates/mdx/accordion.mdx.js +1 -1
  71. package/dist/templates/mdx/ai-assistant.mdx.d.ts +1 -1
  72. package/dist/templates/mdx/ai-assistant.mdx.js +20 -22
  73. package/dist/templates/mdx/buttons.mdx.d.ts +1 -1
  74. package/dist/templates/mdx/buttons.mdx.js +1 -1
  75. package/dist/templates/mdx/callouts.mdx.d.ts +1 -1
  76. package/dist/templates/mdx/callouts.mdx.js +7 -3
  77. package/dist/templates/mdx/cards.mdx.d.ts +1 -1
  78. package/dist/templates/mdx/cards.mdx.js +20 -4
  79. package/dist/templates/mdx/code.mdx.d.ts +1 -1
  80. package/dist/templates/mdx/code.mdx.js +1 -1
  81. package/dist/templates/mdx/columns.mdx.d.ts +1 -1
  82. package/dist/templates/mdx/columns.mdx.js +3 -3
  83. package/dist/templates/mdx/commands.mdx.d.ts +1 -1
  84. package/dist/templates/mdx/commands.mdx.js +13 -5
  85. package/dist/templates/mdx/components.mdx.d.ts +1 -0
  86. package/dist/templates/mdx/components.mdx.js +56 -0
  87. package/dist/templates/mdx/deployment.mdx.d.ts +1 -1
  88. package/dist/templates/mdx/deployment.mdx.js +2 -2
  89. package/dist/templates/mdx/fields.mdx.d.ts +1 -1
  90. package/dist/templates/mdx/fields.mdx.js +1 -1
  91. package/dist/templates/mdx/fonts.mdx.d.ts +1 -1
  92. package/dist/templates/mdx/fonts.mdx.js +1 -1
  93. package/dist/templates/mdx/footer-links.mdx.d.ts +1 -1
  94. package/dist/templates/mdx/footer-links.mdx.js +2 -2
  95. package/dist/templates/mdx/globals.mdx.d.ts +1 -1
  96. package/dist/templates/mdx/globals.mdx.js +24 -10
  97. package/dist/templates/mdx/headers-and-text.mdx.d.ts +1 -1
  98. package/dist/templates/mdx/headers-and-text.mdx.js +1 -1
  99. package/dist/templates/mdx/icons.mdx.d.ts +1 -1
  100. package/dist/templates/mdx/icons.mdx.js +1 -1
  101. package/dist/templates/mdx/image-and-embeds.mdx.d.ts +1 -1
  102. package/dist/templates/mdx/image-and-embeds.mdx.js +4 -4
  103. package/dist/templates/mdx/index.mdx.d.ts +1 -1
  104. package/dist/templates/mdx/index.mdx.js +34 -18
  105. package/dist/templates/mdx/list-and-tables.mdx.d.ts +1 -1
  106. package/dist/templates/mdx/list-and-tables.mdx.js +7 -7
  107. package/dist/templates/mdx/media-and-assets.mdx.d.ts +1 -1
  108. package/dist/templates/mdx/media-and-assets.mdx.js +2 -2
  109. package/dist/templates/mdx/model-context-protocol.mdx.d.ts +1 -1
  110. package/dist/templates/mdx/model-context-protocol.mdx.js +8 -4
  111. package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
  112. package/dist/templates/mdx/navigation.mdx.js +2 -2
  113. package/dist/templates/mdx/platform/ai-assistant.mdx.d.ts +1 -0
  114. package/dist/templates/mdx/platform/ai-assistant.mdx.js +45 -0
  115. package/dist/templates/mdx/platform/billing.mdx.d.ts +1 -0
  116. package/dist/templates/mdx/platform/billing.mdx.js +44 -0
  117. package/dist/templates/mdx/platform/creating-a-project.mdx.d.ts +1 -0
  118. package/dist/templates/mdx/platform/creating-a-project.mdx.js +47 -0
  119. package/dist/templates/mdx/platform/custom-domains.mdx.d.ts +1 -0
  120. package/dist/templates/mdx/platform/custom-domains.mdx.js +34 -0
  121. package/dist/templates/mdx/platform/deployments.mdx.d.ts +1 -0
  122. package/dist/templates/mdx/platform/deployments.mdx.js +36 -0
  123. package/dist/templates/mdx/platform/external-links.mdx.d.ts +1 -0
  124. package/dist/templates/mdx/platform/external-links.mdx.js +58 -0
  125. package/dist/templates/mdx/platform/file-editor.mdx.d.ts +1 -0
  126. package/dist/templates/mdx/platform/file-editor.mdx.js +41 -0
  127. package/dist/templates/mdx/platform/fonts-settings.mdx.d.ts +1 -0
  128. package/dist/templates/mdx/platform/fonts-settings.mdx.js +47 -0
  129. package/dist/templates/mdx/platform/index.mdx.d.ts +1 -0
  130. package/dist/templates/mdx/platform/index.mdx.js +56 -0
  131. package/dist/templates/mdx/platform/navigation-settings.mdx.d.ts +1 -0
  132. package/dist/templates/mdx/platform/navigation-settings.mdx.js +66 -0
  133. package/dist/templates/mdx/platform/project-settings.mdx.d.ts +1 -0
  134. package/dist/templates/mdx/platform/project-settings.mdx.js +36 -0
  135. package/dist/templates/mdx/platform/publishing.mdx.d.ts +1 -0
  136. package/dist/templates/mdx/platform/publishing.mdx.js +41 -0
  137. package/dist/templates/mdx/platform/sections-settings.mdx.d.ts +1 -0
  138. package/dist/templates/mdx/platform/sections-settings.mdx.js +41 -0
  139. package/dist/templates/mdx/platform/site-settings.mdx.d.ts +1 -0
  140. package/dist/templates/mdx/platform/site-settings.mdx.js +41 -0
  141. package/dist/templates/mdx/platform/team-members.mdx.d.ts +1 -0
  142. package/dist/templates/mdx/platform/team-members.mdx.js +45 -0
  143. package/dist/templates/mdx/platform/theme-settings.mdx.d.ts +1 -0
  144. package/dist/templates/mdx/platform/theme-settings.mdx.js +44 -0
  145. package/dist/templates/mdx/sections.mdx.d.ts +1 -1
  146. package/dist/templates/mdx/sections.mdx.js +3 -3
  147. package/dist/templates/mdx/steps.mdx.d.ts +1 -1
  148. package/dist/templates/mdx/steps.mdx.js +5 -1
  149. package/dist/templates/mdx/tabs.mdx.d.ts +1 -1
  150. package/dist/templates/mdx/tabs.mdx.js +2 -2
  151. package/dist/templates/mdx/theme.mdx.d.ts +1 -1
  152. package/dist/templates/mdx/theme.mdx.js +1 -1
  153. package/dist/templates/mdx/update.mdx.d.ts +1 -1
  154. package/dist/templates/mdx/update.mdx.js +3 -3
  155. package/dist/templates/next.config.d.ts +1 -1
  156. package/dist/templates/next.config.js +0 -3
  157. package/dist/templates/package.js +5 -5
  158. package/dist/templates/services/llm/config.d.ts +1 -1
  159. package/dist/templates/services/llm/config.js +1 -1
  160. package/dist/templates/services/llm/types.d.ts +1 -1
  161. package/dist/templates/services/llm/types.js +1 -1
  162. package/dist/templates/services/mcp/server.d.ts +1 -1
  163. package/dist/templates/services/mcp/server.js +1 -1
  164. package/dist/templates/services/mcp/tools.d.ts +1 -1
  165. package/dist/templates/services/mcp/tools.js +1 -5
  166. package/dist/templates/structures.d.ts +2 -0
  167. package/dist/templates/structures.js +208 -0
  168. package/dist/templates/utils/config.d.ts +1 -1
  169. package/dist/templates/utils/config.js +2 -2
  170. package/package.json +2 -2
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  ## Quick Start
20
20
 
21
- Make sure you have [Node.js](https://nodejs.org) (v18+) installed.
21
+ Make sure you have [Node.js](https://nodejs.org) (v22+) installed.
22
22
 
23
23
  ```bash
24
24
  npx doccupine
@@ -59,6 +59,7 @@ description: "Page description for SEO"
59
59
  category: "Getting Started"
60
60
  categoryOrder: 0 # Sort order for the category group
61
61
  order: 1 # Sort order within the category
62
+ name: "My Docs" # Override site name in title suffix
62
63
  icon: "https://..." # Page favicon URL
63
64
  image: "https://..." # OpenGraph image URL
64
65
  date: "2025-01-01" # Page date metadata
@@ -128,7 +129,7 @@ Place these JSON files in your project root (where you run `doccupine`). They ar
128
129
  | File | Purpose |
129
130
  | ----------------- | --------------------------------------------------------------------------------------------------------- |
130
131
  | `doccupine.json` | CLI config (watchDir, outputDir, port). Auto-generated on first run. |
131
- | `config.json` | Site metadata: `name`, `description`, `icon`, `preview` image URL |
132
+ | `config.json` | Site metadata: `name`, `description`, `icon`, `image` URL |
132
133
  | `theme.json` | Theme overrides for [cherry-styled-components](https://github.com/cherry-design-system/styled-components) |
133
134
  | `navigation.json` | Manual navigation structure (overrides auto-generated) |
134
135
  | `links.json` | Static header/footer links |
@@ -141,7 +142,7 @@ Place static assets (images, favicons, `robots.txt`, etc.) in a `public/` direct
141
142
 
142
143
  ## AI Chat Setup
143
144
 
144
- The generated app includes an AI chat assistant. To enable it, create a `.env.local` file in the generated app directory:
145
+ The generated app includes an AI chat assistant. To enable it, create a `.env` file in the generated app directory:
145
146
 
146
147
  ```env
147
148
  LLM_PROVIDER=openai # openai | anthropic | google
@@ -170,7 +171,7 @@ Default models per provider:
170
171
  | --------- | ---------------------------- | ------------------------ |
171
172
  | OpenAI | `gpt-4.1-nano` | `text-embedding-3-small` |
172
173
  | Anthropic | `claude-sonnet-4-5-20250929` | OpenAI fallback |
173
- | Google | `gemini-2.5-flash-lite` | `text-embedding-004` |
174
+ | Google | `gemini-2.5-flash-lite` | `gemini-embedding-001` |
174
175
 
175
176
  ## MCP Server
176
177
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export declare function generateSlug(filePath: string): string;
3
- export declare function getFullSlug(pageSlug: string, sectionSlug: string): string;
4
- export declare function escapeTemplateContent(content: string): string;
2
+ export { generateSlug, getFullSlug, escapeTemplateContent, } from "./lib/utils.js";
package/dist/index.js CHANGED
@@ -6,209 +6,16 @@ import path from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import matter from "gray-matter";
8
8
  import chalk from "chalk";
9
- import prompts from "prompts";
10
- import { envExampleTemplate } from "./templates/env.example.js";
11
- import { gitignoreTemplate } from "./templates/gitignore.js";
12
- import { eslintConfigTemplate } from "./templates/eslint.config.js";
13
- import { nextConfigTemplate } from "./templates/next.config.js";
14
- import { packageJsonTemplate } from "./templates/package.js";
15
- import { prettierrcTemplate } from "./templates/prettierrc.js";
16
- import { prettierignoreTemplate } from "./templates/prettierignore.js";
17
- import { proxyTemplate } from "./templates/proxy.js";
18
- import { tsconfigTemplate } from "./templates/tsconfig.js";
19
- import { mcpRoutesTemplate } from "./templates/app/api/mcp/route.js";
20
- import { ragRoutesTemplate } from "./templates/app/api/rag/route.js";
21
- import { routesTemplate } from "./templates/app/api/theme/routes.js";
22
- import { layoutTemplate } from "./templates/app/layout.js";
23
- import { notFoundTemplate } from "./templates/app/not-found.js";
24
- import { themeTemplate } from "./templates/app/theme.js";
25
- import { chatTemplate } from "./templates/components/Chat.js";
26
- import { clickOutsideTemplate } from "./templates/components/ClickOutside.js";
27
- import { docsTemplate } from "./templates/components/Docs.js";
28
- import { docsSideBarTemplate } from "./templates/components/DocsSideBar.js";
29
- import { mdxComponentsTemplate } from "./templates/components/MDXComponents.js";
30
- import { sectionNavProviderTemplate } from "./templates/components/SectionNavProvider.js";
31
- import { sideBarTemplate } from "./templates/components/SideBar.js";
32
- import { sectionBarTemplate } from "./templates/components/layout/SectionBar.js";
33
- import { accordionTemplate } from "./templates/components/layout/Accordion.js";
34
- import { actionBarTemplate } from "./templates/components/layout/ActionBar.js";
35
- import { buttonTemplate } from "./templates/components/layout/Button.js";
36
- import { calloutTemplate } from "./templates/components/layout/Callout.js";
37
- import { cardTemplate } from "./templates/components/layout/Card.js";
38
- import { cherryThemeProviderTemplate } from "./templates/components/layout/CherryThemeProvider.js";
39
- import { clientThemeProviderTemplate } from "./templates/components/layout/ClientThemeProvider.js";
40
- import { codeTemplate } from "./templates/components/layout/Code.js";
41
- import { columnsTemplate } from "./templates/components/layout/Columns.js";
42
- import { demoThemeTemplate } from "./templates/components/layout/DemoTheme.js";
43
- import { docsComponentsTemplate } from "./templates/components/layout/DocsComponents.js";
44
- import { docsNavigationTemplate } from "./templates/components/layout/DocsNavigation.js";
45
- import { fieldTemplate } from "./templates/components/layout/Field.js";
46
- import { footerTemplate } from "./templates/components/layout/Footer.js";
47
- import { globalStylesTemplate } from "./templates/components/layout/GlobalStyles.js";
48
- import { headerTemplate } from "./templates/components/layout/Header.js";
49
- import { iconTemplate } from "./templates/components/layout/Icon.js";
50
- import { pictogramsTemplate } from "./templates/components/layout/Pictograms.js";
51
- import { sharedStyledTemplate } from "./templates/components/layout/SharedStyles.js";
52
- import { staticLinksTemplate } from "./templates/components/layout/StaticLinks.js";
53
- import { stepsTemplate } from "./templates/components/layout/Steps.js";
54
- import { tabsTemplate } from "./templates/components/layout/Tabs.js";
55
- import { themeToggleTemplate } from "./templates/components/layout/ThemeToggle.js";
56
- import { typographyTemplate } from "./templates/components/layout/Typography.js";
57
- import { updateTemplate } from "./templates/components/layout/Update.js";
58
- import { mcpIndexTemplate } from "./templates/services/mcp/index.js";
59
- import { mcpServerTemplate } from "./templates/services/mcp/server.js";
60
- import { mcpToolsTemplate } from "./templates/services/mcp/tools.js";
61
- import { mcpTypesTemplate } from "./templates/services/mcp/types.js";
62
- import { llmConfigTemplate } from "./templates/services/llm/config.js";
63
- import { llmFactoryTemplate } from "./templates/services/llm/factory.js";
64
- import { llmIndexTemplate } from "./templates/services/llm/index.js";
65
- import { llmTypesTemplate } from "./templates/services/llm/types.js";
66
- import { styledDTemplate } from "./templates/types/styled.js";
67
- import { orderNavItemsTemplate } from "./templates/utils/orderNavItems.js";
68
- import { rateLimitTemplate } from "./templates/utils/rateLimit.js";
69
- import { brandingTemplate } from "./templates/utils/branding.js";
70
- import { configTemplate } from "./templates/utils/config.js";
71
- import { accordionMdxTemplate } from "./templates/mdx/accordion.mdx.js";
72
- import { aiAssistantMdxTemplate } from "./templates/mdx/ai-assistant.mdx.js";
73
- import { buttonsMdxTemplate } from "./templates/mdx/buttons.mdx.js";
74
- import { calloutsMdxTemplate } from "./templates/mdx/callouts.mdx.js";
75
- import { cardsMdxTemplate } from "./templates/mdx/cards.mdx.js";
76
- import { codeMdxTemplate } from "./templates/mdx/code.mdx.js";
77
- import { columnsMdxTemplate } from "./templates/mdx/columns.mdx.js";
78
- import { commandsMdxTemplate } from "./templates/mdx/commands.mdx.js";
79
- import { deploymentMdxTemplate } from "./templates/mdx/deployment.mdx.js";
80
- import { fieldsMdxTemplate } from "./templates/mdx/fields.mdx.js";
81
- import { fontsMdxTemplate } from "./templates/mdx/fonts.mdx.js";
82
- import { globalsMdxTemplate } from "./templates/mdx/globals.mdx.js";
83
- import { headersAndTextMdxTemplate } from "./templates/mdx/headers-and-text.mdx.js";
84
- import { iconsMdxTemplate } from "./templates/mdx/icons.mdx.js";
85
- import { imageAndEmbedsMdxTemplate } from "./templates/mdx/image-and-embeds.mdx.js";
86
- import { indexMdxTemplate } from "./templates/mdx/index.mdx.js";
87
- import { footerLinksMdxTemplate } from "./templates/mdx/footer-links.mdx.js";
88
- import { listAndTablesMdxTemplate } from "./templates/mdx/list-and-tables.mdx.js";
89
- import { mediaAndAssetsMdxTemplate } from "./templates/mdx/media-and-assets.mdx.js";
90
- import { mcpMdxTemplate } from "./templates/mdx/model-context-protocol.mdx.js";
91
- import { navigationMdxTemplate } from "./templates/mdx/navigation.mdx.js";
92
- import { sectionsMdxTemplate } from "./templates/mdx/sections.mdx.js";
93
- import { stepsMdxTemplate } from "./templates/mdx/steps.mdx.js";
94
- import { tabsMdxTemplate } from "./templates/mdx/tabs.mdx.js";
95
- import { themeMdxTemplate } from "./templates/mdx/theme.mdx.js";
96
- import { updateMdxTemplate } from "./templates/mdx/update.mdx.js";
97
- async function findAvailablePort(startPort) {
98
- const net = await import("net");
99
- return new Promise((resolve) => {
100
- const server = net.createServer();
101
- server.listen(startPort, () => {
102
- server.close(() => resolve(startPort));
103
- });
104
- server.on("error", () => {
105
- resolve(findAvailablePort(startPort + 1));
106
- });
107
- });
108
- }
109
- export function generateSlug(filePath) {
110
- if (filePath === "index.mdx" || filePath === "./index.mdx") {
111
- return "";
112
- }
113
- const normalized = filePath
114
- .replace(/\.mdx$/, "")
115
- .replace(/\\/g, "/")
116
- .replace(/[^a-zA-Z0-9\/\-_]/g, "-")
117
- .toLowerCase();
118
- // Strip trailing /index for subdirectory index files
119
- if (normalized.endsWith("/index")) {
120
- return normalized.slice(0, -"/index".length);
121
- }
122
- return normalized;
123
- }
124
- export function getFullSlug(pageSlug, sectionSlug) {
125
- if (!sectionSlug)
126
- return pageSlug;
127
- if (pageSlug === "")
128
- return sectionSlug;
129
- return `${sectionSlug}/${pageSlug}`;
130
- }
131
- export function escapeTemplateContent(content) {
132
- return content
133
- .replace(/\\/g, "\\\\")
134
- .replace(/`/g, "\\`")
135
- .replace(/\$\{/g, "\\${");
136
- }
9
+ import { appStructure, startingDocsStructure } from "./lib/structures.js";
10
+ import { layoutTemplate } from "./lib/layout.js";
11
+ import { ConfigManager } from "./lib/config-manager.js";
12
+ import { findAvailablePort, generateSlug, getFullSlug, escapeTemplateContent, } from "./lib/utils.js";
13
+ import { generateMetadataBlock, generateRuntimeOnlyMetadataBlock, } from "./lib/metadata.js";
14
+ export { generateSlug, getFullSlug, escapeTemplateContent, } from "./lib/utils.js";
137
15
  const __filename = fileURLToPath(import.meta.url);
138
16
  const __dirname = path.dirname(__filename);
139
17
  const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
140
18
  const version = packageJson.version;
141
- class ConfigManager {
142
- configPath;
143
- constructor(configPath = "doccupine.json") {
144
- this.configPath = path.resolve(process.cwd(), configPath);
145
- }
146
- async loadConfig() {
147
- try {
148
- if (await fs.pathExists(this.configPath)) {
149
- const configContent = await fs.readFile(this.configPath, "utf8");
150
- const config = JSON.parse(configContent);
151
- console.log(chalk.blue("šŸ“„ Using existing configuration from doccupine.json"));
152
- return config;
153
- }
154
- }
155
- catch (error) {
156
- console.warn(chalk.yellow("āš ļø Error reading config file, will create new one"));
157
- }
158
- return null;
159
- }
160
- async saveConfig(config) {
161
- try {
162
- await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), "utf8");
163
- console.log(chalk.green("šŸ’¾ Configuration saved to doccupine.json"));
164
- }
165
- catch (error) {
166
- console.error(chalk.red("āŒ Error saving config file:"), error);
167
- }
168
- }
169
- async promptForConfig(existingConfig) {
170
- const questions = [
171
- {
172
- type: "text",
173
- name: "watchDir",
174
- message: "Enter directory to watch for MDX files:",
175
- initial: existingConfig?.watchDir || "docs",
176
- },
177
- {
178
- type: "text",
179
- name: "outputDir",
180
- message: "Enter output directory for Next.js app:",
181
- initial: existingConfig?.outputDir || "nextjs-app",
182
- },
183
- ];
184
- const { watchDir, outputDir } = (await prompts(questions));
185
- if (!watchDir || !outputDir) {
186
- console.log(chalk.yellow("\nāš ļø Setup cancelled."));
187
- process.exit(0);
188
- }
189
- return {
190
- watchDir: path.resolve(process.cwd(), watchDir),
191
- outputDir: path.resolve(process.cwd(), outputDir),
192
- port: existingConfig?.port || "3000",
193
- };
194
- }
195
- async getConfig(options = {}) {
196
- let config = null;
197
- if (!options.reset) {
198
- config = await this.loadConfig();
199
- }
200
- if (!config || options.reset) {
201
- console.log(chalk.blue("šŸ”§ Setting up Doccupine configuration..."));
202
- config = await this.promptForConfig(config || {});
203
- await this.saveConfig(config);
204
- }
205
- if (options.port) {
206
- config.port = options.port;
207
- await this.saveConfig(config);
208
- }
209
- return config;
210
- }
211
- }
212
19
  class MDXToNextJSGenerator {
213
20
  watchDir;
214
21
  outputDir;
@@ -255,72 +62,13 @@ class MDXToNextJSGenerator {
255
62
  }
256
63
  async createNextJSStructure() {
257
64
  const structure = {
258
- ".env.example": envExampleTemplate,
259
- ".gitignore": gitignoreTemplate,
260
- ".prettierrc": prettierrcTemplate,
261
- ".prettierignore": prettierignoreTemplate,
65
+ ...appStructure,
262
66
  "config.json": `{}\n`,
263
- "eslint.config.mjs": eslintConfigTemplate,
264
67
  "links.json": `[]\n`,
265
68
  "navigation.json": `[]\n`,
266
69
  "sections.json": `[]\n`,
267
- "next.config.ts": nextConfigTemplate,
268
- "package.json": packageJsonTemplate,
269
- "proxy.ts": proxyTemplate,
270
70
  "theme.json": `{}\n`,
271
- "tsconfig.json": tsconfigTemplate,
272
71
  "app/layout.tsx": this.generateRootLayout(),
273
- "app/not-found.tsx": notFoundTemplate,
274
- "app/theme.ts": themeTemplate,
275
- "app/api/mcp/route.ts": mcpRoutesTemplate,
276
- "app/api/rag/route.ts": ragRoutesTemplate,
277
- "app/api/theme/route.ts": routesTemplate,
278
- "services/mcp/index.ts": mcpIndexTemplate,
279
- "services/mcp/server.ts": mcpServerTemplate,
280
- "services/mcp/tools.ts": mcpToolsTemplate,
281
- "services/mcp/types.ts": mcpTypesTemplate,
282
- "services/llm/config.ts": llmConfigTemplate,
283
- "services/llm/factory.ts": llmFactoryTemplate,
284
- "services/llm/index.ts": llmIndexTemplate,
285
- "services/llm/types.ts": llmTypesTemplate,
286
- "types/styled.d.ts": styledDTemplate,
287
- "utils/branding.ts": brandingTemplate,
288
- "utils/orderNavItems.ts": orderNavItemsTemplate,
289
- "utils/rateLimit.ts": rateLimitTemplate,
290
- "utils/config.ts": configTemplate,
291
- "components/Chat.tsx": chatTemplate,
292
- "components/ClickOutside.ts": clickOutsideTemplate,
293
- "components/Docs.tsx": docsTemplate,
294
- "components/DocsSideBar.tsx": docsSideBarTemplate,
295
- "components/MDXComponents.tsx": mdxComponentsTemplate,
296
- "components/SectionNavProvider.tsx": sectionNavProviderTemplate,
297
- "components/SideBar.tsx": sideBarTemplate,
298
- "components/layout/Accordion.tsx": accordionTemplate,
299
- "components/layout/ActionBar.tsx": actionBarTemplate,
300
- "components/layout/Button.tsx": buttonTemplate,
301
- "components/layout/Callout.tsx": calloutTemplate,
302
- "components/layout/Card.tsx": cardTemplate,
303
- "components/layout/CherryThemeProvider.tsx": cherryThemeProviderTemplate,
304
- "components/layout/ClientThemeProvider.tsx": clientThemeProviderTemplate,
305
- "components/layout/Code.tsx": codeTemplate,
306
- "components/layout/Columns.tsx": columnsTemplate,
307
- "components/layout/DemoTheme.tsx": demoThemeTemplate,
308
- "components/layout/DocsComponents.tsx": docsComponentsTemplate,
309
- "components/layout/DocsNavigation.tsx": docsNavigationTemplate,
310
- "components/layout/SectionBar.tsx": sectionBarTemplate,
311
- "components/layout/Field.tsx": fieldTemplate,
312
- "components/layout/Footer.tsx": footerTemplate,
313
- "components/layout/GlobalStyles.ts": globalStylesTemplate,
314
- "components/layout/Header.tsx": headerTemplate,
315
- "components/layout/Icon.tsx": iconTemplate,
316
- "components/layout/Pictograms.tsx": pictogramsTemplate,
317
- "components/layout/SharedStyled.ts": sharedStyledTemplate,
318
- "components/layout/StaticLinks.tsx": staticLinksTemplate,
319
- "components/layout/Steps.tsx": stepsTemplate,
320
- "components/layout/Tabs.tsx": tabsTemplate,
321
- "components/layout/ThemeToggle.tsx": themeToggleTemplate,
322
- "components/layout/Typography.ts": typographyTemplate,
323
- "components/layout/Update.tsx": updateTemplate,
324
72
  };
325
73
  for (const [filePath, content] of Object.entries(structure)) {
326
74
  const fullPath = path.join(this.outputDir, filePath);
@@ -329,34 +77,7 @@ class MDXToNextJSGenerator {
329
77
  }
330
78
  }
331
79
  async createStartingDocs() {
332
- const structure = {
333
- "accordion.mdx": accordionMdxTemplate,
334
- "ai-assistant.mdx": aiAssistantMdxTemplate,
335
- "buttons.mdx": buttonsMdxTemplate,
336
- "callouts.mdx": calloutsMdxTemplate,
337
- "cards.mdx": cardsMdxTemplate,
338
- "code.mdx": codeMdxTemplate,
339
- "columns.mdx": columnsMdxTemplate,
340
- "commands.mdx": commandsMdxTemplate,
341
- "deployment.mdx": deploymentMdxTemplate,
342
- "fields.mdx": fieldsMdxTemplate,
343
- "fonts.mdx": fontsMdxTemplate,
344
- "globals.mdx": globalsMdxTemplate,
345
- "headers-and-text.mdx": headersAndTextMdxTemplate,
346
- "icons.mdx": iconsMdxTemplate,
347
- "image-and-embeds.mdx": imageAndEmbedsMdxTemplate,
348
- "index.mdx": indexMdxTemplate,
349
- "footer-links.mdx": footerLinksMdxTemplate,
350
- "lists-and-tables.mdx": listAndTablesMdxTemplate,
351
- "media-and-assets.mdx": mediaAndAssetsMdxTemplate,
352
- "model-context-protocol.mdx": mcpMdxTemplate,
353
- "navigation.mdx": navigationMdxTemplate,
354
- "sections.mdx": sectionsMdxTemplate,
355
- "steps.mdx": stepsMdxTemplate,
356
- "tabs.mdx": tabsMdxTemplate,
357
- "theme.mdx": themeMdxTemplate,
358
- "update.mdx": updateMdxTemplate,
359
- };
80
+ const structure = startingDocsStructure;
360
81
  const indexMdxExists = await fs.pathExists(path.join(this.watchDir, "index.mdx"));
361
82
  if (!indexMdxExists) {
362
83
  for (const [filePath, content] of Object.entries(structure)) {
@@ -898,22 +619,23 @@ export default function SectionIndex() {
898
619
  }
899
620
  }
900
621
  async generatePageFromMDX(mdxFile) {
622
+ const fm = mdxFile.frontmatter;
623
+ const metadataBlock = generateMetadataBlock({
624
+ title: fm.title,
625
+ titleFallback: "Generated with Doccupine",
626
+ name: fm.name,
627
+ titleOrder: "page-first",
628
+ description: fm.description,
629
+ icon: fm.icon,
630
+ image: fm.image,
631
+ });
901
632
  const pageContent = `import { Metadata } from "next";
902
633
  import { Docs } from "@/components/Docs";
903
634
  import { config } from "@/utils/config";
904
635
 
905
636
  const content = \`${escapeTemplateContent(mdxFile.content)}\`;
906
637
 
907
- export const metadata: Metadata = {
908
- title: \`${mdxFile.frontmatter.title || "Generated with Doccupine"} \${config.name ? "- " + config.name : "- Doccupine"}\`,
909
- description: \`${mdxFile.frontmatter.description ? mdxFile.frontmatter.description : '${config.description ? config.description : "Generated with Doccupine"}'}\`,
910
- icons: \`${mdxFile.frontmatter.icon ? mdxFile.frontmatter.icon : '\${config.icon || "https://doccupine.com/favicon.ico"}'}\`,
911
- openGraph: {
912
- title: \`${mdxFile.frontmatter.title || "Generated with Doccupine"} \${config.name ? "- " + config.name : "- Doccupine"}\`,
913
- description: \`${mdxFile.frontmatter.description ? mdxFile.frontmatter.description : '${config.description ? config.description : "Generated with Doccupine"}'}\`,
914
- images: \`${mdxFile.frontmatter.image ? mdxFile.frontmatter.image : '\${config.preview || "https://doccupine.com/preview.png"}'}\`,
915
- },
916
- };
638
+ ${metadataBlock}
917
639
 
918
640
  export default function Page() {
919
641
  return <Docs content={content} />;
@@ -937,37 +659,29 @@ export default function Page() {
937
659
  description: frontmatter.description || "",
938
660
  icon: frontmatter.icon,
939
661
  image: frontmatter.image,
662
+ name: frontmatter.name,
940
663
  };
941
664
  break;
942
665
  }
943
666
  }
667
+ const metadataBlock = indexMDX
668
+ ? generateMetadataBlock({
669
+ title: indexMDX.title,
670
+ titleFallback: "Welcome",
671
+ name: indexMDX.name,
672
+ titleOrder: "name-first",
673
+ description: indexMDX.description || undefined,
674
+ icon: indexMDX.icon,
675
+ image: indexMDX.image,
676
+ })
677
+ : generateRuntimeOnlyMetadataBlock();
944
678
  const indexContent = `import { Metadata } from "next";
945
679
  import { Docs } from "@/components/Docs";
946
680
  import { config } from "@/utils/config";
947
681
 
948
682
  ${indexMDX ? `const content = \`${escapeTemplateContent(indexMDX.content)}\`;` : `const content = null;`}
949
683
 
950
- ${indexMDX
951
- ? `export const metadata: Metadata = {
952
- title: \`\${config.name ? config.name + " -" : "Doccupine -"} ${indexMDX.title}\`,
953
- description: \`${indexMDX.description ? indexMDX.description : '${config.description ? config.description : "Generated with Doccupine"}'}\`,
954
- icons: \`${indexMDX.icon ? indexMDX.icon : '\${config.icon || "https://doccupine.com/favicon.ico"}'}\`,
955
- openGraph: {
956
- title: \`\${config.name ? config.name + " -" : "Doccupine -"} ${indexMDX.title}\`,
957
- description: \`${indexMDX.description ? indexMDX.description : '${config.description ? config.description : "Generated with Doccupine"}'}\`,
958
- images: \`${indexMDX.image ? indexMDX.image : '\${config.preview || "https://doccupine.com/preview.png"}'}\`,
959
- },
960
- };`
961
- : `export const metadata: Metadata = {
962
- title: \`\${config.name || "Doccupine"}\`,
963
- description: \`\${config.description || "Generated with Doccupine"}\`,
964
- icons: \`\${config.icon || "https://doccupine.com/favicon.ico"}\`,
965
- openGraph: {
966
- title: \`\${config.name || "Doccupine"}\`,
967
- description: \`\${config.description || "Generated with Doccupine"}\`,
968
- images: \`\${config.preview || "https://doccupine.com/preview.png"}\`,
969
- },
970
- };`}
684
+ ${metadataBlock}
971
685
 
972
686
  export default function Home() {
973
687
  return <Docs content={content} />;
@@ -976,22 +690,22 @@ export default function Home() {
976
690
  await fs.writeFile(path.join(this.outputDir, "app", "page.tsx"), indexContent, "utf8");
977
691
  }
978
692
  async updateSectionIndex(sectionSlug, frontmatter, mdxContent) {
693
+ const metadataBlock = generateMetadataBlock({
694
+ title: frontmatter.title,
695
+ titleFallback: "Section",
696
+ name: frontmatter.name,
697
+ titleOrder: "name-first",
698
+ description: frontmatter.description || undefined,
699
+ icon: frontmatter.icon,
700
+ image: frontmatter.image,
701
+ });
979
702
  const indexContent = `import { Metadata } from "next";
980
703
  import { Docs } from "@/components/Docs";
981
704
  import { config } from "@/utils/config";
982
705
 
983
706
  const content = \`${escapeTemplateContent(mdxContent)}\`;
984
707
 
985
- export const metadata: Metadata = {
986
- title: \`\${config.name ? config.name + " -" : "Doccupine -"} ${frontmatter.title || "Section"}\`,
987
- description: \`${frontmatter.description ? frontmatter.description : '${config.description ? config.description : "Generated with Doccupine"}'}\`,
988
- icons: \`${frontmatter.icon ? frontmatter.icon : '\${config.icon || "https://doccupine.com/favicon.ico"}'}\`,
989
- openGraph: {
990
- title: \`\${config.name ? config.name + " -" : "Doccupine -"} ${frontmatter.title || "Section"}\`,
991
- description: \`${frontmatter.description ? frontmatter.description : '${config.description ? config.description : "Generated with Doccupine"}'}\`,
992
- images: \`${frontmatter.image ? frontmatter.image : '\${config.preview || "https://doccupine.com/preview.png"}'}\`,
993
- },
994
- };
708
+ ${metadataBlock}
995
709
 
996
710
  export default function Page() {
997
711
  return <Docs content={content} />;
@@ -1089,7 +803,10 @@ program
1089
803
  if (output.includes("Ready") || output.includes("started")) {
1090
804
  console.log(chalk.green(`🌐 Next.js ready at http://localhost:${port}`));
1091
805
  }
1092
- if (output.includes("compiled") ||
806
+ if (options.verbose) {
807
+ process.stdout.write(chalk.gray("[Next.js] ") + output);
808
+ }
809
+ else if (output.includes("compiled") ||
1093
810
  output.includes("error") ||
1094
811
  output.includes("Ready")) {
1095
812
  process.stdout.write(chalk.gray("[Next.js] ") + output);
@@ -0,0 +1,12 @@
1
+ import type { DoccupineConfig } from "./types.js";
2
+ export declare class ConfigManager {
3
+ private configPath;
4
+ constructor(configPath?: string);
5
+ loadConfig(): Promise<DoccupineConfig | null>;
6
+ saveConfig(config: DoccupineConfig): Promise<void>;
7
+ promptForConfig(existingConfig?: Partial<DoccupineConfig>): Promise<DoccupineConfig>;
8
+ getConfig(options?: {
9
+ reset?: boolean;
10
+ port?: string;
11
+ }): Promise<DoccupineConfig>;
12
+ }
@@ -0,0 +1,75 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import chalk from "chalk";
4
+ import prompts from "prompts";
5
+ export class ConfigManager {
6
+ configPath;
7
+ constructor(configPath = "doccupine.json") {
8
+ this.configPath = path.resolve(process.cwd(), configPath);
9
+ }
10
+ async loadConfig() {
11
+ try {
12
+ if (await fs.pathExists(this.configPath)) {
13
+ const configContent = await fs.readFile(this.configPath, "utf8");
14
+ const config = JSON.parse(configContent);
15
+ console.log(chalk.blue("šŸ“„ Using existing configuration from doccupine.json"));
16
+ return config;
17
+ }
18
+ }
19
+ catch (error) {
20
+ console.warn(chalk.yellow("āš ļø Error reading config file, will create new one"));
21
+ }
22
+ return null;
23
+ }
24
+ async saveConfig(config) {
25
+ try {
26
+ await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), "utf8");
27
+ console.log(chalk.green("šŸ’¾ Configuration saved to doccupine.json"));
28
+ }
29
+ catch (error) {
30
+ console.error(chalk.red("āŒ Error saving config file:"), error);
31
+ }
32
+ }
33
+ async promptForConfig(existingConfig) {
34
+ const questions = [
35
+ {
36
+ type: "text",
37
+ name: "watchDir",
38
+ message: "Enter directory to watch for MDX files:",
39
+ initial: existingConfig?.watchDir || "docs",
40
+ },
41
+ {
42
+ type: "text",
43
+ name: "outputDir",
44
+ message: "Enter output directory for Next.js app:",
45
+ initial: existingConfig?.outputDir || "nextjs-app",
46
+ },
47
+ ];
48
+ const { watchDir, outputDir } = (await prompts(questions));
49
+ if (!watchDir || !outputDir) {
50
+ console.log(chalk.yellow("\nāš ļø Setup cancelled."));
51
+ process.exit(0);
52
+ }
53
+ return {
54
+ watchDir: path.resolve(process.cwd(), watchDir),
55
+ outputDir: path.resolve(process.cwd(), outputDir),
56
+ port: existingConfig?.port || "3000",
57
+ };
58
+ }
59
+ async getConfig(options = {}) {
60
+ let config = null;
61
+ if (!options.reset) {
62
+ config = await this.loadConfig();
63
+ }
64
+ if (!config || options.reset) {
65
+ console.log(chalk.blue("šŸ”§ Setting up Doccupine configuration..."));
66
+ config = await this.promptForConfig(config || {});
67
+ await this.saveConfig(config);
68
+ }
69
+ if (options.port) {
70
+ config.port = options.port;
71
+ await this.saveConfig(config);
72
+ }
73
+ return config;
74
+ }
75
+ }
@@ -0,0 +1,5 @@
1
+ export declare const DEFAULT_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.";
2
+ export declare const DEFAULT_SITE_NAME = "Doccupine";
3
+ export declare const DEFAULT_META_DESCRIPTION = "Generated with Doccupine";
4
+ export declare const DEFAULT_FAVICON = "https://docs.doccupine.com/favicon.ico";
5
+ export declare const DEFAULT_OG_IMAGE = "https://docs.doccupine.com/preview.png";
@@ -0,0 +1,5 @@
1
+ export const DEFAULT_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.";
2
+ export const DEFAULT_SITE_NAME = "Doccupine";
3
+ export const DEFAULT_META_DESCRIPTION = "Generated with Doccupine";
4
+ export const DEFAULT_FAVICON = "https://docs.doccupine.com/favicon.ico";
5
+ export const DEFAULT_OG_IMAGE = "https://docs.doccupine.com/preview.png";
@@ -0,0 +1,30 @@
1
+ import type { SectionConfig } from "./types.js";
2
+ interface PageData {
3
+ slug: string;
4
+ title: string;
5
+ description: string;
6
+ date: string | null;
7
+ category: string;
8
+ path: string;
9
+ categoryOrder: number;
10
+ order: number;
11
+ section: string;
12
+ }
13
+ interface GoogleFontConfig {
14
+ fontName?: string;
15
+ subsets?: string[];
16
+ weight?: string | string[];
17
+ }
18
+ interface LocalFontSrc {
19
+ path: string;
20
+ weight: string;
21
+ style: string;
22
+ }
23
+ interface FontConfig {
24
+ googleFont?: GoogleFontConfig;
25
+ localFonts?: string | {
26
+ src?: LocalFontSrc[];
27
+ };
28
+ }
29
+ export declare const layoutTemplate: (pages: PageData[], fontConfig: FontConfig | null, sectionsConfig?: SectionConfig[] | null) => string;
30
+ export {};