@lupinum/ginko-docs 0.4.0-rc.9 → 0.5.0

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 (304) hide show
  1. package/CHANGELOG.md +141 -0
  2. package/LICENSE +1 -1
  3. package/README.md +300 -53
  4. package/app/app.config.ts +44 -55
  5. package/app/assets/docs.css +619 -0
  6. package/app/components/DocsBanner.vue +29 -0
  7. package/app/components/DocsExample.vue +43 -0
  8. package/app/components/DocsFooter.vue +19 -0
  9. package/app/components/DocsHeader.vue +113 -0
  10. package/app/components/DocsIcon.vue +12 -0
  11. package/app/components/DocsLanding.vue +58 -0
  12. package/app/components/DocsLanguage.vue +40 -0
  13. package/app/components/DocsNavSheet.vue +37 -0
  14. package/app/components/DocsNavTree.vue +38 -0
  15. package/app/components/DocsPage.vue +88 -0
  16. package/app/components/DocsPageActions.vue +47 -0
  17. package/app/components/DocsPageEnd.ts +12 -0
  18. package/app/components/DocsPost.vue +58 -0
  19. package/app/components/DocsSearch.vue +136 -0
  20. package/app/components/DocsShell.vue +36 -0
  21. package/app/components/DocsSidebar.vue +19 -0
  22. package/app/components/DocsSidebarEnd.ts +4 -0
  23. package/app/components/DocsTable.vue +11 -0
  24. package/app/components/DocsThemeToggle.vue +45 -0
  25. package/app/components/DocsToc.vue +73 -0
  26. package/app/composables/useDocs.ts +53 -0
  27. package/app/composables/useDocsBlog.ts +33 -0
  28. package/app/composables/useDocsCopy.ts +17 -0
  29. package/app/composables/useDocsFrame.ts +11 -0
  30. package/app/composables/useDocsPopover.ts +36 -0
  31. package/app/composables/useDocsSite.ts +31 -0
  32. package/app/docs-pages/blog.vue +55 -0
  33. package/app/docs-pages/changelog.vue +35 -0
  34. package/app/docs-pages/doc.vue +16 -0
  35. package/app/docs-pages/docs.vue +9 -0
  36. package/app/docs-pages/index.vue +12 -0
  37. package/app/docs-pages/post.vue +8 -0
  38. package/app/error.vue +38 -115
  39. package/app/layouts/default.vue +29 -7
  40. package/app/lib/blogTypes.ts +8 -0
  41. package/app/lib/docsFirst.ts +11 -0
  42. package/app/lib/docsInit.ts +18 -0
  43. package/app/lib/docsNav.ts +36 -0
  44. package/app/lib/docsPage.ts +84 -0
  45. package/app/lib/markdownComponents.ts +15 -0
  46. package/app/lib/previewToc.ts +18 -0
  47. package/dist/config.d.mts +252 -0
  48. package/dist/config.d.ts +252 -0
  49. package/dist/config.mjs +83 -0
  50. package/dist/icons.d.mts +38 -0
  51. package/dist/icons.d.ts +38 -0
  52. package/dist/icons.mjs +175 -0
  53. package/dist/pages.d.mts +5 -0
  54. package/dist/pages.d.ts +5 -0
  55. package/dist/pages.mjs +68 -0
  56. package/i18n/de.json +1 -0
  57. package/i18n/en.json +1 -0
  58. package/i18n/fr.json +1 -0
  59. package/icons/README.md +2 -0
  60. package/icons/bluesky.svg +1 -0
  61. package/icons/claude.svg +1 -0
  62. package/icons/discord.svg +1 -0
  63. package/icons/github.svg +1 -0
  64. package/icons/linkedin.svg +1 -0
  65. package/icons/mastodon.svg +1 -0
  66. package/icons/openai.svg +1 -0
  67. package/icons/x.svg +1 -0
  68. package/icons/youtube.svg +1 -0
  69. package/nuxt.config.ts +22 -212
  70. package/package.json +44 -76
  71. package/public/_docs/fonts/LICENSE +188 -0
  72. package/public/_docs/fonts/inter-latin-wght-normal.woff2 +0 -0
  73. package/public/_docs/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  74. package/public/_docs/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
  75. package/server/feeds/blog-locale.get.ts +9 -0
  76. package/server/feeds/blog.get.ts +4 -0
  77. package/server/lib/blogFeed.ts +35 -0
  78. package/server/mcp/handler.ts +108 -0
  79. package/server/routes/__ginko/docs-mcp.ts +35 -0
  80. package/shared/layerRoutes.ts +66 -0
  81. package/shared/paths.ts +4 -0
  82. package/app/app.vue +0 -98
  83. package/app/assets/css/prose.css +0 -3240
  84. package/app/assets/css/tailwind.css +0 -394
  85. package/app/assets/css/theme-palettes.css +0 -309
  86. package/app/assets/css/theme-presets.css +0 -141
  87. package/app/components/OgImage/GinkoDocs.satori.vue +0 -238
  88. package/app/components/content/DocumentPageShell.vue +0 -55
  89. package/app/components/content/Feedback.vue +0 -102
  90. package/app/components/content/ImageZoomDialog.vue +0 -84
  91. package/app/components/content/PageMarkdownCopy.vue +0 -104
  92. package/app/components/content/imageZoom.ts +0 -25
  93. package/app/components/mdc/MdcAccordion.vue +0 -67
  94. package/app/components/mdc/MdcAccordionItem.vue +0 -42
  95. package/app/components/mdc/MdcApi.vue +0 -159
  96. package/app/components/mdc/MdcAside.vue +0 -23
  97. package/app/components/mdc/MdcCallout.vue +0 -61
  98. package/app/components/mdc/MdcCard.vue +0 -175
  99. package/app/components/mdc/MdcCards.vue +0 -30
  100. package/app/components/mdc/MdcCenter.vue +0 -71
  101. package/app/components/mdc/MdcCodeGroup.vue +0 -197
  102. package/app/components/mdc/MdcCodeTree.vue +0 -234
  103. package/app/components/mdc/MdcCollapse.vue +0 -61
  104. package/app/components/mdc/MdcColumn.vue +0 -70
  105. package/app/components/mdc/MdcDropcap.vue +0 -84
  106. package/app/components/mdc/MdcError.vue +0 -23
  107. package/app/components/mdc/MdcExcerpt.vue +0 -26
  108. package/app/components/mdc/MdcFigure.vue +0 -85
  109. package/app/components/mdc/MdcFiles.vue +0 -120
  110. package/app/components/mdc/MdcIdea.vue +0 -17
  111. package/app/components/mdc/MdcInfo.vue +0 -17
  112. package/app/components/mdc/MdcInlineToc.vue +0 -51
  113. package/app/components/mdc/MdcKbd.vue +0 -10
  114. package/app/components/mdc/MdcLayout.vue +0 -57
  115. package/app/components/mdc/MdcNote.vue +0 -17
  116. package/app/components/mdc/MdcQuiz.vue +0 -241
  117. package/app/components/mdc/MdcQuizQuestion.vue +0 -221
  118. package/app/components/mdc/MdcReadMore.vue +0 -70
  119. package/app/components/mdc/MdcSteps.vue +0 -59
  120. package/app/components/mdc/MdcSuccess.vue +0 -23
  121. package/app/components/mdc/MdcTab.vue +0 -17
  122. package/app/components/mdc/MdcTabs.vue +0 -150
  123. package/app/components/mdc/MdcTimeline.vue +0 -17
  124. package/app/components/mdc/MdcTimelineItem.vue +0 -40
  125. package/app/components/mdc/MdcWarning.vue +0 -23
  126. package/app/components/mdc/api.utils.ts +0 -132
  127. package/app/components/mdc/code-tree.utils.ts +0 -22
  128. package/app/components/mdc/icons.ts +0 -10
  129. package/app/components/mdc/quiz.utils.ts +0 -38
  130. package/app/components/prose/ProseA.vue +0 -27
  131. package/app/components/prose/ProseBlockquote.vue +0 -30
  132. package/app/components/prose/ProseCode.vue +0 -14
  133. package/app/components/prose/ProseEm.vue +0 -14
  134. package/app/components/prose/ProseH1.vue +0 -18
  135. package/app/components/prose/ProseH2.vue +0 -29
  136. package/app/components/prose/ProseH3.vue +0 -29
  137. package/app/components/prose/ProseH4.vue +0 -29
  138. package/app/components/prose/ProseH5.vue +0 -15
  139. package/app/components/prose/ProseH6.vue +0 -15
  140. package/app/components/prose/ProseHr.vue +0 -12
  141. package/app/components/prose/ProseImg.vue +0 -55
  142. package/app/components/prose/ProseLi.vue +0 -14
  143. package/app/components/prose/ProseOl.vue +0 -14
  144. package/app/components/prose/ProseP.vue +0 -14
  145. package/app/components/prose/ProsePre.vue +0 -180
  146. package/app/components/prose/ProseStrong.vue +0 -14
  147. package/app/components/prose/ProseTable.vue +0 -18
  148. package/app/components/prose/ProseTbody.vue +0 -14
  149. package/app/components/prose/ProseTd.vue +0 -14
  150. package/app/components/prose/ProseTh.vue +0 -14
  151. package/app/components/prose/ProseThead.vue +0 -14
  152. package/app/components/prose/ProseTr.vue +0 -14
  153. package/app/components/prose/ProseUl.vue +0 -14
  154. package/app/components/site/ModeToggle.vue +0 -81
  155. package/app/components/site/SiteBanner.vue +0 -97
  156. package/app/components/site/SiteFooter.vue +0 -90
  157. package/app/components/site/SiteHeader.vue +0 -371
  158. package/app/components/site/SiteHeroCode.vue +0 -173
  159. package/app/components/site/SiteInteractionLayer.vue +0 -42
  160. package/app/components/site/SiteLocaleSwitcher.vue +0 -190
  161. package/app/components/site/SiteLogoMark.vue +0 -12
  162. package/app/components/site/SiteSkipLink.vue +0 -14
  163. package/app/components/site/SiteSocialLinks.vue +0 -33
  164. package/app/components/site/header-utils.ts +0 -3
  165. package/app/components/site/mode-toggle.utils.ts +0 -18
  166. package/app/components/ui/badge/Badge.vue +0 -28
  167. package/app/components/ui/badge/index.ts +0 -24
  168. package/app/components/ui/button/Button.vue +0 -31
  169. package/app/components/ui/button/index.ts +0 -35
  170. package/app/components/ui/collapsible/Collapsible.vue +0 -15
  171. package/app/components/ui/collapsible/CollapsibleContent.vue +0 -25
  172. package/app/components/ui/collapsible/CollapsibleTrigger.vue +0 -12
  173. package/app/components/ui/collapsible/index.ts +0 -3
  174. package/app/components/ui/dropdown-menu/DropdownMenu.vue +0 -15
  175. package/app/components/ui/dropdown-menu/DropdownMenuContent.vue +0 -50
  176. package/app/components/ui/dropdown-menu/DropdownMenuItem.vue +0 -41
  177. package/app/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +0 -15
  178. package/app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +0 -37
  179. package/app/components/ui/dropdown-menu/DropdownMenuSeparator.vue +0 -23
  180. package/app/components/ui/dropdown-menu/DropdownMenuTrigger.vue +0 -14
  181. package/app/components/ui/dropdown-menu/index.ts +0 -7
  182. package/app/components/ui/kbd/Kbd.vue +0 -23
  183. package/app/components/ui/kbd/index.ts +0 -21
  184. package/app/components/ui/scroll-area/ScrollArea.vue +0 -39
  185. package/app/components/ui/scroll-area/ScrollBar.vue +0 -33
  186. package/app/components/ui/scroll-area/index.ts +0 -2
  187. package/app/components/ui/separator/Separator.vue +0 -27
  188. package/app/components/ui/separator/index.ts +0 -1
  189. package/app/components/ui/sheet/Sheet.vue +0 -15
  190. package/app/components/ui/sheet/SheetContent.vue +0 -59
  191. package/app/components/ui/sheet/SheetDescription.vue +0 -21
  192. package/app/components/ui/sheet/SheetOverlay.vue +0 -26
  193. package/app/components/ui/sheet/SheetTitle.vue +0 -21
  194. package/app/components/ui/sheet/SheetTrigger.vue +0 -12
  195. package/app/components/ui/sheet/index.ts +0 -5
  196. package/app/components/ui/tabs/Tabs.vue +0 -24
  197. package/app/components/ui/tabs/TabsList.vue +0 -26
  198. package/app/components/ui/tabs/TabsTrigger.vue +0 -28
  199. package/app/components/ui/tabs/index.ts +0 -3
  200. package/app/composables/site-navigation.utils.ts +0 -133
  201. package/app/composables/useCanonicalUrl.ts +0 -9
  202. package/app/composables/useContentRouteAlternates.ts +0 -35
  203. package/app/composables/useGinkoAnalytics.ts +0 -52
  204. package/app/composables/useGinkoDocsConfig.ts +0 -6
  205. package/app/composables/useGinkoOgImage.ts +0 -20
  206. package/app/composables/useLocalizedPath.ts +0 -12
  207. package/app/composables/useLocalizedRouteSwitch.ts +0 -31
  208. package/app/composables/useMetaKey.ts +0 -18
  209. package/app/composables/usePageMarkdownActions.ts +0 -79
  210. package/app/composables/useProseAppearance.ts +0 -24
  211. package/app/composables/useSchemaJsonLd.ts +0 -25
  212. package/app/composables/useSiteNavigation.ts +0 -64
  213. package/app/config/site.utils.ts +0 -36
  214. package/app/features/docs/components/DocsBreadcrumb.vue +0 -37
  215. package/app/features/docs/components/DocsContributeLinks.vue +0 -75
  216. package/app/features/docs/components/DocsMobileToc.vue +0 -108
  217. package/app/features/docs/components/DocsPageContent.vue +0 -234
  218. package/app/features/docs/components/DocsPageNav.vue +0 -57
  219. package/app/features/docs/components/DocsSidebar.vue +0 -145
  220. package/app/features/docs/components/DocsSidebarDropdown.vue +0 -70
  221. package/app/features/docs/components/DocsSidebarItem.vue +0 -122
  222. package/app/features/docs/components/DocsSidebarList.vue +0 -35
  223. package/app/features/docs/components/DocsSidebarRow.vue +0 -27
  224. package/app/features/docs/components/DocsSidebarTabs.vue +0 -59
  225. package/app/features/docs/components/DocsToc.vue +0 -106
  226. package/app/features/docs/composables/useDocsNavigation.ts +0 -29
  227. package/app/features/docs/composables/useDocsNavigationData.ts +0 -18
  228. package/app/features/docs/composables/useRevealActive.ts +0 -58
  229. package/app/features/docs/composables/useScrollspy.ts +0 -135
  230. package/app/features/docs/docs-navigation.ts +0 -157
  231. package/app/features/docs/toc-context.ts +0 -6
  232. package/app/features/search/command-center.ts +0 -110
  233. package/app/features/search/components/SiteCommandCenter.vue +0 -359
  234. package/app/features/search/components/SiteSearchPageHighlight.vue +0 -126
  235. package/app/features/search/useCommandCenter.ts +0 -292
  236. package/app/layouts/blog.vue +0 -15
  237. package/app/layouts/docs.vue +0 -20
  238. package/app/lib/errors.ts +0 -37
  239. package/app/lib/schema-org.ts +0 -38
  240. package/app/pages/blog/[slug].vue +0 -228
  241. package/app/pages/blog/index.vue +0 -130
  242. package/app/pages/docs/[...slug].vue +0 -10
  243. package/app/pages/docs/index.vue +0 -19
  244. package/app/pages/index.vue +0 -278
  245. package/app/plugins/ginko-docs-theme.ts +0 -14
  246. package/app/plugins/ssr-width.ts +0 -6
  247. package/app/utils/content.ts +0 -67
  248. package/app/utils/file-icons.ts +0 -90
  249. package/app/utils/index.ts +0 -7
  250. package/app/utils/repository.ts +0 -20
  251. package/components.ts +0 -9
  252. package/content-collections.ts +0 -89
  253. package/content.js +0 -200
  254. package/content.ts +0 -104
  255. package/i18n/i18n.config.ts +0 -10
  256. package/i18n/locales.ts +0 -81
  257. package/i18n/messages/global/banner.ts +0 -8
  258. package/i18n/messages/global/blog.ts +0 -18
  259. package/i18n/messages/global/command.ts +0 -49
  260. package/i18n/messages/global/docs.ts +0 -36
  261. package/i18n/messages/global/errors.ts +0 -36
  262. package/i18n/messages/global/feedback.ts +0 -11
  263. package/i18n/messages/global/index.ts +0 -21
  264. package/i18n/messages/global/nav.ts +0 -26
  265. package/i18n/messages/global/site.ts +0 -4
  266. package/i18n/messages/global/theme.ts +0 -9
  267. package/i18n/messages/index.ts +0 -20
  268. package/i18n/messages/localize.ts +0 -35
  269. package/i18n/routes.ts +0 -33
  270. package/icon-bundle.ts +0 -116
  271. package/index.d.ts +0 -37
  272. package/modules/analytics-boundary.ts +0 -23
  273. package/modules/feature-routing.ts +0 -68
  274. package/modules/syntax-highlighting.ts +0 -120
  275. package/public/fonts/public-sans/LICENSE +0 -93
  276. package/public/fonts/public-sans/README.md +0 -12
  277. package/public/fonts/public-sans/public-sans-400-normal-latin.woff +0 -0
  278. package/public/fonts/public-sans/public-sans-500-normal-latin.woff +0 -0
  279. package/public/fonts/public-sans/public-sans-600-normal-latin.woff +0 -0
  280. package/public/fonts/public-sans/public-sans-700-normal-latin.woff +0 -0
  281. package/runtime/generate-favicons.mjs +0 -124
  282. package/runtime/server/agent-markdown.ts +0 -19
  283. package/server/api/_ginko-docs/redirects.get.ts +0 -28
  284. package/server/mcp/tools/get-page.ts +0 -14
  285. package/server/mcp/tools/list-pages.ts +0 -10
  286. package/server/middleware/redirects.ts +0 -22
  287. package/server/plugins/agent-markdown.ts +0 -6
  288. package/server/plugins/sitemap-policy.ts +0 -12
  289. package/server/routes/.well-known/ai-catalog.json.get.ts +0 -10
  290. package/server/routes/[locale]/blog/rss.xml.get.ts +0 -13
  291. package/server/routes/blog/rss.xml.get.ts +0 -5
  292. package/server/routes/mcp/server-card.get.ts +0 -14
  293. package/server/utils/blog-feed.ts +0 -51
  294. package/server/utils/feed.ts +0 -70
  295. package/server/utils/mcp-server-card.ts +0 -45
  296. package/server/utils/redirects.ts +0 -38
  297. package/server/utils/redirects.utils.ts +0 -58
  298. package/server/utils/sitemap.ts +0 -45
  299. package/shared/route-slugs.ts +0 -5
  300. package/shared/theme-palettes.ts +0 -37
  301. package/shared/theme-presets.ts +0 -3
  302. package/shared/types/app-config.ts +0 -172
  303. package/shared/types/nuxt-config.ts +0 -14
  304. package/tags.ts +0 -192
