blume 0.0.0 → 0.1.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 (263) hide show
  1. package/bin/blume.mjs +18 -0
  2. package/dist/cli/index.js +11989 -0
  3. package/dist/cli/index.js.map +141 -0
  4. package/docs/01-quickstart.mdx +99 -0
  5. package/docs/02-deployment.mdx +129 -0
  6. package/docs/advanced/api-reference.mdx +114 -0
  7. package/docs/advanced/blog.mdx +121 -0
  8. package/docs/advanced/changelog.mdx +113 -0
  9. package/docs/advanced/custom-pages.mdx +187 -0
  10. package/docs/advanced/meta.ts +7 -0
  11. package/docs/changelog/v0-1-0.mdx +12 -0
  12. package/docs/changelog/v0-2-0.mdx +16 -0
  13. package/docs/configuration/ai.mdx +228 -0
  14. package/docs/configuration/analytics.mdx +98 -0
  15. package/docs/configuration/customization.mdx +91 -0
  16. package/docs/configuration/export.mdx +70 -0
  17. package/docs/configuration/index.mdx +271 -0
  18. package/docs/configuration/meta.ts +15 -0
  19. package/docs/configuration/search.mdx +172 -0
  20. package/docs/configuration/seo.mdx +196 -0
  21. package/docs/configuration/theming.mdx +178 -0
  22. package/docs/content/components.mdx +565 -0
  23. package/docs/content/i18n.mdx +205 -0
  24. package/docs/content/index.mdx +161 -0
  25. package/docs/content/islands.mdx +94 -0
  26. package/docs/content/meta.mdx +119 -0
  27. package/docs/content/meta.ts +15 -0
  28. package/docs/content/navigation.mdx +168 -0
  29. package/docs/content/sources.mdx +216 -0
  30. package/docs/content/syntax.mdx +445 -0
  31. package/docs/index.mdx +112 -0
  32. package/docs/reference/cli.mdx +43 -0
  33. package/docs/reference/frontmatter.mdx +74 -0
  34. package/docs/reference/meta.ts +7 -0
  35. package/package.json +140 -6
  36. package/src/ai/ask.ts +93 -0
  37. package/src/ai/llms.ts +65 -0
  38. package/src/ai/markdown.ts +31 -0
  39. package/src/ai/mcp/data.ts +74 -0
  40. package/src/ai/mcp/discovery.ts +49 -0
  41. package/src/ai/mcp/server.ts +225 -0
  42. package/src/ai/mcp/tools.ts +47 -0
  43. package/src/assets/icon.png +0 -0
  44. package/src/astro/generate.ts +878 -0
  45. package/src/astro/index.ts +4 -0
  46. package/src/astro/integration.ts +74 -0
  47. package/src/astro/islands.ts +131 -0
  48. package/src/astro/markdown-negotiation.ts +68 -0
  49. package/src/astro/pages.ts +28 -0
  50. package/src/astro/templates.ts +1199 -0
  51. package/src/cli/commands/add.ts +81 -0
  52. package/src/cli/commands/build.ts +103 -0
  53. package/src/cli/commands/dev.ts +108 -0
  54. package/src/cli/commands/doctor.ts +74 -0
  55. package/src/cli/commands/eject.ts +57 -0
  56. package/src/cli/commands/init.ts +98 -0
  57. package/src/cli/commands/migrate.ts +39 -0
  58. package/src/cli/commands/preview.ts +39 -0
  59. package/src/cli/commands/sync.ts +52 -0
  60. package/src/cli/commands/validate.ts +60 -0
  61. package/src/cli/index.ts +35 -0
  62. package/src/cli/log.ts +37 -0
  63. package/src/cli/prepare.ts +80 -0
  64. package/src/components/Icon.astro +99 -0
  65. package/src/components/content/Accordion.astro +8 -0
  66. package/src/components/content/AccordionItem.astro +121 -0
  67. package/src/components/content/AutoTypeTable.astro +51 -0
  68. package/src/components/content/Badge.astro +124 -0
  69. package/src/components/content/Callout.astro +73 -0
  70. package/src/components/content/Card.astro +104 -0
  71. package/src/components/content/CardGroup.astro +14 -0
  72. package/src/components/content/CodeGroup.astro +13 -0
  73. package/src/components/content/Color.astro +15 -0
  74. package/src/components/content/ColorItem.astro +87 -0
  75. package/src/components/content/ColorRow.astro +10 -0
  76. package/src/components/content/Column.astro +6 -0
  77. package/src/components/content/Columns.astro +9 -0
  78. package/src/components/content/Expandable.astro +11 -0
  79. package/src/components/content/FileTree.astro +8 -0
  80. package/src/components/content/Frame.astro +70 -0
  81. package/src/components/content/GithubInfo.astro +110 -0
  82. package/src/components/content/Math.astro +24 -0
  83. package/src/components/content/Panel.astro +20 -0
  84. package/src/components/content/Prompt.astro +129 -0
  85. package/src/components/content/Step.astro +34 -0
  86. package/src/components/content/Steps.astro +20 -0
  87. package/src/components/content/Tab.astro +40 -0
  88. package/src/components/content/Tabs.astro +273 -0
  89. package/src/components/content/Tile.astro +42 -0
  90. package/src/components/content/Tooltip.astro +68 -0
  91. package/src/components/content/Tree.astro +300 -0
  92. package/src/components/content/TreeFile.astro +15 -0
  93. package/src/components/content/TreeFolder.astro +62 -0
  94. package/src/components/content/TypeTable.astro +106 -0
  95. package/src/components/content/Update.astro +66 -0
  96. package/src/components/content/Visibility.astro +12 -0
  97. package/src/components/content/Warning.astro +9 -0
  98. package/src/components/content/auto-type-table.ts +141 -0
  99. package/src/components/content/github-info.ts +79 -0
  100. package/src/components/content/mermaid-element.ts +68 -0
  101. package/src/components/github-mark.ts +9 -0
  102. package/src/components/index.ts +14 -0
  103. package/src/components/islands/AskAI.astro +12 -0
  104. package/src/components/islands/ask-ai.tsx +156 -0
  105. package/src/components/layout/Analytics.astro +63 -0
  106. package/src/components/layout/Banner.astro +50 -0
  107. package/src/components/layout/Breadcrumbs.astro +31 -0
  108. package/src/components/layout/Favicon.astro +15 -0
  109. package/src/components/layout/Fonts.astro +14 -0
  110. package/src/components/layout/Header.astro +188 -0
  111. package/src/components/layout/LanguageSwitcher.astro +56 -0
  112. package/src/components/layout/NavTree.astro +462 -0
  113. package/src/components/layout/PageActions.astro +438 -0
  114. package/src/components/layout/PageFeedback.astro +58 -0
  115. package/src/components/layout/Pagination.astro +56 -0
  116. package/src/components/layout/ReferenceLayout.astro +102 -0
  117. package/src/components/layout/RootLayout.astro +533 -0
  118. package/src/components/layout/Search.astro +608 -0
  119. package/src/components/layout/TableOfContents.astro +68 -0
  120. package/src/components/layout/analytics-client.ts +38 -0
  121. package/src/components/layout/nav-utils.ts +87 -0
  122. package/src/components/layout/overrides.ts +32 -0
  123. package/src/components/layout/search/algolia.ts +43 -0
  124. package/src/components/layout/search/endpoint.ts +22 -0
  125. package/src/components/layout/search/flexsearch.ts +52 -0
  126. package/src/components/layout/search/orama-cloud.ts +41 -0
  127. package/src/components/layout/search/orama.ts +26 -0
  128. package/src/components/layout/search/pagefind.ts +43 -0
  129. package/src/components/layout/search/types.ts +163 -0
  130. package/src/components/layout/search/typesense.ts +60 -0
  131. package/src/components/layout/toc-element.ts +108 -0
  132. package/src/core/bridge.ts +92 -0
  133. package/src/core/config.ts +112 -0
  134. package/src/core/content.ts +50 -0
  135. package/src/core/define-components.ts +34 -0
  136. package/src/core/define-meta.ts +20 -0
  137. package/src/core/deployment-env.ts +73 -0
  138. package/src/core/diagnostics.ts +104 -0
  139. package/src/core/graph.ts +128 -0
  140. package/src/core/i18n-ui.ts +171 -0
  141. package/src/core/i18n.ts +169 -0
  142. package/src/core/last-modified.ts +88 -0
  143. package/src/core/links.ts +336 -0
  144. package/src/core/load-module.ts +15 -0
  145. package/src/core/manifest.ts +126 -0
  146. package/src/core/meta.ts +97 -0
  147. package/src/core/navigation.ts +392 -0
  148. package/src/core/package-root.ts +37 -0
  149. package/src/core/project-graph.ts +153 -0
  150. package/src/core/project.ts +56 -0
  151. package/src/core/schema.ts +1057 -0
  152. package/src/core/server-features.ts +23 -0
  153. package/src/core/sources/assets.ts +77 -0
  154. package/src/core/sources/cache.ts +122 -0
  155. package/src/core/sources/filesystem.ts +99 -0
  156. package/src/core/sources/mdx-remote.ts +216 -0
  157. package/src/core/sources/mintlify.ts +161 -0
  158. package/src/core/sources/normalize.ts +227 -0
  159. package/src/core/sources/notion.ts +440 -0
  160. package/src/core/sources/portable-text.ts +143 -0
  161. package/src/core/sources/read.ts +36 -0
  162. package/src/core/sources/resolve.ts +158 -0
  163. package/src/core/sources/sanity.ts +218 -0
  164. package/src/core/sources/types.ts +105 -0
  165. package/src/core/types.ts +261 -0
  166. package/src/core/ui-packs/ar.ts +47 -0
  167. package/src/core/ui-packs/bg.ts +47 -0
  168. package/src/core/ui-packs/bn.ts +47 -0
  169. package/src/core/ui-packs/ca.ts +47 -0
  170. package/src/core/ui-packs/cs.ts +47 -0
  171. package/src/core/ui-packs/da.ts +47 -0
  172. package/src/core/ui-packs/de.ts +47 -0
  173. package/src/core/ui-packs/el.ts +47 -0
  174. package/src/core/ui-packs/es.ts +47 -0
  175. package/src/core/ui-packs/fa.ts +47 -0
  176. package/src/core/ui-packs/fi.ts +47 -0
  177. package/src/core/ui-packs/fr.ts +47 -0
  178. package/src/core/ui-packs/he.ts +47 -0
  179. package/src/core/ui-packs/hi.ts +47 -0
  180. package/src/core/ui-packs/hr.ts +47 -0
  181. package/src/core/ui-packs/hu.ts +47 -0
  182. package/src/core/ui-packs/id.ts +47 -0
  183. package/src/core/ui-packs/index.ts +87 -0
  184. package/src/core/ui-packs/it.ts +47 -0
  185. package/src/core/ui-packs/ja.ts +47 -0
  186. package/src/core/ui-packs/ko.ts +47 -0
  187. package/src/core/ui-packs/nl.ts +47 -0
  188. package/src/core/ui-packs/no.ts +47 -0
  189. package/src/core/ui-packs/pl.ts +47 -0
  190. package/src/core/ui-packs/pt-br.ts +47 -0
  191. package/src/core/ui-packs/pt.ts +47 -0
  192. package/src/core/ui-packs/ro.ts +47 -0
  193. package/src/core/ui-packs/ru.ts +47 -0
  194. package/src/core/ui-packs/sk.ts +47 -0
  195. package/src/core/ui-packs/sr.ts +47 -0
  196. package/src/core/ui-packs/sv.ts +47 -0
  197. package/src/core/ui-packs/th.ts +47 -0
  198. package/src/core/ui-packs/tr.ts +47 -0
  199. package/src/core/ui-packs/uk.ts +47 -0
  200. package/src/core/ui-packs/vi.ts +47 -0
  201. package/src/core/ui-packs/zh-tw.ts +47 -0
  202. package/src/core/ui-packs/zh.ts +47 -0
  203. package/src/core/version.ts +23 -0
  204. package/src/deploy/robots.ts +20 -0
  205. package/src/deploy/rss.ts +128 -0
  206. package/src/deploy/sitemap.ts +28 -0
  207. package/src/index.ts +27 -0
  208. package/src/markdown/code-title.ts +71 -0
  209. package/src/markdown/directives.ts +83 -0
  210. package/src/markdown/heading-anchors.ts +137 -0
  211. package/src/markdown/index.ts +159 -0
  212. package/src/markdown/inline-code.ts +108 -0
  213. package/src/markdown/language-icon.ts +172 -0
  214. package/src/markdown/math.ts +32 -0
  215. package/src/markdown/mdast.ts +48 -0
  216. package/src/markdown/mermaid.ts +37 -0
  217. package/src/markdown/package-commands.ts +159 -0
  218. package/src/markdown/package-install.ts +40 -0
  219. package/src/migrate/fumadocs/config.ts +106 -0
  220. package/src/migrate/fumadocs/content.ts +365 -0
  221. package/src/migrate/fumadocs/frontmatter.ts +18 -0
  222. package/src/migrate/fumadocs/index.ts +252 -0
  223. package/src/migrate/fumadocs/meta.ts +114 -0
  224. package/src/migrate/migrate.ts +53 -0
  225. package/src/migrate/mintlify/config.ts +1040 -0
  226. package/src/migrate/mintlify/content.ts +98 -0
  227. package/src/migrate/mintlify/frontmatter.ts +126 -0
  228. package/src/migrate/mintlify/i18n.ts +51 -0
  229. package/src/migrate/mintlify/icons.ts +128 -0
  230. package/src/migrate/mintlify/index.ts +266 -0
  231. package/src/migrate/mintlify/snippets.ts +305 -0
  232. package/src/migrate/mintlify/transform.ts +81 -0
  233. package/src/migrate/nextra/content.ts +46 -0
  234. package/src/migrate/nextra/frontmatter.ts +40 -0
  235. package/src/migrate/nextra/index.ts +374 -0
  236. package/src/migrate/nextra/meta.ts +266 -0
  237. package/src/migrate/shared.ts +623 -0
  238. package/src/migrate/starlight/config.ts +459 -0
  239. package/src/migrate/starlight/content.ts +78 -0
  240. package/src/migrate/starlight/frontmatter.ts +111 -0
  241. package/src/migrate/starlight/i18n.ts +54 -0
  242. package/src/migrate/starlight/index.ts +131 -0
  243. package/src/og/card.ts +92 -0
  244. package/src/og/index.ts +2 -0
  245. package/src/openapi/scalar.ts +246 -0
  246. package/src/registry/eject.ts +263 -0
  247. package/src/registry/registry.ts +100 -0
  248. package/src/registry/rewrite-imports.ts +39 -0
  249. package/src/runtime/index.ts +14 -0
  250. package/src/search/build.ts +23 -0
  251. package/src/search/documents.ts +165 -0
  252. package/src/search/orama-index.ts +66 -0
  253. package/src/search/providers.ts +91 -0
  254. package/src/search/sync/algolia.ts +30 -0
  255. package/src/search/sync/index.ts +50 -0
  256. package/src/search/sync/orama-cloud.ts +40 -0
  257. package/src/search/sync/typesense.ts +65 -0
  258. package/src/seo/jsonld.ts +113 -0
  259. package/src/theme/entry.ts +608 -0
  260. package/src/theme/fonts.ts +198 -0
  261. package/src/theme/icons.ts +184 -0
  262. package/src/theme/palette.ts +143 -0
  263. package/src/theme/twoslash.ts +81 -0
