doccupine 0.0.124 → 0.0.126

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 (36) hide show
  1. package/dist/index.js +5 -5
  2. package/dist/lib/structures.js +14 -0
  3. package/dist/templates/components/Docs.d.ts +1 -1
  4. package/dist/templates/components/Docs.js +6 -2
  5. package/dist/templates/components/MDXComponents.d.ts +1 -1
  6. package/dist/templates/components/MDXComponents.js +2 -2
  7. package/dist/templates/components/MermaidPre.d.ts +1 -0
  8. package/dist/templates/components/MermaidPre.js +68 -0
  9. package/dist/templates/components/layout/DocsComponents.d.ts +1 -1
  10. package/dist/templates/components/layout/DocsComponents.js +0 -1
  11. package/dist/templates/components/layout/GlobalStyles.d.ts +1 -1
  12. package/dist/templates/components/layout/GlobalStyles.js +11 -0
  13. package/dist/templates/components/layout/Header.d.ts +1 -1
  14. package/dist/templates/components/layout/Header.js +1 -1
  15. package/dist/templates/components/layout/Mermaid.d.ts +1 -0
  16. package/dist/templates/components/layout/Mermaid.js +342 -0
  17. package/dist/templates/components/layout/Pictograms.d.ts +1 -1
  18. package/dist/templates/components/layout/Pictograms.js +15 -13
  19. package/dist/templates/components/layout/Update.d.ts +1 -1
  20. package/dist/templates/components/layout/Update.js +3 -0
  21. package/dist/templates/mdx/components.mdx.d.ts +1 -1
  22. package/dist/templates/mdx/components.mdx.js +4 -1
  23. package/dist/templates/mdx/mermaid.mdx.d.ts +1 -0
  24. package/dist/templates/mdx/mermaid.mdx.js +142 -0
  25. package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
  26. package/dist/templates/mdx/navigation.mdx.js +4 -2
  27. package/dist/templates/mdx/what-is-doccupine.mdx.d.ts +1 -0
  28. package/dist/templates/mdx/what-is-doccupine.mdx.js +68 -0
  29. package/dist/templates/package.js +7 -6
  30. package/dist/templates/utils/mermaid.d.ts +1 -0
  31. package/dist/templates/utils/mermaid.js +48 -0
  32. package/dist/templates/utils/parseCodeMeta.d.ts +1 -0
  33. package/dist/templates/utils/parseCodeMeta.js +32 -0
  34. package/dist/templates/utils/rehypeCodeMeta.d.ts +1 -0
  35. package/dist/templates/utils/rehypeCodeMeta.js +23 -0
  36. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ export declare const mermaidMdxTemplate = "---\ntitle: \"Mermaid\"\ndescription: \"Create flowcharts, sequence diagrams, and other visualizations using Mermaid syntax.\"\ndate: \"2026-07-16\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 16\n---\n\n# Mermaid\n\nCreate flowcharts, sequence diagrams, and other visualizations using Mermaid syntax with automatic rendering.\n\nWrite a diagram inside a `mermaid` code fence and it renders as an SVG:\n\n````mdx\n```mermaid\nflowchart LR\n A[Start] --> B{Decision}\n B -->|Yes| C[Action]\n B -->|No| D[End]\n```\n````\n\n```mermaid\nflowchart LR\n A[Start] --> B{Decision}\n B -->|Yes| C[Action]\n B -->|No| D[End]\n```\n\nDiagrams are rendered when your site is built, so no diagramming library is shipped to your readers' browsers. They are drawn with your theme's colors and follow the light and dark toggle automatically.\n\n## Supported diagram types\n\nDoccupine renders diagrams with [beautiful-mermaid](https://github.com/lukilabs/beautiful-mermaid), which supports six diagram types:\n\n| Type | Opening keyword |\n| --- | --- |\n| Flowchart | `flowchart` or `graph` |\n| Sequence | `sequenceDiagram` |\n| State | `stateDiagram-v2` |\n| Class | `classDiagram` |\n| Entity relationship | `erDiagram` |\n| XY chart | `xychart-beta` |\n\nOther Mermaid diagram types - including `pie`, `gantt`, `mindmap`, `journey`, and `gitGraph` - are not supported. A diagram that cannot be rendered falls back to a plain code block showing its source, and the reason is logged when your site builds. A broken diagram never breaks the page.\n\n## Examples\n\n### Sequence diagram\n\n```mermaid\nsequenceDiagram\n participant Reader\n participant Docs\n participant Search\n Reader->>Docs: Open a page\n Docs->>Search: Index the content\n Search-->>Reader: Return results\n```\n\n### Subgraphs\n\n```mermaid placement=\"top-right\"\nflowchart LR\n subgraph one\n direction TB\n top1[top] --> bottom1[bottom]\n end\n subgraph two\n direction TB\n top2[top] --> bottom2[bottom]\n end\n outside --> one\n outside --> top2\n```\n\n## Interactive controls\n\nDiagrams include zoom in and out, pan in four directions, reset the view, and full screen. You can also drag a diagram with your mouse to move it around.\n\nBy default the controls appear once a diagram is taller than 120px, since a diagram that already fits does not need them. Use the `actions` property to decide explicitly. Setting `actions={false}` turns off the whole interactive layer, including dragging.\n\n## Properties\n\n<Field value=\"placement\" type=\"string\">\n Where the controls sit. One of `top-left`, `top-right`, `bottom-left`, or `bottom-right`. Defaults to `bottom-right`.\n</Field>\n\n<Field value=\"actions\" type=\"boolean\">\n Show or hide the controls. When set, this overrides the default behavior of showing them only on diagrams taller than 120px.\n</Field>\n\nSet properties on the opening fence, after the language:\n\n````mdx\n```mermaid placement=\"top-left\" actions={true}\nflowchart LR\n A --> B\n```\n````\n\nTo hide the controls entirely:\n\n````mdx\n```mermaid actions={false}\nflowchart LR\n A --> B\n```\n````\n\n```mermaid actions={false}\nflowchart LR\n A --> B\n```\n\n## Layout\n\nDiagrams are laid out with the [ELK](https://eclipse.dev/elk/) engine, which arranges nodes to reduce overlapping edges and keep large diagrams readable. It is always on, so no directive is needed to enable it.\n\nIf you are porting diagrams from another tool, a `%%{init: ...}%%` directive is read as a comment and ignored rather than causing an error.\n\n## Theming\n\nDiagram colors come from CSS variables, so they follow your theme and the light/dark toggle without re-rendering. Override any of them in your own CSS to restyle diagrams:\n\n```css\n:root {\n --mermaid-bg: var(--color-light);\n --mermaid-fg: var(--color-dark);\n --mermaid-line: var(--color-grayDark);\n --mermaid-accent: var(--color-accent);\n --mermaid-muted: var(--color-grayDark);\n --mermaid-surface: var(--color-grayLight);\n --mermaid-border: var(--color-gray);\n}\n```\n\n## Syntax reference\n\nFor the syntax of each supported diagram type, see the [Mermaid documentation](https://mermaid.js.org/intro/). Keep to the six types listed above.";
