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,168 @@
1
+ ---
2
+ title: Navigation
3
+ description: Build the sidebar from your files, then refine it with frontmatter, folder meta, or config.
4
+ ---
5
+
6
+ Blume builds your sidebar from the file system, then lets you refine it as much —
7
+ or as little — as you want: page by page, folder by folder, or with one explicit
8
+ config. Breadcrumbs, previous/next links, and the on-page outline all follow from
9
+ the same model, with nothing to wire up.
10
+
11
+ ## The generated sidebar
12
+
13
+ By default the sidebar mirrors your content tree:
14
+
15
+ - folders become **groups**, files become **pages**
16
+ - a page's label is its frontmatter `title`; a group's label is the humanized
17
+ folder name
18
+ - items sort by [numeric prefix](/docs/content), then alphabetically, and a folder's
19
+ `index` page comes first
20
+
21
+ That's enough for many sites — everything below is opt-in.
22
+
23
+ ## Page label, icon, and badge
24
+
25
+ Tune how a single page appears in the sidebar from its frontmatter, under
26
+ `sidebar`:
27
+
28
+ ```yaml lineNumbers
29
+ sidebar:
30
+ label: Quickstart # override the title in the sidebar
31
+ icon: rocket # an icon from Blume's built-in set
32
+ badge: New # a small label beside the entry
33
+ order: 1 # sort position within its group
34
+ ```
35
+
36
+ See [Frontmatter](/docs/reference/frontmatter) for the full page schema.
37
+
38
+ ## Folder groups
39
+
40
+ Each folder becomes a sidebar group. Drop a [`meta.ts`](/docs/content/meta)
41
+ beside its pages to set the group's title, icon, order, [display
42
+ mode](/docs/content/meta#display-modes), and the order of its children:
43
+
44
+ ```ts meta.ts
45
+ import { defineMeta } from "blume";
46
+
47
+ export default defineMeta({
48
+ title: "Guides",
49
+ icon: "book-open",
50
+ pages: ["configuration", "theming", "deployment"],
51
+ });
52
+ ```
53
+
54
+ See [Folder meta](/docs/content/meta) for every field, the three display modes,
55
+ and computing meta at scan time.
56
+
57
+ To group pages _without_ adding a URL segment, use a parenthesized folder name —
58
+ see [Pages](/docs/content#group-folders).
59
+
60
+ ## Ordering
61
+
62
+ When the sidebar is generated, order is resolved highest priority first:
63
+
64
+ <Steps>
65
+ <Step title="Config sidebar">
66
+ An explicit `navigation.sidebar` replaces the generated tree entirely.
67
+ </Step>
68
+ <Step title="Folder meta">
69
+ The `pages` array in `meta.ts` orders a group.
70
+ </Step>
71
+ <Step title="Frontmatter">`sidebar.order` on a page.</Step>
72
+ <Step title="File system">
73
+ An `index` page first, then numeric prefixes, then alphabetical by label.
74
+ </Step>
75
+ </Steps>
76
+
77
+ ## Hidden pages
78
+
79
+ Hide a page from the sidebar — and from previous/next pagination — while keeping
80
+ it built and reachable by its URL:
81
+
82
+ ```yaml
83
+ sidebar:
84
+ hidden: true
85
+ ```
86
+
87
+ ## Tabs
88
+
89
+ Render top-level sections as tabs in the header, useful for separating, say, docs
90
+ from an API reference. A tab is highlighted when the current route falls under
91
+ its `path`:
92
+
93
+ ```ts blume.config.ts lineNumbers
94
+ navigation: {
95
+ tabs: [
96
+ { label: "Docs", path: "/", icon: "book-open" },
97
+ { label: "API", path: "/api", icon: "rocket" },
98
+ ],
99
+ }
100
+ ```
101
+
102
+ ## Explicit sidebar
103
+
104
+ For full control, define `navigation.sidebar` in config. When it's set, Blume
105
+ uses it verbatim and skips file-system generation:
106
+
107
+ ```ts blume.config.ts lineNumbers
108
+ navigation: {
109
+ sidebar: [
110
+ "/", // a page, referenced by route
111
+ {
112
+ label: "Guides", // a group
113
+ collapsed: false,
114
+ items: ["/configuration", "/configuration/theming"],
115
+ },
116
+ { label: "GitHub", href: "https://github.com/owner/repo" }, // an external link
117
+ ],
118
+ }
119
+ ```
120
+
121
+ Each item is a page route (a string), a group (`label` + `items`), or a link
122
+ (`label` + `href`). Groups can nest, take a [`display`
123
+ mode](/docs/content/meta#display-modes), and start `collapsed`.
124
+
125
+ ## Repository link
126
+
127
+ When you set [`github`](/docs/configuration) in your config, Blume shows a GitHub
128
+ icon in the header — beside the theme toggle — that links to your repository. It's
129
+ on by default; hide it with `navigation.repo`:
130
+
131
+ ```ts blume.config.ts lineNumbers
132
+ navigation: {
133
+ repo: false, // hide the header GitHub link (default: true)
134
+ }
135
+ ```
136
+
137
+ The link only appears when `github` is configured, so projects without a repo are
138
+ unaffected either way.
139
+
140
+ ## Breadcrumbs and pagination
141
+
142
+ These come for free from the sidebar tree — no configuration:
143
+
144
+ - **Breadcrumbs** show the current page's parent group above the title.
145
+ - **Previous and next** links at the foot of each page follow sidebar order,
146
+ skipping hidden pages.
147
+
148
+ ## On this page
149
+
150
+ A right-rail outline is generated automatically from each page's `##` and `###`
151
+ headings, so long pages stay scannable. On narrower screens, where the right rail
152
+ is hidden, it collapses into an “On this page” dropdown above the content.
153
+
154
+ ## Page actions
155
+
156
+ Below the table of contents, every page shows a set of quick actions:
157
+
158
+ - **Edit this page on GitHub** — links straight to the source file. Appears once
159
+ you set [`github`](/docs/configuration) in your config.
160
+ - **Scroll to top** — smoothly returns to the top of long pages.
161
+ - **Give feedback** — opens a prefilled GitHub issue with an optional reaction and
162
+ note (also requires `github`).
163
+
164
+ Three more hand the page to AI tools — **Copy as Markdown**, **Open in chat**, and
165
+ **Ask AI about this page** — covered in [AI](/docs/configuration/ai#copy-as-markdown).
166
+
167
+ With [`export`](/docs/configuration/export) on, an **Export** action also lets
168
+ readers download the page as a PDF or EPUB.
@@ -0,0 +1,216 @@
1
+ ---
2
+ title: Content sources
3
+ description: Pull docs from local files, a remote repo, or any custom backend — and mix several sources into one site.
4
+ ---
5
+
6
+ By default Blume reads a folder of `.md`/`.mdx` files. **Content sources** let
7
+ you pull pages from somewhere else — a remote repository, a CMS, or any custom
8
+ backend — and mix several sources into a single site. Sources are read at
9
+ build time; Blume stays static-first.
10
+
11
+ ## The default
12
+
13
+ With no configuration, Blume scans your content root (`docs` by default) as one
14
+ implicit filesystem source. The top-level `content.root`/`include`/`exclude`
15
+ options still work exactly as before — nothing to change.
16
+
17
+ ```ts blume.config.ts
18
+ import { defineConfig } from "blume";
19
+
20
+ export default defineConfig({
21
+ content: { root: "docs" },
22
+ });
23
+ ```
24
+
25
+ ## Multiple sources
26
+
27
+ Add a `content.sources` array to compose sources. Each entry is namespaced by an
28
+ optional `prefix`, so its routes nest under `/<prefix>/…`. When `sources` is
29
+ present it replaces the implicit default, so include a `filesystem` entry for
30
+ your local docs.
31
+
32
+ ```ts blume.config.ts
33
+ import { defineConfig } from "blume";
34
+
35
+ export default defineConfig({
36
+ content: {
37
+ sources: [
38
+ // Local docs at the site root
39
+ { type: "filesystem", root: "docs" },
40
+
41
+ // Remote MDX from a GitHub repo, mounted under /sdk
42
+ {
43
+ type: "mdx-remote",
44
+ prefix: "sdk",
45
+ github: { owner: "acme", repo: "sdk", ref: "main", path: "docs" },
46
+ },
47
+ ],
48
+ },
49
+ });
50
+ ```
51
+
52
+ If two sources resolve to the same route, Blume reports a `BLUME_DUPLICATE_ROUTE`
53
+ build error — give each source a distinct `prefix`.
54
+
55
+ ## Remote MDX
56
+
57
+ The built-in `mdx-remote` source fetches raw `.md`/`.mdx` over HTTP. Enumerate
58
+ files either from a GitHub repo subtree (`github`) or explicitly against a raw
59
+ base URL (`url` + `files`):
60
+
61
+ ```ts blume.config.ts
62
+ {
63
+ type: "mdx-remote",
64
+ prefix: "sdk",
65
+ url: "https://raw.githubusercontent.com/acme/sdk/main/docs",
66
+ files: ["intro.mdx", "guide.mdx"],
67
+ }
68
+ ```
69
+
70
+ A private repo's token is read from the `GITHUB_TOKEN` environment variable — it
71
+ is never inlined into your config or generated output.
72
+
73
+ Remote pages are rendered with full MDX-plus-component fidelity: their bodies are
74
+ materialized into a hidden staging directory and rendered through Astro
75
+ alongside your local docs, so callouts, tabs, and every other Blume component
76
+ keep working.
77
+
78
+ ### Caching and offline builds
79
+
80
+ Each remote source keeps a snapshot under `.blume/cache/<source>/`. If a fetch
81
+ fails — a network blip or a CMS outage — Blume serves the last-known-good
82
+ snapshot with a warning rather than failing the build. The cache lives inside
83
+ `.blume/` and is regenerated, never committed.
84
+
85
+ In dev, remote content is fetched once and frozen for the session; restart the
86
+ dev server to refresh it. Local filesystem sources hot-reload as usual. To poll
87
+ a remote source for changes instead, set `pollInterval` (seconds) on it — the
88
+ dev server re-fetches on that interval and reloads only when the content
89
+ actually changes. Leave it unset to avoid hitting the API while you work.
90
+
91
+ ## Sanity
92
+
93
+ The built-in `sanity` source runs a GROQ query and maps each document's fields
94
+ to frontmatter and its Portable Text body to Markdown. The `@sanity/client`
95
+ package is an optional peer dependency — install it only if you use this source.
96
+
97
+ ```ts blume.config.ts
98
+ import { defineConfig } from "blume";
99
+
100
+ export default defineConfig({
101
+ content: {
102
+ sources: [
103
+ { type: "filesystem", root: "docs" },
104
+ {
105
+ type: "sanity",
106
+ prefix: "guides",
107
+ projectId: "abc123",
108
+ dataset: "production",
109
+ query: `*[_type == "guide"]`,
110
+ // Field paths default to title / slug.current / body / _updatedAt
111
+ fields: { slug: "slug.current", body: "content" },
112
+ },
113
+ ],
114
+ },
115
+ });
116
+ ```
117
+
118
+ A read token for a private dataset comes from the `SANITY_TOKEN` environment
119
+ variable. Custom Portable Text block types map to Blume components through the
120
+ adapter's `serializers` option, available when you construct `sanitySource`
121
+ directly via a [custom source](#custom-sources).
122
+
123
+ ## Notion
124
+
125
+ The built-in `notion` source turns a Notion database into a collection: each row
126
+ becomes a page, its properties become frontmatter, and its block tree becomes
127
+ MDX. Callouts, toggles, columns, and code blocks map to the matching Blume
128
+ components. `@notionhq/client` is an optional peer dependency.
129
+
130
+ ```ts blume.config.ts
131
+ import { defineConfig } from "blume";
132
+
133
+ export default defineConfig({
134
+ content: {
135
+ sources: [
136
+ { type: "filesystem", root: "docs" },
137
+ {
138
+ type: "notion",
139
+ prefix: "handbook",
140
+ database: process.env.NOTION_DB_ID,
141
+ // Property names default to the title-typed prop / Description / Slug / Order
142
+ // Set publishedValue to treat Status as a publish gate (opt-in)
143
+ publishedValue: "Published",
144
+ },
145
+ ],
146
+ },
147
+ });
148
+ ```
149
+
150
+ The integration token comes from the `NOTION_TOKEN` environment variable (share
151
+ the database with your integration). By default every page is imported; set
152
+ `publishedValue` to make the `Status` property a publish gate — any other value
153
+ then maps to `draft: true`, which production builds drop. **Notion image URLs
154
+ are signed and expire**, so the adapter downloads them at build time into the
155
+ site's assets and rewrites the references — a CMS image never rots a static
156
+ build.
157
+
158
+ ## Preview and sync
159
+
160
+ Two flags control how remote content is fetched and what's included:
161
+
162
+ - **`--preview`** on `blume dev` or `blume build` renders drafts and pulls
163
+ unpublished CMS content — Sanity switches to its `previewDrafts` perspective,
164
+ and Notion stops filtering by `Status`. Production builds without the flag
165
+ exclude drafts as usual, so a preview build is a safe way to review
166
+ unpublished work before it ships.
167
+ - **`blume sync`** re-fetches every remote source and regenerates the runtime.
168
+ Dev is cache-first — a remote source is fetched once and served from
169
+ `.blume/cache` on restart (fast and offline-tolerant), so `blume sync` is how
170
+ you pull the latest CMS content without restarting the dev server (a running
171
+ server hot-reloads). Add `--force` to drop the cache first, or set
172
+ `pollInterval` on a source to refresh automatically.
173
+
174
+ ```sh
175
+ blume dev --preview # author workflow: see drafts live
176
+ blume build --preview # render a full preview build
177
+ blume sync # refresh remote content now
178
+ blume sync --force # ...ignoring any cached snapshot
179
+ ```
180
+
181
+ ## Custom sources
182
+
183
+ Any object implementing the `ContentSource` interface can be passed directly,
184
+ which is how an adapter with custom serializers — or any backend not built in —
185
+ plugs in without its SDK touching the core install:
186
+
187
+ ```ts blume.config.ts
188
+ import { defineConfig } from "blume";
189
+ import { sanitySource } from "blume/sources/sanity.ts";
190
+
191
+ export default defineConfig({
192
+ content: {
193
+ sources: [
194
+ { type: "filesystem", root: "docs" },
195
+ {
196
+ type: "custom",
197
+ source: sanitySource({
198
+ name: "guides",
199
+ prefix: "guides",
200
+ projectId: "abc123",
201
+ dataset: "production",
202
+ query: `*[_type == "guide"]`,
203
+ // Map custom Portable Text blocks to Blume components
204
+ serializers: {
205
+ callout: (block) => `<Callout>${block.text}</Callout>`,
206
+ },
207
+ }),
208
+ },
209
+ ],
210
+ },
211
+ });
212
+ ```
213
+
214
+ A source normalizes its native shape (Portable Text, Notion blocks, remote HTML)
215
+ to Markdown/MDX text, so the same components and markdown features apply no
216
+ matter where a page comes from.