package/CHANGELOG.md ADDED
@@ -0,0 +1,141 @@
1
+ # @lupinum/ginko-docs
2
+
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add public ways to customize the docs: `<DocsShell>` for a site's own pages in the docs frame, the override points `DocsPageEnd` and `DocsSidebarEnd`, and `docs: { search: false }`.
8
+
9
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add a docs frame for sites that embed the docs in their own layout: no framed panel, the search above the navigation, a phone bar with the navigation as a sheet, and `--docs-gutter` to line the docs up with the site's container.
10
+
11
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add `homePages({ locales })` to `@lupinum/ginko-docs/config`: the start page by locale, with the main locale at `/`.
12
+
13
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Change the docs layer to draw icons itself instead of with @nuxt/icon: pages outside the docs no longer download an icon library (about 16 KB gzip less on every page of a site that embeds the docs), and docs pages load only the icons they use. Icon names work as before (any installed Iconify set). The build finds them in your Markdown front matter and component attributes (not in prose or code blocks), in YAML and JSON content, in `app.config.ts` and in your own `app/` components (`<Icon name="lucide:x" />`); it reads all locales and ignores commented-out code. A name built at runtime (a variable) is not found, so write it once as a literal; a name that is not installed logs one build warning with its file. A site's own `@nuxt/icon` still wins over the layer's `Icon`. Remove the `icon` options from your nuxt.config if you set any. The icon hints in the editor now say "needs a global Icon component".
14
+
15
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add route links outside Markdown: the start page's buttons and cards, `nav`, `footer.links` and `banner.href` take `$docs.<page>` and `$page.<key>`, which lead to the page in the reader's language.
16
+
17
+ - [#24](https://github.com/lupinum-dev/ginko/pull/24) [`c28d1e3`](https://github.com/lupinum-dev/ginko/commit/c28d1e3e4ba1e558f8c71d7b69961f7474a221d1) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add `source: 'platform'` to docsCollection, docsHome, blogCollections and changelogCollection, so docs content can be edited in Ginko Studio; the default stays `'files'`.
18
+
19
+ ### Patch Changes
20
+
21
+ - [#21](https://github.com/lupinum-dev/ginko/pull/21) [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add `breadcrumbJsonLd(steps, siteUrl)` to `@lupinum/ginko`: a JSON-LD BreadcrumbList from steps with `title` and `path`, such as the nodes of `useGinkoBreadcrumbs` (templates/_features/site/app/composables/usePageSeo.ts uses it).
22
+
23
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix the 404 page's main-language link ignoring the site's i18n strategy, and name the language in the reader's language
24
+
25
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix the focus ring of the default theme in light mode: emerald-700 instead of emerald-500, 5.5:1 against the page instead of 2.5:1.
26
+
27
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix layout shift on first load of a docs page: the standalone layout preloads Inter, so text no longer re-wraps when the font arrives.
28
+
29
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add French texts to the docs layer.
30
+
31
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix the "not translated" note in the language menu: screen readers read it in the page's language. An empty changelog now says where to add releases.
32
+
33
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix English fallback text on translated docs pages being read in the page language, and add a link to the main-language page on a docs 404 under another language
34
+
35
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add CollectionPage JSON-LD and a description to the changelog page, and CollectionPage JSON-LD to the blog list.
36
+
37
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix tables with three columns on phones narrower than 360 px: the last column keeps its width and the table scrolls, instead of showing a few letters per line.
38
+
39
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix docs tables, the home feature list and the install box on phones.
40
+
41
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Change the phone header and menu of the docs layer: the light/dark button stays in the header, and the menu lists the languages as links at its top, one tap each.
42
+
43
+ - [#21](https://github.com/lupinum-dev/ginko/pull/21) [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Change the JSON-LD of a blog post from Article to BlogPosting, built by `postJsonLd` of `@lupinum/ginko/basics`, with the post's tags as keywords.
44
+
45
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix route links outside Markdown (nav, footer, banner, start page): they lead to the main-language page when the current language has no such doc, instead of a raw `$docs…` address.
46
+
47
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix the docs layer adding a second blog, blog feed or changelog at /blog and /changelog to a site that has its own: it now adds them only at the address of your posts and changelog and only when you have no page there.
48
+
49
+ A changelog page needs `changelog: changelogPages({ locales })` in `pages` (or a `route` on the changelog brick); without an address the build warns once and the layer adds no changelog. The layer now decides after all of your pages are known, so a page that the page-paths module moves to `/blog` also counts as yours, and its links to the blog and changelog follow the addresses you configured.
50
+
51
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix short tables in the docs ending before the edge of their frame: the rows and the header now fill it.
52
+
53
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add a note to the language menu for a language that has no version of the page: "Not translated: opens the start page".
54
+
55
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix wide tables, long titles and the previous and next links making docs pages scroll or squeeze text on phones
56
+
57
+ - [#21](https://github.com/lupinum-dev/ginko/pull/21) [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Change Markdown refs in page state to carry no table of contents: read `toc` from the loaded text, `(await useGinkoMarkdown(() => entry.value.data.body)).value?.toc`.
58
+
59
+ - [#23](https://github.com/lupinum-dev/ginko/pull/23) [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add `releaseAnchor(version)` to `@lupinum/ginko/basics`: the anchor of a release on a changelog page (`4.6.0` → `v4-6-0`). The changelog page of `@lupinum/ginko-docs` and the changelog feature of the templates (templates/_features/changelog/app/composables/useChangelog.ts, server/middleware/changelog-feed.ts) use it, so both keep the same public addresses.
60
+ - Updated dependencies [[`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`c28d1e3`](https://github.com/lupinum-dev/ginko/commit/c28d1e3e4ba1e558f8c71d7b69961f7474a221d1), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`7b165c2`](https://github.com/lupinum-dev/ginko/commit/7b165c25e17ed2f4fb50e8054febf618a6af10d7), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991), [`80f93a4`](https://github.com/lupinum-dev/ginko/commit/80f93a4f6bd171e1146b929913254039becdd991)]:
61
+ - @lupinum/ginko@0.5.0
62
+ - @lupinum/ginko-components@0.5.0
63
+ - @lupinum/ginko-content@0.5.0
64
+ - @lupinum/ginko-i18n@0.5.0
65
+
66
+ ## 0.4.0
67
+
68
+ ### Minor Changes
69
+
70
+ - [`ea2ea13`](https://github.com/lupinum-dev/ginko/commit/ea2ea133997f2011ad0d43f77a0f1dc75605923e) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add Ginko 0.4, the first release: one content system for Nuxt websites, from Markdown files in Git to a hosted platform.
71
+
72
+ Owners, staff and AI agents edit the same content. All seven packages release together under one version. It starts at 0.4 because `@lupinum/ginko-content` and `@lupinum/ginko-docs` already published an older, unrelated line up to 0.3. Until 1.0, a minor version (0.4 → 0.5) may contain breaking changes; the changelog names each one and how to update.
73
+
74
+ Requirements: Node 22.18+, 24 or 26, and Nuxt 4.6+ or Nuxt 5 (tested on its nightly until it is released). Start a site with `npm create ginko@latest my-site`; the documentation explains every step.
75
+
76
+ **Public API**
77
+
78
+ - `@lupinum/ginko`: `defineSite`, `single`, `collection`, `f`, `defineComponents`, `formatMoney`, `plainText`, `safeHref`, `startOfWeek` and the documented types. Imported, not auto-imported.
79
+ - `@lupinum/ginko/nuxt`: the module, the `useGinko*` composables (everything that needs a Nuxt app starts with `useGinko`), `<GinkoMarkdown>` and `<GinkoImage>`. `@lupinum/ginko/vue`: `<GinkoMarkdown>` for any Vue app. `@lupinum/ginko/search`: `loadIndex` and `search`.
80
+ - `@lupinum/ginko/internal` and `@lupinum/ginko/internal/search` are for Ginko's own packages and have no stability promise.
81
+ - The `ginko` CLI: `check [--offline]`, `release` and `export [folder]`, plus `--version`. Every command run prints one JSON line, `{ "ok": true, … }` or `{ "ok": false, "error": { code, message } }` (`--help` and `--version` print plain text), and ends with exit code 0 (ok), 1 (fix the code), 2 (usage), 3 (platform unreachable, retry) or 4 (key not allowed). CI deploys the site only when `release` prints `"deploy": true` (a superseded run exits 0 with `"deploy": false`). The CLI reads `GINKO_PLATFORM` (or `NUXT_PUBLIC_GINKO_PLATFORM`), `GINKO_KEY`, `GINKO_COMMIT` (or `GITHUB_SHA`), `GINKO_BRANCH` and `GINKO_REMOTE`; it does not read `.env` files. `ginko-i18n --json` uses the same output shape, error codes (`USAGE`, `INVALID`) and exit codes.
82
+ - Config names: `f.ref` (one entry) and `f.refs` (several); `visible: { mode: 'until', field, days?, deleteExpired? }`; prefill tokens `@today`, `@workWeek`, `@nextWorkWeek`; `firstDayOfWeek`, `linkCheck`, `untranslated`, `maxBytes`, `Migration.compute`, `retired` rule `{ drop: true }`. Options and defaults are typed per field, and an unknown top-level key fails the build.
83
+ - Markdown components: `embed`, `frame` (`none`, `card`, `border`, …), `background` (`none`, `muted`, `tint`), `appearance` (`quiet`, `tint`), `quiz-question{mode}`, `code-tree{file}`.
84
+
85
+ **Content (`@lupinum/ginko`, `@lupinum/ginko-content`)**
86
+
87
+ - One text format: Markdown (comark 0.7) everywhere, with field profiles that limit what a field may contain. Footnotes, emoji, alerts, Shiki code, task lists, route links (`$blog.my-post`), reusable snippets and heading anchors.
88
+ - Data files: YAML and JSON (one file, one entry) and CSV (one file, many entries), checked against the field schema; every error names the file and field, and the line for CSV rows and unreadable files. Entries with `draft: true` stay out of production builds.
89
+ - Query engine in the site, over the loaded bundle: `where`, `order`, `limit`, pagination with totals, field selection, `include` for references, previous/next and facet counts.
90
+ - References (`f.ref`, `f.refs`), navigation trees and breadcrumbs, and a URL for every entry in every language; two entries on one URL fail the build.
91
+ - Link check before any HTML exists: route links, anchors, snippets and redirected paths, in the build, the dev terminal, `ginko check` and the agent tools. On the platform a save, a new entry or a scheduled publish that adds a broken link is stopped, and History says why. External links are checked on request (`linkCheck.external`), at build and in `ginko check` (never in dev), with a 7-day cache.
92
+ - Images: WebP copies at 480, 960 and 1600 px, made at upload on the platform and at build for files. `<GinkoImage>` and Markdown images get `srcset` and `sizes`.
93
+ - Redirects from `redirectFrom` (301) and site rules in `redirects` (301 by default, `status` 302/307/308 per rule).
94
+ - SEO from the bundle, with no other module: title template, canonical, Open Graph with `og:url`, `<html lang>`, hreflang with `x-default`, sitemap with `lastmod`, images and alternates, robots.txt with `noindex` on preview hosts, JSON-LD. With `nuxt-og-image` (in every starter), every page gets a generated share card in the brand colour `seo.color`, with the site's logo and the page's image.
95
+ - Works with the Nuxt SEO modules (`@nuxtjs/seo` or single ones, in any order): Ginko leaves them sitemap, robots.txt and JSON-LD defaults and hands them its pages with hreflang, the site's address, name and languages, and `noindex` on preview hosts. `nuxt-ai-ready` stays off while Ginko serves `/llms.txt`. Requires `nuxt-og-image` 7.
96
+ - Search index built in plain JS at build time, one record per heading section, loaded lazily per language.
97
+ - Agent output: `/llms.txt`, `/llms-full.txt`, a `.md` twin for every entry page (collections with a `route`), and a Markdown 404 that suggests pages. The normal address always answers with HTML.
98
+ - Render modes: Git-only sites prerender everything; platform sites refresh changed pages after a publish; previews render with `noindex`.
99
+ - In dev, `nuxt dev` restarts when `ginko.config.ts` changes, and a brick that cannot reach the platform names itself and the fix.
100
+ - CLI `ginko`: `check` (schema, links and the share image, for every site; `--offline` without the platform) and `release` for CI, `export` for backups; `pnpm local:dev|import|pull` run only in the Ginko monorepo.
101
+
102
+ **Languages (`@lupinum/ginko-i18n`)**
103
+
104
+ - The only locale authority: routes, alternates, hreflang, messages with plurals, and formatters for dates, ranges, relative time, numbers, currency and lists, each in the site's time zone.
105
+ - Works on its own in any Nuxt 4.6+ or Nuxt 5 app, without the rest of Ginko.
106
+
107
+ **Components and docs (`@lupinum/ginko-components`, `@lupinum/ginko-docs`)**
108
+
109
+ - Content components with props defined as Ginko fields: callouts, tabs, code groups, steps, cards, accordion, figures, embeds (click to load), timeline, quiz and more. Each one can also be copied into an app with the shadcn-vue CLI, from a registry the docs build generates.
110
+ - Docs layer (`@lupinum/ginko-docs`; `npm create ginko@latest my-docs -- --preset docs` starts a site with it): navigation, section tabs, breadcrumbs, table of contents with scroll spy, previous/next, ⌘K search with heading results, blog with authors and RSS, changelog, copy page as Markdown, dark mode. A guide for switching from Nuxt Content and `@nuxtjs/i18n`. Math (KaTeX) and mermaid diagrams render and load only on pages that use them.
111
+
112
+ **Platform and Studio (hosted by Lupinum)**
113
+
114
+ The platform is a hosted service, not an npm package. A site connects to it with one setting; without it, the site reads its content from files.
115
+
116
+ - Quick tasks for the jobs owners do most ("Heute geschlossen", "Preis ändern"), phone first, with the full form behind "Alles bearbeiten".
117
+ - Files library: All, Recent, Unused, Missing alt text, Duplicates and folders; icon and list views; "used in" with links; replace a file and keep its references; a used file cannot be removed by mistake. Alt text set in the library is the default for every use, per language.
118
+ - Approvals, off by default: a task or agent key can need a yes. Reviewers see the change, approve, approve for a time, or reject with a sentence; the author sees the reason. Releases publish several changes together.
119
+ - History with "show changes", "back to this version" and undo; drafts and scheduled publishing; trash with restore; translation status per language; "why is this not on the website?".
120
+ - Team and invitations with per-task rights, sign-in with an emailed code, AI agent keys with an MCP tool catalog derived from the operations, and weekly reminder mails.
121
+ - Long forms group their fields under headings or in tabs (`group` on a field, `layout: 'tabs'` on a brick); phones always show headings.
122
+ - A rich text editor (TipTap 3) that writes Markdown, where untouched text stays byte for byte. Headings, lists, task lists, quotes, code blocks, tables, images from the library, embeds, registry components with prop forms, slash and bubble menus, Markdown shortcuts and paste, source mode, find and replace (⌘F), a drag handle and Alt+↑/↓ to move blocks, character counter, a link card for pasted URLs, uploads with progress, and a formatting bar above the phone keyboard.
123
+ - Delete a site, with seven days to cancel, and delete your own account. The last owner of a site must hand it over or delete it first.
124
+ - Studio in German, English and Spanish (beta), light and dark.
125
+
126
+ **Presets (`@lupinum/ginko-preset-gastro`, `create-ginko`)**
127
+
128
+ - Gastro: opening hours with exceptions, seasons, holidays and new hours from a date; lunch week with planning ahead and an optional PDF; menu with prices from a date; notices that expire; events; JSON-LD for Restaurant, Menu, opening hours and Event; a printable lunch sheet.
129
+ - `create-ginko` starts a new site, plain or with `--preset gastro|docs`. Starters install with npm, pnpm 11 and bun, carry a `typecheck` script, a page description and share cards (`nuxt-og-image` with Takumi, Nuxt 4.6.1 or later; set `NUXT_APP_SECRET` where the site runs, `.env` has one), and create-ginko warns on an unsupported Node.
130
+
131
+ **Not in 0.4**
132
+
133
+ Real-time co-editing comes next. Also not included: an agency preset, the editor UI as a shadcn-vue registry, OAuth for agent connectors, and a Google Business sync.
134
+
135
+ ### Patch Changes
136
+
137
+ - Updated dependencies [[`ea2ea13`](https://github.com/lupinum-dev/ginko/commit/ea2ea133997f2011ad0d43f77a0f1dc75605923e)]:
138
+ - @lupinum/ginko@0.4.0
139
+ - @lupinum/ginko-i18n@0.4.0
140
+ - @lupinum/ginko-content@0.4.0
141
+ - @lupinum/ginko-components@0.4.0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024-present Lupinum OG and contributors
3
+ Copyright (c) 2025-2026 Lupinum OG
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,86 +1,333 @@
1
- <p align="center">
2
- <img src="https://raw.githubusercontent.com/lupinum-dev/ginko-docs/main/docs/public/favicon.svg" width="128" alt="Ginko Docs icon">
3
- </p>
1
+ # @lupinum/ginko-docs
4
2
 
5
- <h1 align="center">@lupinum/ginko-docs</h1>
3
+ A Nuxt layer for documentation sites on [`@lupinum/ginko`](https://github.com/lupinum-dev/ginko/tree/main/packages/ginko)
4
+ and [`@lupinum/ginko-content`](https://github.com/lupinum-dev/ginko/tree/main/packages/ginko-content):
5
+ a whole docs site with a start page, navigation, search, blog and changelog, or docs inside a site that already exists
6
+ (see "Inside an existing site"). The Markdown components (callouts, tabs, steps, cards,
7
+ code blocks and more) come from `@lupinum/ginko-components`. Math (`$x^2$`, `$$…$$`) renders with KaTeX and `mermaid` code fences as diagrams; both load only on pages that use them. Pages are Markdown files in `content/docs/`.
6
8
 
7
- <p align="center">Add a complete documentation experience to a Nuxt application through one reusable layer.</p>
9
+ ## Use
8
10
 
9
- <p align="center">
10
- <a href="https://www.npmjs.com/package/@lupinum/ginko-docs"><img src="https://img.shields.io/npm/v/@lupinum/ginko-docs?color=00DC82" alt="npm version"></a>
11
- <a href="https://github.com/lupinum-dev/ginko-docs/actions/workflows/ci.yml"><img src="https://github.com/lupinum-dev/ginko-docs/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
12
- <a href="https://github.com/lupinum-dev/ginko-docs/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT license"></a>
13
- </p>
11
+ ```bash
12
+ npm install @lupinum/ginko @lupinum/ginko-content @lupinum/ginko-i18n @lupinum/ginko-docs
13
+ ```
14
14
 
15
- > [!WARNING]
16
- > This package is stable in the 0.3 release line. Because it is pre-1.0, a later minor release can contain breaking changes.
15
+ ```ts
16
+ // ginko.config.ts
17
+ import { defineSite } from '@lupinum/ginko'
18
+ import { components, docsCollection, homePages } from '@lupinum/ginko-docs/config'
17
19
 
18
- ## Purpose
20
+ const locales = ['en', 'de'] as const
19
21
 
20
- Use this package when a Nuxt application needs documentation routes, navigation, search, localization, metadata, social images, feedback, and agent-readable content. The layer provides the interface while the consuming application keeps ownership of its content and identity.
22
+ export default defineSite({
23
+ site: 'my-docs',
24
+ name: 'My docs',
25
+ url: 'https://docs.example.com',
26
+ timeZone: 'Europe/Vienna',
27
+ locales,
28
+ currency: 'EUR',
29
+ pages: { home: homePages({ locales }) }, // the start page is the page `home`
30
+ components, // the Markdown components: ::callout, ::tabs, ::steps …
31
+ bricks: { docs: docsCollection({ locales }) },
32
+ })
33
+ ```
21
34
 
22
- ## Requirements
35
+ `docsCollection`, `blogCollections`, `homePages`, `blogPages` and `changelogPages` take one options object. `locales` is the same list as
36
+ in `defineSite` (the layer accepts any `readonly string[]`; `defineSite` itself needs the tuple, hence `as const`).
23
37
 
24
- - Node.js 22.18, 24.11, or 26 and later maintenance releases
25
- - Nuxt 4.5.1 or later in the Nuxt 4 line
26
- - Vue 3.5.40 or later
27
- - Ginko Content 0.4 prerelease or later in the 0.4 line
38
+ The bricks read Markdown files from `content/`. To edit them in Ginko Studio instead, pass `source: 'platform'` to
39
+ `docsCollection`, `docsHome`, `blogCollections` or `changelogCollection` (each brick on its own; the default is
40
+ `'files'`). The pages, their Markdown twins and `read_doc` work the same with either source, and a page from the
41
+ platform links "Edit this page" to its form in the Studio. Two things are built from files only: the search index
42
+ (the search box and `search_docs`) finds no page that lives on the platform, and an icon named only in Studio content
43
+ is not bundled (name it once in a file the icon scan reads, see "Icons").
28
44
 
29
- ## Installation
45
+ `components` is the registry of `@lupinum/ginko-components` (a dependency of the layer, re-exported here). With it, Ginko checks every component tag and prop in the
46
+ pages; a site can add its own components next to it (see "Inside an existing site").
30
47
 
31
- ```bash
32
- pnpm add -D @lupinum/ginko-docs@0.4.0-rc.9 @lupinum/ginko-content@1.0.0-beta.5
48
+ Limits of the layer:
49
+
50
+ - It finds its content by brick key, so keep these names: `docs` (docsCollection), `home` (docsHome), `posts` and
51
+ `authors` (blogCollections), `changelog` (changelogCollection). Only `docs` is required. One site has one docs
52
+ collection.
53
+ - The docs move with `base`; the blog is always at `/blog` and the changelog at `/changelog` (with the language
54
+ prefix in other languages, for example `/de/blog`).
55
+
56
+ ```ts
57
+ // nuxt.config.ts
58
+ import ginko from './ginko.config.ts'
59
+
60
+ export default defineNuxtConfig({ extends: ['@lupinum/ginko-docs'], modules: ['@lupinum/ginko/nuxt'], ginko })
33
61
  ```
34
62
 
63
+ ## Configure
64
+
65
+ Options go in the site's `app.config.ts`. All are optional. Internal paths in `nav`, `footer.links` and `banner.href`
66
+ follow the reader's language (`/guide` becomes `/de/guide`); absolute URLs stay as written. A route link names the page
67
+ instead of its address, as in Markdown: `$docs.<page>` (a docs page by its file name, such as `$docs.webhooks`, or its
68
+ slug) and `$page.<key>` (a page of `pages` in `ginko.config.ts`, such as `$page.changelog`), with an optional `#anchor`.
69
+ It leads to the page in the reader's language, also when a translation has another slug.
70
+
35
71
  ```ts
36
- export default defineNuxtConfig({
37
- extends: ["@lupinum/ginko-docs"],
38
- site: { url: "https://docs.example.com" },
39
- i18n: { baseUrl: "https://docs.example.com" },
40
- });
72
+ export default defineAppConfig({
73
+ docs: {
74
+ title: 'My docs', // header text, next to the logo (default: `name` from ginko.config.ts)
75
+ logo: { light: '/logo.svg', dark: '/logo-dark.svg' }, // `wordmark: true` when the image holds the name
76
+ theme: 'green', // colour preset: 'default' (emerald on zinc) or 'green' (green on slate)
77
+ nav: [{ id: 'guide', href: '/guide' }], // header links after Docs, Blog, Changelog
78
+ social: [{ icon: 'docs:github', href: 'https://github.com/me/docs', label: 'GitHub' }],
79
+ banner: { id: 'v2', href: '/docs/changes' }, // dismissible notice above the header; `href` optional
80
+ repository: { url: 'https://github.com/me/docs', branch: 'main' }, // "Edit this page" and "Report an issue"
81
+ markdownActions: { copy: true, openIn: ['chatgpt', 'claude'] }, // "Copy page" and the chats of its menu (the defaults)
82
+ footer: {
83
+ links: [{ id: 'github', href: 'https://github.com/me/docs' }],
84
+ attribution: true, // "Built with Ginko", default true
85
+ },
86
+ },
87
+ })
88
+ ```
89
+
90
+ Texts are not part of the config, they come from the site's own messages (`i18n/<code>.json`), so every
91
+ language has its own:
92
+
93
+ ```json
94
+ { "docs": { "banner": { "v2": "Version 2 is out." }, "nav": { "guide": "Guide" }, "footer": { "github": "GitHub" } } }
95
+ ```
96
+
97
+ - `docs` is a reserved message namespace: keep your own messages out of it. Only `docs.nav.<id>`, `docs.footer.<id>` and `docs.banner.<id>` are yours to set; the other `docs.*` keys are the layer's own texts.
98
+ - `banner.id` picks the message `docs.banner.<id>`. A reader who closes the banner does not see it again (it is remembered in `localStorage`, and the page gets `data-docs-banner-off` on `<html>`); a new `id` shows it to everyone.
99
+ - Each `nav` and footer link `id` picks the message `docs.nav.<id>` or `docs.footer.<id>`.
100
+ - `social` icons are any Iconify name. Built in: `docs:github`, `docs:discord`, `docs:x`, `docs:bluesky`, `docs:mastodon`, `docs:linkedin`, `docs:youtube`.
101
+ - `repository` adds "Edit this page" to every page that comes from a file (`<url>/edit/<branch>/<source>`; `branch` defaults to `main`)
102
+ and, for GitHub, "Report an issue". `editUrl` (`{url}`, `{branch}`, `{source}`) and `issueUrl` (`{url}`, `{title}`, `{page}`) are templates for other hosts. Pages stored on the Ginko platform (not in files) link to
103
+ their form in the Studio instead, at the site's platform address.
104
+ - Every page shows "Last updated" from the entry's `updatedAt`, and its JSON-LD is a `TechArticle` with `dateModified`.
105
+ - "Copy page" copies the page as Markdown; its menu opens the `.md` twin, or ChatGPT or Claude with a prompt that points at it.
106
+ - The layer also serves a read-only [MCP](https://modelcontextprotocol.io) endpoint at `POST /__ginko/docs-mcp` (Streamable HTTP, JSON-RPC)
107
+ with the tools `search_docs(query, locale?)` and `read_doc(path)`. No auth, no rate limit: it only exposes what the public site shows.
108
+
109
+ ### Pages
110
+
111
+ Each docs page's frontmatter can set, besides `title` and `description`:
112
+
113
+ | Field | Effect |
114
+ | --- | --- |
115
+ | `section` | Starts a group in the side navigation with this heading; the pages after it belong to it until the next `section`. |
116
+ | `tab` | Starts a tab above the side navigation (for example "Guide" and "Reference"); pages follow the tab before them. |
117
+ | `parent` | Nests the page under another one (`parent: docs/<name>`: the entry id, the file name without number, locale and extension). |
118
+ | `icon` | An Iconify name, e.g. `lucide:rocket`, before the title in the navigation. Main locale only. |
119
+ | `badge` | A short label after the title, e.g. "New". |
120
+
121
+ ### Icons
122
+
123
+ The layer draws icons itself (no `@nuxt/icon`, no icon API call, no icon library in the browser). At build time it reads
124
+ exactly the icons your site names from the installed `@iconify-json/<set>` packages (`lucide` is installed with the
125
+ layer; add others with `pnpm add -D @iconify-json/<set>`) and bundles them in one small map that only docs pages load.
126
+
127
+ The build scans, in all locales:
128
+
129
+ - the front matter of your Markdown files, the attributes of Markdown components (`::card{icon="lucide:rocket"}`) and the
130
+ `---` block inside a component; prose and code blocks are not read;
131
+ - YAML and JSON content files and `app.config.ts` (`icon:` values and `social`);
132
+ - the layer's own components and your site's `app/**/*.vue` files (`<Icon name="lucide:x" />`, `icon="..."`, or a bound
133
+ literal `:name="'lucide:x'"`). Commented-out code is ignored; other `.ts` files than `app.config.ts` are not read.
134
+
135
+ A name is `set:name`; a bare name such as `book-open` means Lucide. The `i-set-name` form is not supported. Names built at
136
+ runtime (a variable, a template string) are not found; write the name once as a literal somewhere in the places above. A
137
+ name the build cannot find logs one warning with its file and renders nothing.
138
+
139
+ The layer registers a global `Icon` component that the Markdown components (card, tabs, callout) use. If your site installs
140
+ `@nuxt/icon` itself, yours wins (the layer's has a lower priority).
141
+
142
+ ### Start page (optional)
143
+
144
+ `docsHome()` adds a `home` brick: one file `content/home.md` (and `home.<locale>.md`). Its frontmatter fills the hero
145
+ and the feature grid, the text below it follows them:
146
+
147
+ ```md
148
+ ---
149
+ title: Docs for my library.
150
+ description: One sentence on what it does.
151
+ install: npm install my-library
152
+ links:
153
+ - { label: Get started, href: /docs/introduction }
154
+ - { label: GitHub, href: https://github.com/me/lib }
155
+ features:
156
+ - { icon: lucide:zap, title: Fast, description: Why it is fast., href: /docs/speed }
157
+ ---
158
+ ```
159
+
160
+ `href` takes a path as written, an absolute URL, or a route link (`$docs.introduction`, `$page.changelog`) that follows
161
+ the reader's language, so the translations (`home.<locale>.md`) can use the same links.
162
+
163
+ Add `home: docsHome()` to `bricks`. Without it, `/` leads to the first docs page. A site's own `pages/index.vue` wins.
164
+
165
+ ### Look and colours
166
+
167
+ The layer is plain CSS. Colours, radius and fonts are shadcn-style tokens, the same ones
168
+ `@lupinum/ginko-components` reads: `--background`, `--foreground`, `--muted`, `--muted-foreground`, `--accent`,
169
+ `--border`, `--primary`, `--primary-foreground`, `--card`, `--popover`, `--ring`, `--radius`, `--font-sans`,
170
+ `--font-mono`. The layer's defaults have zero specificity, so any value the site sets wins:
171
+
172
+ ```css
173
+ /* assets/site.css */
174
+ :root {
175
+ --primary: light-dark(#2f6f4f, #7cc59d);
176
+ --primary-foreground: light-dark(#fff, #0c1f15);
177
+ --font-sans: 'Inter', system-ui, sans-serif;
178
+ }
41
179
  ```
42
180
 
43
- ## Quick start
181
+ The defaults are `light-dark(light, dark)` pairs. The header switch stores the reader's choice in `localStorage`
182
+ (key `docs-color-mode`) and sets `data-theme="light|dark"` on `<html>`; a small inline script applies it before the first paint. A `.dark` class
183
+ on `<html>` (for example from `@nuxtjs/color-mode`) works too. Layout sizes are tokens as well: `--docs-sidebar`,
184
+ `--docs-toc`, `--docs-max`, `--docs-header`.
185
+
186
+ ## Inside an existing site
187
+
188
+ The layer can add docs to a site that has its own design, pages and layout, for example a company site with docs
189
+ under `/docs` or `/handbook`:
44
190
 
45
191
  ```ts
46
- import { defineGinkoDocsConfig } from "@lupinum/ginko-docs/content";
192
+ // nuxt.config.ts of the existing site
193
+ export default defineNuxtConfig({ extends: ['@lupinum/ginko-docs'], modules: ['@lupinum/ginko/nuxt'], ginko })
194
+ ```
47
195
 
48
- export default defineGinkoDocsConfig({
49
- site: {
50
- name: "Example Docs",
51
- description: "Documentation for Example.",
52
- whenToUse: "Use this site to learn and operate Example.",
53
- },
54
- locales: ["en"],
55
- blog: false,
56
- });
196
+ ```ts
197
+ // ginko.config.ts: the docs brick next to the site's own bricks, the Markdown components next to the site's own
198
+ import { components, docsCollection } from '@lupinum/ginko-docs/config'
199
+
200
+ bricks: { docs: docsCollection({ locales, base: '/handbook' }), /* … */ },
201
+ components: { ...components, /* the site's own components; same name wins */ },
202
+ ```
203
+
204
+ - **Only the docs pages are added.** The layer registers its pages from the bricks, after all pages of the site are
205
+ known: the docs at the `base` of `docsCollection` (default `/docs`), the blog (with its RSS feed) at the route of
206
+ the `posts` brick and the changelog at the route of the `changelog` brick (or `pages.changelog`), and `/` only when
207
+ the site has no start page of its own. A page the site defines itself at one of these addresses always wins, also
208
+ when the page-paths module gives it that address (a page file `news.vue` that answers at `/blog`). Then the layer
209
+ adds no page and no feed there, and its header and post links point to the site's page.
210
+ - **The site's frame stays.** The header, footer and page background are the layer's `layouts/default.vue`. When
211
+ the site has its own `layouts/default.vue`, that one is used and the docs (navigation, page, table of contents)
212
+ sit inside it, without the layer's framed panel, on the site's background. The search sits above the navigation.
213
+ On phones a bar under the site's header holds a "Contents" button (the navigation as a sheet), the search and the
214
+ "On this page" menu, so the docs need no header of their own.
215
+ - **Nothing leaks.** Every rule is under a `docs-` class; the page background, font and `color-scheme` are only set
216
+ by the layer's own frame. The search, the language menu and the light/dark switch are components
217
+ (`<DocsSearch />`, `<DocsLanguage />`, `<DocsThemeToggle />`) the site can put into its own header; the switch sets
218
+ `data-theme` on `<html>`, so it fits a site that themes with that attribute. `<DocsThemeToggle segmented />` is the
219
+ three-way Auto/Light/Dark switch and `<DocsLanguage list />` the languages as a row of links (the phone menu uses
220
+ both). A language without a version of the page says so ("Not translated: opens the start page"). These three,
221
+ `<DocsShell>` and the override points under [Customize](#customize) are the public components. The other `Docs*`
222
+ components, the `useDocs*` composables and the files in `app/lib` are internal and can change in any release.
223
+ - **Error page:** the layer's `error.vue` shows a not-found page inside the site's layout, with links home and to
224
+ the docs. A site with its own `error.vue` keeps it.
225
+ - **Components:** the layer loads the Vue side of `@lupinum/ginko-components`. Pass the registry in the site's
226
+ `components` (see above): only then does Ginko check the tags and props in the pages. Without a registry, the
227
+ check accepts any tag, so a misspelled `::calout` goes through without an error.
228
+ - **Title:** pages get the title `Page · Site name` from Ginko (`seo.titleTemplate` in `defineSite`). A
229
+ `titleTemplate` in `app.head` or from nuxt-seo-utils does not apply to them, so the name is never added twice.
230
+ - **Styling:** map the site's design tokens to the token names above (leave out the ones the site already defines
231
+ under the same name, often `--font-sans` and `--font-mono`). Three layout tokens line the docs up with the site:
232
+ - `--docs-max` and `--docs-gutter`: the width and the side padding of the site's content container, so the search
233
+ and the navigation start where the header's logo does.
234
+ - `--docs-top`: the space the sidebar, the phone bar and the table of contents keep from the top of the window when
235
+ they stick, and the scroll offset of headings. With a sticky header, its height; with one that scrolls away, 0.
236
+
237
+ ```css
238
+ :root {
239
+ --background: var(--color-white);
240
+ --foreground: var(--color-ink);
241
+ --muted: var(--color-stone-100);
242
+ --muted-foreground: var(--color-stone-600);
243
+ --border: var(--color-stone-300);
244
+ --primary: var(--color-brand);
245
+ --radius: 0.75rem;
246
+ --docs-max: 82.5rem;
247
+ --docs-gutter: 1.5rem;
248
+ --docs-top: 4.5rem; /* sticky header 4.5rem high; 0 for one that scrolls away */
249
+ }
57
250
  ```
58
251
 
59
- Put Markdown files in `content/docs`. Open `/docs` after the Nuxt server starts.
252
+ Headings use the site's own heading styles; the layer sets no font on them.
60
253
 
61
- Generate the browser icon set from one square SVG or raster source:
254
+ ## Customize
62
255
 
63
- ```bash
64
- pnpm exec ginko-docs-favicons --source public/product-icon.svg --out public
256
+ Everything here is public and stays stable between releases.
257
+
258
+ **Tokens.** The colour tokens are listed under [Look and colours](#look-and-colours). The layout tokens:
259
+
260
+ | Token | Default | What it sets |
261
+ | --- | --- | --- |
262
+ | `--docs-max` | `90rem` | Width of the docs, gutters included |
263
+ | `--docs-gutter` | `1rem` | Space between the window edge and the docs |
264
+ | `--docs-top` | `0px` (standalone: the header) | Height of what sticks above the docs |
265
+ | `--docs-sidebar` | `17rem` | Width of the navigation |
266
+ | `--docs-toc` | `13.5rem` | Width of "On this page" beside the text (from 80rem window width) |
267
+ | `--docs-measure` | `38rem` | Reading width of running text |
268
+ | `--docs-h1` | `clamp(1.75rem, …, 2.25rem)` | Size of page titles |
269
+ | `--docs-header` | `4rem` | Height of the standalone header |
270
+
271
+ **Override points.** The layer ships empty components that a site replaces with its own file of the same name in
272
+ `app/components/`:
273
+
274
+ - `DocsPageEnd` (prop `doc`, the page's entry): after the text of every page, before "Edit this page" and the pager.
275
+ For a support box or a call to action.
276
+ - `DocsSidebarEnd`: below the navigation, in the sidebar and in the phone menu. For a few links or a contact line.
277
+
278
+ **Own pages in the docs frame.** `<DocsShell>` is the docs body (navigation, search, the phone bar) with a default slot
279
+ for the page and a `bar` slot for controls in the phone bar. A help center's start page, for example:
280
+
281
+ ```vue
282
+ <!-- app/pages/help/index.vue; the docs live at /help (docsCollection({ locales, base: '/help' })) -->
283
+ <script setup lang="ts">
284
+ const docs = useGinko('docs')
285
+ </script>
286
+
287
+ <template>
288
+ <DocsShell>
289
+ <h1>How can we help?</h1>
290
+ <ul>
291
+ <li v-for="item in docs.items" :key="item.id"><NuxtLink :to="item.url">{{ item.data.title }}</NuxtLink></li>
292
+ </ul>
293
+ </DocsShell>
294
+ </template>
65
295
  ```
66
296
 
67
- The command writes `favicon.svg`, `favicon-96x96.png`, `apple-touch-icon.png`, and `favicon.ico`. Ginko Docs adds the matching head links and uses the generated 96px PNG in Nuxt-preset social images so every supported source format renders consistently.
297
+ The layer then adds no page of its own at that address.
298
+
299
+ **Search.** `docs: { search: false }` in app.config leaves out the built-in search (header, sidebar and phone bar), for
300
+ a site that puts `<DocsSearch />` into its own header.
68
301
 
69
- ## Exports
302
+ **Texts.** Every text of the layer is a `docs.*` message, and the site's own i18n wins per key. A help center, for
303
+ example, words the search for itself in `i18n/en.json`: `{ "docs": { "searchPlaceholder": "Search help…" } }`. The
304
+ layer brings English, German and French.
70
305
 
71
- - `@lupinum/ginko-docs` is the Nuxt layer entry.
72
- - `@lupinum/ginko-docs/content` exports `defineGinkoDocsConfig`.
73
- - `@lupinum/ginko-docs/app-config` exports application configuration types.
74
- - `@lupinum/ginko-docs/components` exports the public MDC component contract.
306
+ ## Blog and changelog (optional)
75
307
 
76
- ## Documentation
308
+ A site opts in by adding the collections to `ginko.config.ts`. The layer then adds the pages and the header links;
309
+ a site without them gets neither.
77
310
 
78
- Read the [Ginko Docs documentation](https://ginko-docs.lupinum.com) and the [root README](https://github.com/lupinum-dev/ginko-docs#readme).
311
+ ```ts
312
+ import { blogCollections, blogPages, changelogCollection, changelogPages, docsCollection } from '@lupinum/ginko-docs/config'
313
+
314
+ export default defineSite({
315
+ // ...
316
+ pages: { /* home */ blog: blogPages({ locales }), changelog: changelogPages({ locales }) },
317
+ bricks: { docs: docsCollection({ locales }), ...blogCollections({ locales }), changelog: changelogCollection() },
318
+ })
319
+ ```
79
320
 
80
- ## Support and security
321
+ - `blogCollections({ locales })` returns `{ posts, authors }`. Both are file bricks, so the folders are `content/posts/` and `content/authors/` (the brick name is the folder name).
322
+ - **Posts** (`content/posts/<n>.<name>[.<locale>].md`) have `title`, `description`, `date` (`YYYY-MM-DD`), `authors` (a list of author ids), `image`, `tags` and `slug`. They live at `/blog/<slug>` (`/<l>/blog/<slug>` in other languages), the list at `/blog`, newest first.
323
+ - **Authors** (`content/authors/<name>[.<locale>].yml`) have `name`, `role`, `avatar` and `url`. A post names them by id: `authors: [authors/jane]`. Authors have no page.
324
+ - A post page writes Article JSON-LD with the author names, `datePublished` from `date` and `dateModified` from the entry's `updatedAt`.
325
+ - **RSS:** `/blog/rss.xml` and `/<l>/blog/rss.xml`, RSS 2.0 with title and description (not the full text) and absolute links. It reads the build-time file bundle, so it works for file blogs only. `nuxt generate` writes it: the blog page sends the feed path in the `x-nitro-prerender` header, because Nitro's crawler does not follow `.xml` links.
326
+ - **Addresses:** the blog list is the parent of the `posts` route (`/blog/[slug]` gives `/blog`; `blogCollections` uses `/blog`). The changelog page is at the route of the `changelog` brick, else at `pages.changelog` (`changelogPages({ locales })`, `/changelog`). A changelog brick with neither gets no page, and the build warns once. A site that has its own page at an address keeps it; the layer then adds nothing there.
327
+ - **Changelog:** `changelogCollection()` (options: `max`) is one collection with `version`, `date` and Markdown text per release (`content/changelog/v1-2-0.md`; no dots in the file name, a dot reads as a language). The page `/changelog` shows all releases newest first, each with an anchor (`#v1-2-0`). It is a collection, not a docs page, so the date orders it and it has its own link in the header.
81
328
 
82
- Use [GitHub issues](https://github.com/lupinum-dev/ginko-docs/issues) or the [Lupinum OSS Discord](https://discord.gg/RPH6SeA36N) for support. Report vulnerabilities through the [private security process](https://github.com/lupinum-dev/ginko-docs/security/policy).
329
+ The Ginko docs themselves are built this way: [sites/docs](https://github.com/lupinum-dev/ginko/tree/main/sites/docs).
83
330
 
84
331
  ## License
85
332
 
86
- Released by [Lupinum OG](https://lupinum.com) under the [MIT License](https://github.com/lupinum-dev/ginko-docs/blob/main/LICENSE).
333
+ MIT © Lupinum OG