@@ -0,0 +1,142 @@
1
+ export const mermaidMdxTemplate = `---
2
+ title: "Mermaid"
3
+ description: "Create flowcharts, sequence diagrams, and other visualizations using Mermaid syntax."
4
+ date: "2026-07-16"
5
+ category: "Components"
6
+ categoryOrder: 1
7
+ order: 16
8
+ ---
9
+
10
+ # Mermaid
11
+
12
+ Create flowcharts, sequence diagrams, and other visualizations using Mermaid syntax with automatic rendering.
13
+
14
+ Write a diagram inside a \`mermaid\` code fence and it renders as an SVG:
15
+
16
+ \`\`\`\`mdx
17
+ \`\`\`mermaid
18
+ flowchart LR
19
+ A[Start] --> B{Decision}
20
+ B -->|Yes| C[Action]
21
+ B -->|No| D[End]
22
+ \`\`\`
23
+ \`\`\`\`
24
+
25
+ \`\`\`mermaid
26
+ flowchart LR
27
+ A[Start] --> B{Decision}
28
+ B -->|Yes| C[Action]
29
+ B -->|No| D[End]
30
+ \`\`\`
31
+
32
+ Diagrams are rendered when your site is built, so no diagramming library is shipped to your readers' browsers. They are drawn with your theme's colors and follow the light and dark toggle automatically.
33
+
34
+ ## Supported diagram types
35
+
36
+ Doccupine renders diagrams with [beautiful-mermaid](https://github.com/lukilabs/beautiful-mermaid), which supports six diagram types:
37
+
38
+ | Type | Opening keyword |
39
+ | --- | --- |
40
+ | Flowchart | \`flowchart\` or \`graph\` |
41
+ | Sequence | \`sequenceDiagram\` |
42
+ | State | \`stateDiagram-v2\` |
43
+ | Class | \`classDiagram\` |
44
+ | Entity relationship | \`erDiagram\` |
45
+ | XY chart | \`xychart-beta\` |
46
+
47
+ Other Mermaid diagram types - including \`pie\`, \`gantt\`, \`mindmap\`, \`journey\`, and \`gitGraph\` - are not supported. A diagram that cannot be rendered falls back to a plain code block showing its source, and the reason is logged when your site builds. A broken diagram never breaks the page.
48
+
49
+ ## Examples
50
+
51
+ ### Sequence diagram
52
+
53
+ \`\`\`mermaid
54
+ sequenceDiagram
55
+ participant Reader
56
+ participant Docs
57
+ participant Search
58
+ Reader->>Docs: Open a page
59
+ Docs->>Search: Index the content
60
+ Search-->>Reader: Return results
61
+ \`\`\`
62
+
63
+ ### Subgraphs
64
+
65
+ \`\`\`mermaid placement="top-right"
66
+ flowchart LR
67
+ subgraph one
68
+ direction TB
69
+ top1[top] --> bottom1[bottom]
70
+ end
71
+ subgraph two
72
+ direction TB
73
+ top2[top] --> bottom2[bottom]
74
+ end
75
+ outside --> one
76
+ outside --> top2
77
+ \`\`\`
78
+
79
+ ## Interactive controls
80
+
81
+ Diagrams include zoom in and out, pan in four directions, reset the view, and full screen. You can also drag a diagram with your mouse to move it around.
82
+
83
+ By default the controls appear once a diagram is taller than 120px, since a diagram that already fits does not need them. Use the \`actions\` property to decide explicitly. Setting \`actions={false}\` turns off the whole interactive layer, including dragging.
84
+
85
+ ## Properties
86
+
87
+ <Field value="placement" type="string">
88
+ Where the controls sit. One of \`top-left\`, \`top-right\`, \`bottom-left\`, or \`bottom-right\`. Defaults to \`bottom-right\`.
89
+ </Field>
90
+
91
+ <Field value="actions" type="boolean">
92
+ Show or hide the controls. When set, this overrides the default behavior of showing them only on diagrams taller than 120px.
93
+ </Field>
94
+
95
+ Set properties on the opening fence, after the language:
96
+
97
+ \`\`\`\`mdx
98
+ \`\`\`mermaid placement="top-left" actions={true}
99
+ flowchart LR
100
+ A --> B
101
+ \`\`\`
102
+ \`\`\`\`
103
+
104
+ To hide the controls entirely:
105
+
106
+ \`\`\`\`mdx
107
+ \`\`\`mermaid actions={false}
108
+ flowchart LR
109
+ A --> B
110
+ \`\`\`
111
+ \`\`\`\`
112
+
113
+ \`\`\`mermaid actions={false}
114
+ flowchart LR
115
+ A --> B
116
+ \`\`\`
117
+
118
+ ## Layout
119
+
120
+ Diagrams are laid out with the [ELK](https://eclipse.dev/elk/) engine, which arranges nodes to reduce overlapping edges and keep large diagrams readable. It is always on, so no directive is needed to enable it.
121
+
122
+ If you are porting diagrams from another tool, a \`%%{init: ...}%%\` directive is read as a comment and ignored rather than causing an error.
123
+
124
+ ## Theming
125
+
126
+ Diagram colors come from CSS variables, so they follow your theme and the light/dark toggle without re-rendering. Override any of them in your own CSS to restyle diagrams:
127
+
128
+ \`\`\`css
129
+ :root {
130
+ --mermaid-bg: var(--color-light);
131
+ --mermaid-fg: var(--color-dark);
132
+ --mermaid-line: var(--color-grayDark);
133
+ --mermaid-accent: var(--color-accent);
134
+ --mermaid-muted: var(--color-grayDark);
135
+ --mermaid-surface: var(--color-grayLight);
136
+ --mermaid-border: var(--color-gray);
137
+ }
138
+ \`\`\`
139
+
140
+ ## Syntax reference
141
+
142
+ For the syntax of each supported diagram type, see the [Mermaid documentation](https://mermaid.js.org/intro/). Keep to the six types listed above.`;
@@ -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\n# Navigation\n\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)\n\nWhen no custom navigation is provided, Doccupine generates a structure based on each page's frontmatter.\n\n### Frontmatter fields\n\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- **navIcon**: Optional [Lucide](https://lucide.dev/icons) icon name shown next to the page's sidebar link.\n- **categoryIcon**: Optional Lucide icon name for the page's category header. The first page in a category that sets it wins.\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\n\nTo centrally define the entire sidebar, create a `navigation.json` at your project root (the same directory where you execute `npx doccupine`). When present, it takes priority over page frontmatter and fully controls the navigation structure.\n\n### Array format\n\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\": \"Getting Started\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Introduction\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n },\n {\n \"label\": \"Components\",\n \"links\": [\n { \"slug\": \"components\", \"title\": \"Components\" },\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 { \"slug\": \"color-swatches\", \"title\": \"Color Swatches\" }\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\": \"analytics\", \"title\": \"Analytics\" },\n { \"slug\": \"deployment-and-hosting\", \"title\": \"Deployment & Hosting\" },\n { \"slug\": \"authentication\", \"title\": \"Authentication\" }\n ]\n }\n]\n```\n\n### Object format (per-section)\n\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\n- **label**: The section header shown in the sidebar.\n- **icon**: Optional [Lucide](https://lucide.dev/icons) icon name shown next to the category header.\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 - **icon**: Optional Lucide icon name shown next to the link.\n - **links**: Optional array of nested child links. See [Nested navigation](#nested-navigation).\n\n## Icons\n\nAdd icons to categories and links to make the sidebar easier to scan. Icons use [Lucide](https://lucide.dev/icons) names in kebab-case (e.g. `rocket`, `book-open`, `settings`). Unknown names render nothing, so a typo never breaks the build.\n\nWith frontmatter, set `navIcon` on a page for its sidebar link and `categoryIcon` for its category:\n\n```text\n---\ntitle: \"Introduction\"\ncategory: \"Getting Started\"\ncategoryOrder: 1\norder: 1\nnavIcon: \"rocket\"\ncategoryIcon: \"book-open\"\n---\n```\n\nWith `navigation.json`, add an `icon` to any category or link:\n\n```json\n[\n {\n \"label\": \"Getting Started\",\n \"icon\": \"book-open\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Introduction\", \"icon\": \"rocket\" },\n { \"slug\": \"commands\", \"title\": \"Commands\", \"icon\": \"terminal\" }\n ]\n }\n]\n```\n\n## Nested navigation\n\nA link in `navigation.json` can hold its own `links` array to create a collapsible group. Groups expand and collapse on click and open automatically when one of their pages is active. Nesting can go as deep as you need.\n\n```json\n[\n {\n \"label\": \"Guides\",\n \"icon\": \"book-open\",\n \"links\": [\n { \"slug\": \"guides\", \"title\": \"Overview\", \"icon\": \"compass\" },\n {\n \"title\": \"Advanced\",\n \"icon\": \"settings\",\n \"links\": [\n { \"slug\": \"guides/caching\", \"title\": \"Caching\" },\n { \"slug\": \"guides/streaming\", \"title\": \"Streaming\" }\n ]\n }\n ]\n }\n]\n```\n\nA group can be a plain label - omit `slug` and it acts only as a collapsible header - or a real page, by adding a `slug` so the group title is also a link.\n\n<Callout type=\"note\">\n Nested groups are only available through `navigation.json`. Frontmatter navigation is always two levels: category and pages.\n</Callout>\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\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\n# Navigation\n\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)\n\nWhen no custom navigation is provided, Doccupine generates a structure based on each page's frontmatter.\n\n### Frontmatter fields\n\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- **navIcon**: Optional [Lucide](https://lucide.dev/icons) icon name shown next to the page's sidebar link.\n- **categoryIcon**: Optional Lucide icon name for the page's category header. The first page in a category that sets it wins.\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\n\nTo centrally define the entire sidebar, create a `navigation.json` at your project root (the same directory where you execute `npx doccupine`). When present, it takes priority over page frontmatter and fully controls the navigation structure.\n\n### Array format\n\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\": \"Getting Started\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Introduction\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" },\n { \"slug\": \"what-is-doccupine\", \"title\": \"What is Doccupine\" }\n ]\n },\n {\n \"label\": \"Components\",\n \"links\": [\n { \"slug\": \"components\", \"title\": \"Components\" },\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 { \"slug\": \"color-swatches\", \"title\": \"Color Swatches\" },\n { \"slug\": \"mermaid\", \"title\": \"Mermaid\" }\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\": \"analytics\", \"title\": \"Analytics\" },\n { \"slug\": \"deployment-and-hosting\", \"title\": \"Deployment & Hosting\" },\n { \"slug\": \"authentication\", \"title\": \"Authentication\" }\n ]\n }\n]\n```\n\n### Object format (per-section)\n\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\n- **label**: The section header shown in the sidebar.\n- **icon**: Optional [Lucide](https://lucide.dev/icons) icon name shown next to the category header.\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 - **icon**: Optional Lucide icon name shown next to the link.\n - **links**: Optional array of nested child links. See [Nested navigation](#nested-navigation).\n\n## Icons\n\nAdd icons to categories and links to make the sidebar easier to scan. Icons use [Lucide](https://lucide.dev/icons) names in kebab-case (e.g. `rocket`, `book-open`, `settings`). Unknown names render nothing, so a typo never breaks the build.\n\nWith frontmatter, set `navIcon` on a page for its sidebar link and `categoryIcon` for its category:\n\n```text\n---\ntitle: \"Introduction\"\ncategory: \"Getting Started\"\ncategoryOrder: 1\norder: 1\nnavIcon: \"rocket\"\ncategoryIcon: \"book-open\"\n---\n```\n\nWith `navigation.json`, add an `icon` to any category or link:\n\n```json\n[\n {\n \"label\": \"Getting Started\",\n \"icon\": \"book-open\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Introduction\", \"icon\": \"rocket\" },\n { \"slug\": \"commands\", \"title\": \"Commands\", \"icon\": \"terminal\" }\n ]\n }\n]\n```\n\n## Nested navigation\n\nA link in `navigation.json` can hold its own `links` array to create a collapsible group. Groups expand and collapse on click and open automatically when one of their pages is active. Nesting can go as deep as you need.\n\n```json\n[\n {\n \"label\": \"Guides\",\n \"icon\": \"book-open\",\n \"links\": [\n { \"slug\": \"guides\", \"title\": \"Overview\", \"icon\": \"compass\" },\n {\n \"title\": \"Advanced\",\n \"icon\": \"settings\",\n \"links\": [\n { \"slug\": \"guides/caching\", \"title\": \"Caching\" },\n { \"slug\": \"guides/streaming\", \"title\": \"Streaming\" }\n ]\n }\n ]\n }\n]\n```\n\nA group can be a plain label - omit `slug` and it acts only as a collapsible header - or a real page, by adding a `slug` so the group title is also a link.\n\n<Callout type=\"note\">\n Nested groups are only available through `navigation.json`. Frontmatter navigation is always two levels: category and pages.\n</Callout>\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\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.";
@@ -52,7 +52,8 @@ The simplest format is an array of categories. When using [sections](/sections),
52
52
  "label": "Getting Started",