@@ -0,0 +1,187 @@
1
+ ---
2
+ title: Custom Pages
3
+ description: Mount fully custom .astro routes alongside your docs and read your site's config, navigation, and content from the blume:data module.
4
+ ---
5
+
6
+ Most of a Blume site is Markdown, but sometimes you need a route that _isn't_ a
7
+ doc — a landing page, a pricing page, a hand-built blog or changelog index, or an
8
+ interactive dashboard. Drop an `.astro` file under your **pages** folder and
9
+ Blume mounts it as a real route, right alongside your content.
10
+
11
+ ## Add a page
12
+
13
+ Create a `pages/` folder at your project root and add an `.astro` file:
14
+
15
+ ```astro pages/pricing.astro lineNumbers
16
+ ---
17
+ import data from "blume:data";
18
+ ---
19
+
20
+ <h1>Pricing for {data.config.title}</h1>
21
+ ```
22
+
23
+ `blume dev` picks it up immediately and `blume build` prerenders it to static
24
+ HTML. The folder name is configurable with [`content.pages`](/docs/configuration#content)
25
+ (default `"pages"`).
26
+
27
+ Custom pages keep their original location on disk, so relative imports, component
28
+ imports, and [`getStaticPaths`](https://docs.astro.build/en/reference/routing-reference/#getstaticpaths)
29
+ all work exactly as they do in a plain Astro project — Blume mounts each file
30
+ where it sits rather than copying it.
31
+
32
+ ## Files and routes
33
+
34
+ Each file's path under the pages folder becomes its route. `index` maps to the
35
+ parent folder, and dynamic `[param]` segments are preserved:
36
+
37
+ | File | Route |
38
+ | ------------------------- | ------------- |
39
+ | `pages/pricing.astro` | `/pricing` |
40
+ | `pages/blog/index.astro` | `/blog` |
41
+ | `pages/blog/[slug].astro` | `/blog/:slug` |
42
+ | `pages/changelog.astro` | `/changelog` |
43
+
44
+ A custom page **wins** over a generated route at the same path. Adding
45
+ `pages/changelog.astro`, for example, replaces Blume's
46
+ [generated changelog timeline](/docs/advanced/changelog) with your own.
47
+
48
+ ## Reading site data
49
+
50
+ Import `blume:data` to read the same resolved config, navigation, routes, and
51
+ feeds the rest of the site uses:
52
+
53
+ ```astro pages/all-pages.astro lineNumbers
54
+ ---
55
+ import data from "blume:data";
56
+ ---
57
+
58
+ <h1>All pages</h1>
59
+ <ul>
60
+ {
61
+ data.routes
62
+ .filter((route) => route.indexable)
63
+ .map((route) => (
64
+ <li>
65
+ <a href={route.path}>{route.title}</a>
66
+ </li>
67
+ ))
68
+ }
69
+ </ul>
70
+ ```
71
+
72
+ The module exposes:
73
+
74
+ <TypeTable
75
+ type={{
76
+ config: {
77
+ type: "object",
78
+ required: true,
79
+ description:
80
+ "Resolved site config — title, description, logo, banner, theme, site URL, repoUrl, and search settings.",
81
+ },
82
+ navigation: {
83
+ type: "object",
84
+ required: true,
85
+ description: "The sidebar and tab tree inferred from your content.",
86
+ },
87
+ routes: {
88
+ type: "Route[]",
89
+ required: true,
90
+ description:
91
+ "Every content page: { id, path, title, indexable, hidden, draft, editUrl }.",
92
+ },
93
+ feeds: {
94
+ type: "Feed[]",
95
+ required: true,
96
+ description: "Generated RSS feeds: { href, title }.",
97
+ },
98
+ }}
99
+ />
100
+
101
+ `routes` carries page metadata but not frontmatter like `type` or `date`. To
102
+ build a list filtered by content type — a blog or changelog index — pair it with
103
+ Astro's `docs` content collection, which holds the frontmatter:
104
+
105
+ ```astro pages/blog/index.astro lineNumbers
106
+ ---
107
+ import { getCollection } from "astro:content";
108
+ import data from "blume:data";
109
+
110
+ // Each route's id matches its collection entry id.
111
+ const routeById = new Map(data.routes.map((route) => [route.id, route.path]));
112
+
113
+ const posts = (await getCollection("docs"))
114
+ .filter((entry) => entry.data.type === "blog" && !entry.data.draft)
115
+ .map((entry) => ({
116
+ description: entry.data.description,
117
+ href: routeById.get(entry.id),
118
+ title: entry.data.title,
119
+ }));
120
+ ---
121
+
122
+ <ul>
123
+ {
124
+ posts.map((post) => (
125
+ <li>
126
+ <a href={post.href}>{post.title}</a>
127
+ <p>{post.description}</p>
128
+ </li>
129
+ ))
130
+ }
131
+ </ul>
132
+ ```
133
+
134
+ ## Using the site layout
135
+
136
+ To give a custom page the full Blume chrome — header, sidebar, search, and theme
137
+ — wrap it in `RootLayout`, the same layout the generated pages use. Pull the
138
+ required props straight from `blume:data`:
139
+
140
+ ```astro pages/pricing.astro lineNumbers
141
+ ---
142
+ import RootLayout from "blume/components/layout/RootLayout.astro";
143
+ import data from "blume:data";
144
+ ---
145
+
146
+ <RootLayout
147
+ site={{ title: data.config.title, description: data.config.description }}
148
+ logo={data.config.logo}
149
+ banner={data.config.banner}
150
+ navigation={data.navigation}
151
+ page={{ title: "Pricing", route: "/pricing" }}
152
+ headings={[]}
153
+ themeMode={data.config.theme.mode}
154
+ searchEnabled={data.config.search.enabled}
155
+ searchProvider={data.config.search.provider}
156
+ indexable={true}
157
+ >
158
+ <h1>Pricing</h1>
159
+ </RootLayout>
160
+ ```
161
+
162
+ :::note
163
+ `RootLayout` is part of the generated runtime, so its props can change between
164
+ releases. When you want a layout that's fully yours,
165
+ [`blume eject`](/docs/configuration/customization#eject) turns `.blume/` into a
166
+ standard Astro project you own outright.
167
+ :::
168
+
169
+ ## Interactive pages
170
+
171
+ Custom pages are ordinary Astro, so you can drop in React (or any framework)
172
+ [islands](/docs/configuration/customization#react-islands) with a hydration directive.
173
+ React switches on automatically the moment your project contains a `.tsx` or
174
+ `.jsx` file.
175
+
176
+ <CardGroup cols={2}>
177
+ <Card
178
+ title="Customization"
179
+ href="/docs/configuration/customization"
180
+ icon="file"
181
+ >
182
+ Component overrides, React islands, the registry, and eject.
183
+ </Card>
184
+ <Card title="Blog" href="/docs/advanced/blog" icon="book-open">
185
+ Author posts and build a custom blog index.
186
+ </Card>
187
+ </CardGroup>
@@ -0,0 +1,7 @@
1
+ import { defineMeta } from "blume";
2
+
3
+ export default defineMeta({
4
+ order: 5,
5
+ pages: ["custom-pages", "changelog", "blog", "api-reference"],
6
+ title: "Advanced",
7
+ });
@@ -0,0 +1,12 @@
1
+ ---
2
+ title: v0.1.0
3
+ type: changelog
4
+ date: 2026-06-01
5
+ changelog:
6
+ version: 0.1.0
7
+ category: Release
8
+ ---
9
+
10
+ The first public release of Blume — a markdown-first docs framework on Astro and
11
+ Vite. Drop in Markdown or MDX, run `blume dev`, and ship a production-grade docs
12
+ site with search, theming, and AI-ready output.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: v0.2.0
3
+ type: changelog
4
+ date: 2026-06-24
5
+ changelog:
6
+ version: 0.2.0
7
+ category: Features
8
+ ---
9
+
10
+ A big batch of built-in components landed: **columns**, **frames**, **trees**,
11
+ **tooltips**, **code groups**, **panels**, **tiles**, and **fields**. Code groups
12
+ now render as proper language tabs, and the changelog gets this timeline.
13
+
14
+ - New `Accordion` / `AccordionItem`, `Expandable`, `Tooltip`, `Frame`, `Color`
15
+ - `CodeGroup` tabs with flush code blocks
16
+ - Redesigned `Prompt` with a copy-to-clipboard button
@@ -0,0 +1,228 @@
1
+ ---
2
+ title: AI
3
+ description: Machine-readable docs with llms.txt and an optional in-page Ask AI assistant.
4
+ ---
5
+
6
+ Blume has several opt-in AI features: machine-readable docs for external tools
7
+ (`llms.txt`), an in-page **Ask AI** assistant, and a hosted **MCP server** for
8
+ coding agents. Everything is off by default, and static docs stay fully static
9
+ until you turn a feature on.
10
+
11
+ ## llms.txt
12
+
13
+ Emit machine-readable versions of your docs that coding agents and chat
14
+ assistants can consume:
15
+
16
+ ```ts blume.config.ts lineNumbers
17
+ ai: {
18
+ llmsTxt: true,
19
+ }
20
+ ```
21
+
22
+ With this on, `blume build` writes two files to the root of your site:
23
+
24
+ - **`/llms.txt`** — a compact index: your site title and description, then a
25
+ linked list of every page with its summary.
26
+ - **`/llms-full.txt`** — the entire corpus: each page's full Markdown body, with
27
+ its source URL, in one file.
28
+
29
+ Draft pages are excluded. Set [`deployment.site`](/docs/deployment) so the links and
30
+ source URLs resolve to absolute addresses.
31
+
32
+ ## Raw Markdown
33
+
34
+ Append `.md` or `.mdx` to any page's URL to fetch its raw Markdown source —
35
+ perfect for LLMs, coding agents, and "copy as Markdown" workflows. It's available
36
+ for every page, in dev and production, with no configuration.
37
+
38
+ | URL | Returns |
39
+ | ----------------- | ----------------------- |
40
+ | `/quickstart` | The rendered page |
41
+ | `/quickstart.md` | The raw Markdown source |
42
+ | `/quickstart.mdx` | The raw Markdown source |
43
+
44
+ Nested routes work the same way (`/content/syntax.md`), and the home page is
45
+ served at `/index.md`.
46
+
47
+ ## Copy as Markdown
48
+
49
+ Every page carries a **Copy as Markdown** action — in the [page
50
+ actions](/docs/content/navigation#page-actions) beneath the table of contents — that copies the
51
+ page's raw Markdown to the clipboard. It's the same source served at the [`.md`
52
+ URL](#raw-markdown) above, ready to paste into an LLM, an issue, or your notes.
53
+ It's available on every page, in dev and production, with no configuration.
54
+
55
+ ## Open in chat
56
+
57
+ The **Open in chat** action opens the current page in an AI assistant — v0,
58
+ ChatGPT, Claude, T3 Chat, Scira, or Cursor — pre-filled with a prompt that points
59
+ it at the page's raw Markdown so it can answer questions about what you're
60
+ reading:
61
+
62
+ > Read `https://your-site/this-page.md` so I can ask you questions about this
63
+ > page.
64
+
65
+ Like Copy as Markdown, it needs no setup. The assistant fetches the page over its
66
+ public URL, so it works as soon as the page is deployed.
67
+
68
+ To embed a ready-to-copy prompt inline in your content — rather than a whole-page
69
+ action — use the [Prompt component](/docs/content/components#prompt), which renders
70
+ a labelled row with a **Copy prompt** button and an optional open-in-Cursor link.
71
+
72
+ ## Ask AI
73
+
74
+ Add an assistant that answers reader questions in an in-page chat panel, backed
75
+ by a streaming server endpoint and the [AI SDK](https://ai-sdk.dev):
76
+
77
+ ```ts blume.config.ts lineNumbers
78
+ ai: {
79
+ ask: {
80
+ enabled: true,
81
+ provider: "gateway", // default
82
+ model: "openai/gpt-5.5",
83
+ },
84
+ }
85
+ ```
86
+
87
+ ### Server output required
88
+
89
+ Ask AI is a server route (`POST /api/ask`), so it can't run on a static build.
90
+ Switch to server output and pick an adapter:
91
+
92
+ ```ts blume.config.ts lineNumbers
93
+ deployment: {
94
+ output: "server",
95
+ adapter: "vercel",
96
+ }
97
+ ```
98
+
99
+ A static build with Ask AI enabled fails fast with a message telling you to set
100
+ `deployment.output` to `server`. See [Deployment](/docs/deployment) for the adapters.
101
+
102
+ ### Backends
103
+
104
+ By default Ask AI routes through the **Vercel AI Gateway**: `model` is a
105
+ `provider/model` string, so you switch models by changing it (`openai/gpt-5.5`,
106
+ `anthropic/claude-sonnet-4-5`, and so on) with no provider SDK to install. The
107
+ gateway reads `AI_GATEWAY_API_KEY` from your environment and is wired up
108
+ automatically when you deploy on Vercel.
109
+
110
+ Set `provider` to point Ask AI somewhere else. Each backend reads its API key
111
+ from an environment variable, and the matching provider SDK is added to your
112
+ project's runtime automatically when you build — only the one you use:
113
+
114
+ | `provider` | `model` | API key env var |
115
+ | ------------------- | --------------------------------------------- | -------------------- |
116
+ | `gateway` (default) | a `provider/model` string via the AI Gateway | `AI_GATEWAY_API_KEY` |
117
+ | `openrouter` | any [OpenRouter](https://openrouter.ai) model | `OPENROUTER_API_KEY` |
118
+ | `llmgateway` | any [LLMGateway](https://llmgateway.io) model | `LLMGATEWAY_API_KEY` |
119
+ | `inkeep` | an [Inkeep](https://inkeep.com) QA model | `INKEEP_API_KEY` |
120
+ | `openai-compatible` | whatever your endpoint serves | set with `apiKeyEnv` |
121
+
122
+ For example, to use OpenRouter:
123
+
124
+ ```ts blume.config.ts lineNumbers
125
+ ai: {
126
+ ask: {
127
+ enabled: true,
128
+ provider: "openrouter",
129
+ model: "anthropic/claude-sonnet-4-5",
130
+ },
131
+ }
132
+ ```
133
+
134
+ Any OpenAI-compatible endpoint works through `openai-compatible` — supply the
135
+ `baseUrl` and the env var holding its key:
136
+
137
+ ```ts blume.config.ts lineNumbers
138
+ ai: {
139
+ ask: {
140
+ enabled: true,
141
+ provider: "openai-compatible",
142
+ baseUrl: "https://my-gateway.example.com/v1",
143
+ apiKeyEnv: "MY_GATEWAY_API_KEY",
144
+ model: "gpt-4o",
145
+ },
146
+ }
147
+ ```
148
+
149
+ Set `apiKeyEnv` (and, for the named providers, `baseUrl`) on any backend to point
150
+ at a different env var or proxy.
151
+
152
+ :::note
153
+ **Inkeep** answers from the content you've indexed in the Inkeep dashboard — it
154
+ runs its own retrieval — rather than from this site's pages. The other backends
155
+ are plain model passthroughs: the endpoint streams the reader's messages straight
156
+ to the model.
157
+ :::
158
+
159
+ Keys are read with `process.env`, which covers the Node, Vercel, and Netlify
160
+ adapters. On Cloudflare, expose the key through the platform's [runtime
161
+ binding](https://docs.astro.build/en/guides/integrations-guide/cloudflare/#environment-variables-and-secrets).
162
+ Enabling Ask AI also turns on React for the in-page island — see
163
+ [Customization](/docs/configuration/customization#react-islands).
164
+
165
+ ## MCP server
166
+
167
+ Host a [Model Context Protocol](https://modelcontextprotocol.io) server so coding
168
+ agents (Claude Code, Cursor, VS Code, claude.ai connectors) can search and read
169
+ your docs directly — no scraping:
170
+
171
+ ```ts blume.config.ts lineNumbers
172
+ mcp: {
173
+ enabled: true,
174
+ route: "/mcp", // where the server is mounted
175
+ }
176
+ ```
177
+
178
+ | Option | Default | Description |
179
+ | -------------- | ------- | ------------------------------------------------- |
180
+ | `enabled` | `false` | Generate and host the MCP server. |
181
+ | `route` | `/mcp` | Path the Streamable-HTTP endpoint is mounted on. |
182
+ | `name` | title | Server name shown to clients (defaults to title). |
183
+ | `instructions` | — | Optional system hint passed to connecting agents. |
184
+
185
+ The server exposes four read-only tools — `search_docs`, `get_page`,
186
+ `list_pages`, and `get_navigation` — and publishes discovery documents at
187
+ `/.well-known/mcp.json` and `/.well-known/mcp/server-card.json`. Each page's
188
+ **Connect to MCP** menu offers copy-and-go install for Claude Code, Cursor, and
189
+ VS Code (shown once [`deployment.site`](/docs/deployment) is set).
190
+
191
+ `search_docs` runs its own full-text index, so it works regardless of your
192
+ [search](/docs/configuration/search) provider — and even when search is set to
193
+ `none`. The MCP server is a separate feature from on-page search.
194
+
195
+ ### Server output required
196
+
197
+ The MCP server is a live endpoint (`/mcp`), so it can't run on a static build.
198
+ Switch to server output and pick an adapter:
199
+
200
+ ```ts blume.config.ts lineNumbers
201
+ deployment: {
202
+ output: "server",
203
+ adapter: "node", // or "vercel" | "netlify" | "cloudflare"
204
+ site: "https://docs.example.com",
205
+ }
206
+ ```
207
+
208
+ A static build with `mcp.enabled` fails fast with a message telling you to set
209
+ `deployment.output` to `server`. See [Deployment](/docs/deployment) for the
210
+ adapters. Once deployed, connect from Claude Code with:
211
+
212
+ ```bash
213
+ claude mcp add --transport http my-docs https://docs.example.com/mcp
214
+ ```
215
+
216
+ ## Agent skill
217
+
218
+ Building a Blume site with the help of a coding agent? Install the Blume
219
+ [agent skill](https://docs.claude.com/en/docs/claude-code/skills) so it knows
220
+ how Blume works without you explaining it:
221
+
222
+ ```bash
223
+ npx skills add haydenbleasel/blume
224
+ ```
225
+
226
+ The skill teaches the agent what Blume is and how to scaffold, write, and
227
+ configure a site, and points it at the full docs bundled in the installed
228
+ package (`node_modules/blume/docs`).
@@ -0,0 +1,98 @@
1
+ ---
2
+ title: Analytics
3
+ description: First-party web analytics — Vercel Web Analytics, PostHog, or any custom script — wired up from blume.config.ts.
4
+ ---
5
+
6
+ Blume injects analytics for you from a single `analytics` block in
7
+ `blume.config.ts`. Vercel Web Analytics and PostHog are first-class, and a
8
+ `scripts` escape hatch covers every other provider — Plausible, Fathom, Google
9
+ Analytics, Umami, and the rest.
10
+
11
+ Analytics loads in **production builds only**. The scripts are emitted by
12
+ `blume build`, never by `blume dev`, so local traffic never reaches your
13
+ dashboards and you don't need a separate "development" project.
14
+
15
+ :::note
16
+ Analytics is opt-in. With no `analytics` block, Blume injects nothing.
17
+ :::
18
+
19
+ ## Vercel Web Analytics
20
+
21
+ Set `vercel: true` to add [Vercel Web Analytics](https://vercel.com/docs/analytics).
22
+ Blume injects Vercel's first-party script, which is served from your own domain
23
+ once Web Analytics is enabled for the project in the Vercel dashboard.
24
+
25
+ ```ts blume.config.ts lineNumbers
26
+ analytics: {
27
+ vercel: true,
28
+ }
29
+ ```
30
+
31
+ No keys are needed — the script reports to the project it's deployed under. This
32
+ only collects data on Vercel deployments, where the `/_vercel/insights` endpoint
33
+ exists.
34
+
35
+ ## PostHog
36
+
37
+ Provide your **project API key** to add [PostHog](https://posthog.com). The host
38
+ defaults to PostHog Cloud US; set `host` for EU Cloud
39
+ (`https://eu.i.posthog.com`) or a self-hosted instance.
40
+
41
+ ```ts blume.config.ts lineNumbers
42
+ analytics: {
43
+ posthog: {
44
+ key: "phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
45
+ host: "https://us.i.posthog.com", // optional, this is the default
46
+ },
47
+ }
48
+ ```
49
+
50
+ The project API key is safe to ship to the browser — it's a public,
51
+ write-only key.
52
+
53
+ ## Custom scripts
54
+
55
+ Use `scripts` to load any other analytics provider. Each entry renders one
56
+ `<script>` tag and must set **exactly one** of `src` (external) or `content`
57
+ (inline).
58
+
59
+ ```ts blume.config.ts lineNumbers
60
+ analytics: {
61
+ scripts: [
62
+ // Plausible
63
+ {
64
+ src: "https://plausible.io/js/script.js",
65
+ strategy: "defer",
66
+ attributes: { "data-domain": "example.com" },
67
+ },
68
+ // Fathom
69
+ {
70
+ src: "https://cdn.usefathom.com/script.js",
71
+ strategy: "defer",
72
+ attributes: { "data-site": "ABCDEFG" },
73
+ },
74
+ // An inline snippet
75
+ {
76
+ content: "console.log('analytics ready')",
77
+ },
78
+ ],
79
+ }
80
+ ```
81
+
82
+ `attributes` is a map of extra HTML attributes (`data-*`, `id`, …) spread onto
83
+ the tag, and `strategy` adds `async` or `defer` to external scripts.
84
+
85
+ ## Options
86
+
87
+ | Option | Default | Description |
88
+ | ---------------------- | -------------------------- | ------------------------------------------------------- |
89
+ | `vercel` | `false` | Add Vercel Web Analytics (Vercel deployments only). |
90
+ | `posthog.key` | — | PostHog project API key. Enables PostHog when set. |
91
+ | `posthog.host` | `https://us.i.posthog.com` | PostHog ingestion host (EU Cloud or self-hosted). |
92
+ | `scripts[].src` | — | External script URL. Mutually exclusive with `content`. |
93
+ | `scripts[].content` | — | Inline script body. Mutually exclusive with `src`. |
94
+ | `scripts[].strategy` | — | `async` or `defer` for an external script. |
95
+ | `scripts[].attributes` | — | Extra HTML attributes spread onto the `<script>` tag. |
96
+
97
+ All three can be combined — enable Vercel, PostHog, and custom scripts together.
98
+ For deploying your built site, see [Deployment](/docs/deployment).
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: Customization
3
+ description: Override components, add interactive islands, mount custom pages, install registry components, or eject.
4
+ ---
5
+
6
+ ## Component overrides
7
+
8
+ Add a `components.ts` (or `components.tsx`) to your project root and export
9
+ `defineComponents`. The `mdx` map either **replaces** a built-in component or
10
+ **adds** a new one — available in every `.mdx` page with no import.
11
+
12
+ ```ts components.ts lineNumbers
13
+ import { defineComponents } from "blume";
14
+ import Callout from "./components/Callout.astro";
15
+ import Pricing from "./components/Pricing.astro";
16
+
17
+ export default defineComponents({
18
+ mdx: {
19
+ Callout, // replace the built-in Callout
20
+ Pricing, // add a new <Pricing /> component
21
+ },
22
+ });
23
+ ```
24
+
25
+ Keys are the names you write in MDX (`<Callout>`, `<Pricing>`). Use the `.tsx`
26
+ filename when you import React components.
27
+
28
+ ## Interactive islands
29
+
30
+ For interactive UI (React, Vue, or Svelte), drop a component into an `islands/`
31
+ folder and use it in any MDX page — Blume hydrates it for you, no wrapper or
32
+ registration needed:
33
+
34
+ ```tsx islands/Counter.tsx lineNumbers
35
+ import { useState } from "react";
36
+
37
+ export default function Counter() {
38
+ const [n, setN] = useState(0);
39
+ return <button onClick={() => setN(n + 1)}>Clicked {n}</button>;
40
+ }
41
+ ```
42
+
43
+ ```mdx page.mdx
44
+ Use it anywhere: <Counter />
45
+ ```
46
+
47
+ See [Islands](/docs/content/islands) for hydration strategies and framework
48
+ setup.
49
+
50
+ ## Custom pages
51
+
52
+ Add `.astro` files under your `pages/` folder to mount fully custom routes
53
+ alongside your docs — a landing page, a pricing page, or a hand-built index. They
54
+ keep their location, so relative imports and `getStaticPaths` work as usual, and
55
+ they can read your config, navigation, and routes from the `blume:data` module.
56
+
57
+ See [Custom Pages](/docs/advanced/custom-pages) for the full guide.
58
+
59
+ ## Registry
60
+
61
+ `blume add` copies a Blume-maintained component into your project as **source** —
62
+ you own it and can edit it freely. Run it with no arguments to list what's
63
+ available:
64
+
65
+ ```bash
66
+ blume add
67
+ ```
68
+
69
+ Install a widget, or any built-in layout slot you want to customize — the
70
+ header, sidebar, breadcrumbs, table of contents, or pagination:
71
+
72
+ ```bash
73
+ blume add pagination
74
+ ```
75
+
76
+ The copy imports the rest of the framework from `blume/*`, so it renders
77
+ exactly like the built-in until you change it. `blume add` prints the
78
+ `defineComponents` snippet to register it under the matching layout slot.
79
+
80
+ ## Eject
81
+
82
+ When you want full control, eject the generated runtime into a standalone Astro
83
+ project:
84
+
85
+ ```bash
86
+ blume eject --yes
87
+ ```
88
+
89
+ Eject is a one-way step: the hidden `.blume/` runtime becomes a normal Astro app
90
+ you own and can modify directly. The `blume` package stays importable, so you
91
+ keep its components, theme, and Markdown processors.