53
53
  "links": [
54
54
  { "slug": "", "title": "Introduction" },
55
- { "slug": "commands", "title": "Commands" }
55
+ { "slug": "commands", "title": "Commands" },
56
+ { "slug": "what-is-doccupine", "title": "What is Doccupine" }
56
57
  ]
57
58
  },
58
59
  {
@@ -73,7 +74,8 @@ The simplest format is an array of categories. When using [sections](/sections),
73
74
  { "slug": "update", "title": "Update" },
74
75
  { "slug": "columns", "title": "Columns" },
75
76
  { "slug": "steps", "title": "Steps" },
76
- { "slug": "color-swatches", "title": "Color Swatches" }
77
+ { "slug": "color-swatches", "title": "Color Swatches" },
78
+ { "slug": "mermaid", "title": "Mermaid" }
77
79
  ]
78
80
  },
79
81
  {
@@ -0,0 +1 @@
1
+ export declare const whatIsDoccupineMdxTemplate = "---\ntitle: \"What is Doccupine\"\ndescription: \"Doccupine is a CLI that turns a folder of MDX files into a complete, production-ready documentation website - no frontend work required.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 2\n---\n\n# What is Doccupine\n\n**Doccupine** is a CLI tool that turns a directory of MDX files into a complete Next.js documentation website. It is less of a framework you assemble and more of a tool that does the assembling for you - you bring the content, Doccupine builds the site.\n\n```bash\nnpx doccupine\n```\n\n## Philosophy\n\nDoccupine was built on a simple belief: writing documentation should feel like writing, not like building a web app. Most docs frameworks hand you a pile of libraries and configuration and expect you to wire up rendering, navigation, theming, and search yourself. Doccupine makes those decisions for you and gets out of the way, so the only thing left to do is write.\n\n## Content first\n\nYou write standard Markdown and MDX. No React, no build configuration, no component wiring. Your navigation, theming, and search are all derived from your files and a handful of JSON config files. If you can write a Markdown file, you can ship a documentation site.\n\n## Batteries included\n\nEverything you expect from a great docs site works the moment you run the command - MDX rendering, an auto-generated sidebar, dark and light themes, 14+ built-in components, full-text search, an AI chat assistant, and an MCP server. Nothing to install, nothing to opt into.\n\n<Callout type=\"info\">\n Every element on this page - this callout, the cards below, the code block above - is a live example of what your docs get out of the box, with zero setup.\n</Callout>\n\n## You own the output\n\nDoccupine generates a real Next.js 16 app inside your project, not a hosted black box. Every page, layout, and API route is written to disk where you can read it, extend it, or deploy it anywhere Next.js runs. Doccupine scaffolds the site; you stay in control of it.\n\n## Instant feedback\n\nRun `npx doccupine` and it watches your files. Every time you save an MDX file, change a config value, or drop in a new font, the site regenerates and the dev server reloads. Your docs are always one save away from being live.\n\n## AI-native\n\nDocumentation is not only read by people anymore. Doccupine ships a RAG-powered chat assistant so readers can ask questions in natural language, and an MCP server so AI tools and agents can search your documentation directly. Your content is ready for both audiences from day one.\n\n## Opinionated, on purpose\n\nDoccupine makes the boring decisions - layout, typography, color, navigation structure - so you can spend your time on the words that matter. When you are ready to customize, simple JSON files let you adjust site metadata, navigation, theme, and fonts without touching a line of code.\n\n## When to use Doccupine\n\nDoccupine is built for anyone who needs a polished documentation site without becoming a frontend engineer.\n\n- Product and API documentation\n- Developer guides and tutorials\n- Internal knowledge bases and runbooks\n- Design systems and component references\n\nThere are two ways to run it:\n\n<Columns cols={2}>\n <Card title=\"Local CLI\" icon=\"terminal\" href=\"/\">\n `npx doccupine` scaffolds and serves the site on your machine, and you self-host the generated Next.js app anywhere.\n </Card>\n <Card title=\"Doccupine Platform\" icon=\"cloud\" href=\"/platform\">\n A managed, browser-based experience with a visual editor, one-click publishing, custom domains, and team collaboration - no local setup.\n </Card>\n</Columns>";
@@ -0,0 +1,68 @@
1
+ export const whatIsDoccupineMdxTemplate = `---
2
+ title: "What is Doccupine"
3
+ description: "Doccupine is a CLI that turns a folder of MDX files into a complete, production-ready documentation website - no frontend work required."
4
+ date: "2026-02-19"
5
+ category: "Getting Started"
6
+ categoryOrder: 0
7
+ order: 2
8
+ ---
9
+
10
+ # What is Doccupine
11
+
12
+ **Doccupine** is a CLI tool that turns a directory of MDX files into a complete Next.js documentation website. It is less of a framework you assemble and more of a tool that does the assembling for you - you bring the content, Doccupine builds the site.
13
+
14
+ \`\`\`bash
15
+ npx doccupine
16
+ \`\`\`
17
+
18
+ ## Philosophy
19
+
20
+ Doccupine was built on a simple belief: writing documentation should feel like writing, not like building a web app. Most docs frameworks hand you a pile of libraries and configuration and expect you to wire up rendering, navigation, theming, and search yourself. Doccupine makes those decisions for you and gets out of the way, so the only thing left to do is write.
21
+
22
+ ## Content first
23
+
24
+ You write standard Markdown and MDX. No React, no build configuration, no component wiring. Your navigation, theming, and search are all derived from your files and a handful of JSON config files. If you can write a Markdown file, you can ship a documentation site.
25
+
26
+ ## Batteries included
27
+
28
+ Everything you expect from a great docs site works the moment you run the command - MDX rendering, an auto-generated sidebar, dark and light themes, 14+ built-in components, full-text search, an AI chat assistant, and an MCP server. Nothing to install, nothing to opt into.
29
+
30
+ <Callout type="info">
31
+ Every element on this page - this callout, the cards below, the code block above - is a live example of what your docs get out of the box, with zero setup.
32
+ </Callout>
33
+
34
+ ## You own the output
35
+
36
+ Doccupine generates a real Next.js 16 app inside your project, not a hosted black box. Every page, layout, and API route is written to disk where you can read it, extend it, or deploy it anywhere Next.js runs. Doccupine scaffolds the site; you stay in control of it.
37
+
38
+ ## Instant feedback
39
+
40
+ Run \`npx doccupine\` and it watches your files. Every time you save an MDX file, change a config value, or drop in a new font, the site regenerates and the dev server reloads. Your docs are always one save away from being live.
41
+
42
+ ## AI-native
43
+
44
+ Documentation is not only read by people anymore. Doccupine ships a RAG-powered chat assistant so readers can ask questions in natural language, and an MCP server so AI tools and agents can search your documentation directly. Your content is ready for both audiences from day one.
45
+
46
+ ## Opinionated, on purpose
47
+
48
+ Doccupine makes the boring decisions - layout, typography, color, navigation structure - so you can spend your time on the words that matter. When you are ready to customize, simple JSON files let you adjust site metadata, navigation, theme, and fonts without touching a line of code.
49
+
50
+ ## When to use Doccupine
51
+
52
+ Doccupine is built for anyone who needs a polished documentation site without becoming a frontend engineer.
53
+
54
+ - Product and API documentation
55
+ - Developer guides and tutorials
56
+ - Internal knowledge bases and runbooks
57
+ - Design systems and component references
58
+
59
+ There are two ways to run it:
60
+
61
+ <Columns cols={2}>
62
+ <Card title="Local CLI" icon="terminal" href="/">
63
+ \`npx doccupine\` scaffolds and serves the site on your machine, and you self-host the generated Next.js app anywhere.
64
+ </Card>
65
+ <Card title="Doccupine Platform" icon="cloud" href="/platform">
66
+ A managed, browser-based experience with a visual editor, one-click publishing, custom domains, and team collaboration - no local setup.
67
+ </Card>
68
+ </Columns>`;
@@ -12,20 +12,21 @@ export const packageJsonTemplate = JSON.stringify({
12
12
  },
13
13
  dependencies: {
14
14
  "@langchain/anthropic": "^1.5.1",
15
- "@langchain/core": "^1.2.2",
15
+ "@langchain/core": "^1.2.3",
16
16
  "@langchain/google-genai": "^2.2.0",
17
17
  "@langchain/openai": "^1.5.5",
18
18
  "@mdx-js/react": "^3.1.1",
19
19
  "@modelcontextprotocol/sdk": "^1.29.0",
20
20
  "@posthog/react": "^1.10.3",
21
+ "beautiful-mermaid": "^1.1.3",
21
22
  "cherry-styled-components": "^0.2.11",
22
23
  langchain: "^1.5.3",
23
24
  "lucide-react": "^1.24.0",
24
25
  minisearch: "^7.2.0",
25
26
  next: "16.2.10",
26
27
  "next-mdx-remote": "^6.0.0",
27
- "posthog-js": "^1.399.2",
28
- "posthog-node": "^5.41.0",
28
+ "posthog-js": "^1.403.0",
29
+ "posthog-node": "^5.45.1",
29
30
  react: "19.2.7",
30
31
  "react-dom": "19.2.7",
31
32
  "rehype-highlight": "^7.0.2",
@@ -42,8 +43,8 @@ export const packageJsonTemplate = JSON.stringify({
42
43
  "@types/node": "^26",
43
44
  "@types/react": "^19",
44
45
  "@types/react-dom": "^19",
45
- "@typescript-eslint/eslint-plugin": "^8.63.0",
46
- "@typescript-eslint/parser": "^8.63.0",
46
+ "@typescript-eslint/eslint-plugin": "^8.64.0",
47
+ "@typescript-eslint/parser": "^8.64.0",
47
48
  "@typescript/native-preview": "^7.0.0-dev.20260707.2",
48
49
  eslint: "^10",
49
50
  "eslint-plugin-import": "^2.32.0",
@@ -52,7 +53,7 @@ export const packageJsonTemplate = JSON.stringify({
52
53
  "eslint-plugin-react-hooks": "^7.1.1",
53
54
  globals: "^17.7.0",
54
55
  prettier: "^3.9.5",
55
- tsx: "^4.23.0",
56
+ tsx: "^4.23.1",
56
57
  typescript: "npm:@typescript/typescript6@^6.0.2",
57
58
  },
58
59
  }, null, 2) + "\n";
@@ -0,0 +1 @@
1
+ export declare const mermaidTemplate = "import \"server-only\";\nimport { renderMermaidSVG } from \"beautiful-mermaid\";\n\nconst DIAGRAM_OPTIONS = {\n bg: \"var(--mermaid-bg)\",\n fg: \"var(--mermaid-fg)\",\n line: \"var(--mermaid-line)\",\n accent: \"var(--mermaid-accent)\",\n muted: \"var(--mermaid-muted)\",\n surface: \"var(--mermaid-surface)\",\n border: \"var(--mermaid-border)\",\n transparent: true,\n};\n\nexport type MermaidResult =\n | { ok: true; svg: string; width: number | null }\n | { ok: false; error: string };\n\nfunction normalizeSvg(svg: string): {\n ok: true;\n svg: string;\n width: number | null;\n} {\n const openTag = /^<svg\\b[^>]*>/.exec(svg);\n if (!openTag) return { ok: true, svg, width: null };\n\n const widthMatch = /\\swidth=\"([\\d.]+)\"/.exec(openTag[0]);\n const width = widthMatch ? Number.parseFloat(widthMatch[1]) : null;\n\n const stripped = openTag[0].replace(/\\s(?:width|height)=\"[^\"]*\"/g, \"\");\n return {\n ok: true,\n svg: stripped + svg.slice(openTag[0].length),\n width: width !== null && Number.isFinite(width) ? width : null,\n };\n}\n\nexport function renderDiagram(code: string): MermaidResult {\n try {\n return normalizeSvg(renderMermaidSVG(code, DIAGRAM_OPTIONS));\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n";
@@ -0,0 +1,48 @@
1
+ export const mermaidTemplate = `import "server-only";
2
+ import { renderMermaidSVG } from "beautiful-mermaid";
3
+
4
+ const DIAGRAM_OPTIONS = {
5
+ bg: "var(--mermaid-bg)",
6
+ fg: "var(--mermaid-fg)",
7
+ line: "var(--mermaid-line)",
8
+ accent: "var(--mermaid-accent)",
9
+ muted: "var(--mermaid-muted)",
10
+ surface: "var(--mermaid-surface)",
11
+ border: "var(--mermaid-border)",
12
+ transparent: true,
13
+ };
14
+
15
+ export type MermaidResult =
16
+ | { ok: true; svg: string; width: number | null }
17
+ | { ok: false; error: string };
18
+
19
+ function normalizeSvg(svg: string): {
20
+ ok: true;
21
+ svg: string;
22
+ width: number | null;
23
+ } {
24
+ const openTag = /^<svg\\b[^>]*>/.exec(svg);
25
+ if (!openTag) return { ok: true, svg, width: null };
26
+
27
+ const widthMatch = /\\swidth="([\\d.]+)"/.exec(openTag[0]);
28
+ const width = widthMatch ? Number.parseFloat(widthMatch[1]) : null;
29
+
30
+ const stripped = openTag[0].replace(/\\s(?:width|height)="[^"]*"/g, "");
31
+ return {
32
+ ok: true,
33
+ svg: stripped + svg.slice(openTag[0].length),
34
+ width: width !== null && Number.isFinite(width) ? width : null,
35
+ };
36
+ }
37
+
38
+ export function renderDiagram(code: string): MermaidResult {
39
+ try {
40
+ return normalizeSvg(renderMermaidSVG(code, DIAGRAM_OPTIONS));
41
+ } catch (error) {
42
+ return {
43
+ ok: false,
44
+ error: error instanceof Error ? error.message : String(error),
45
+ };
46
+ }
47
+ }
48
+ `;
@@ -0,0 +1 @@
1
+ export declare const parseCodeMetaTemplate = "export type CodeMetaValue = string | boolean;\n\nexport function parseCodeMeta(meta?: string): Record<string, CodeMetaValue> {\n const out: Record<string, CodeMetaValue> = {};\n if (!meta) return out;\n\n const pattern = /([A-Za-z_][\\w-]*)(?:=(?:\"([^\"]*)\"|'([^']*)'|\\{([^}]*)\\}))?/g;\n\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(meta)) !== null) {\n const [, key, doubleQuoted, singleQuoted, braced] = match;\n\n if (doubleQuoted !== undefined) {\n out[key] = doubleQuoted;\n } else if (singleQuoted !== undefined) {\n out[key] = singleQuoted;\n } else if (braced !== undefined) {\n const value = braced.trim();\n out[key] =\n value === \"true\"\n ? true\n : value === \"false\"\n ? false\n : value.replace(/^[\"']|[\"']$/g, \"\");\n } else {\n out[key] = true;\n }\n }\n\n return out;\n}\n";
@@ -0,0 +1,32 @@
1
+ export const parseCodeMetaTemplate = `export type CodeMetaValue = string | boolean;
2
+
3
+ export function parseCodeMeta(meta?: string): Record<string, CodeMetaValue> {
4
+ const out: Record<string, CodeMetaValue> = {};
5
+ if (!meta) return out;
6
+
7
+ const pattern = /([A-Za-z_][\\w-]*)(?:=(?:"([^"]*)"|'([^']*)'|\\{([^}]*)\\}))?/g;
8
+
9
+ let match: RegExpExecArray | null;
10
+ while ((match = pattern.exec(meta)) !== null) {
11
+ const [, key, doubleQuoted, singleQuoted, braced] = match;
12
+
13
+ if (doubleQuoted !== undefined) {
14
+ out[key] = doubleQuoted;
15
+ } else if (singleQuoted !== undefined) {
16
+ out[key] = singleQuoted;
17
+ } else if (braced !== undefined) {
18
+ const value = braced.trim();
19
+ out[key] =
20
+ value === "true"
21
+ ? true
22
+ : value === "false"
23
+ ? false
24
+ : value.replace(/^["']|["']$/g, "");
25
+ } else {
26
+ out[key] = true;
27
+ }
28
+ }
29
+
30
+ return out;
31
+ }
32
+ `;
@@ -0,0 +1 @@
1
+ export declare const rehypeCodeMetaTemplate = "interface MetaNode {\n type: string;\n tagName?: string;\n data?: { meta?: string };\n properties?: Record<string, unknown>;\n children?: MetaNode[];\n}\n\nexport function rehypeCodeMeta() {\n return (tree: MetaNode) => {\n const visit = (node: MetaNode) => {\n if (node.type === \"element\" && node.tagName === \"code\") {\n const meta = node.data?.meta;\n if (typeof meta === \"string\" && meta.length > 0) {\n node.properties = { ...node.properties, meta };\n }\n }\n node.children?.forEach(visit);\n };\n visit(tree);\n };\n}\n";
@@ -0,0 +1,23 @@
1
+ export const rehypeCodeMetaTemplate = `interface MetaNode {
2
+ type: string;
3
+ tagName?: string;
4
+ data?: { meta?: string };
5
+ properties?: Record<string, unknown>;
6
+ children?: MetaNode[];
7
+ }
8
+
9
+ export function rehypeCodeMeta() {
10
+ return (tree: MetaNode) => {
11
+ const visit = (node: MetaNode) => {
12
+ if (node.type === "element" && node.tagName === "code") {
13
+ const meta = node.data?.meta;
14
+ if (typeof meta === "string" && meta.length > 0) {
15
+ node.properties = { ...node.properties, meta };
16
+ }
17
+ }
18
+ node.children?.forEach(visit);
19
+ };
20
+ visit(tree);
21
+ };
22
+ }
23
+ `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doccupine",
3
- "version": "0.0.124",
3
+ "version": "0.0.126",
4
4
  "description": "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.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {