blume 0.3.0 → 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 (128) hide show
  1. package/dist/cli/index.js +1631 -940
  2. package/dist/cli/index.js.map +62 -50
  3. package/dist/types/core/data.d.ts +2 -0
  4. package/dist/types/core/project.d.ts +12 -2
  5. package/dist/types/core/schema.d.ts +442 -292
  6. package/dist/types/core/types.d.ts +7 -0
  7. package/dist/types/migrate/mintlify/assets.d.ts +8 -0
  8. package/docs/01-quickstart.mdx +5 -16
  9. package/docs/02-deployment.mdx +21 -54
  10. package/docs/advanced/api-reference.mdx +34 -51
  11. package/docs/advanced/blog.mdx +9 -25
  12. package/docs/advanced/bridge.mdx +74 -0
  13. package/docs/advanced/changelog.mdx +10 -33
  14. package/docs/advanced/custom-pages.mdx +21 -78
  15. package/docs/advanced/meta.ts +8 -1
  16. package/docs/advanced/migrate.mdx +119 -0
  17. package/docs/configuration/ai.mdx +42 -103
  18. package/docs/configuration/analytics.mdx +20 -38
  19. package/docs/configuration/customization.mdx +40 -73
  20. package/docs/configuration/export.mdx +9 -34
  21. package/docs/configuration/index.mdx +67 -87
  22. package/docs/configuration/search.mdx +17 -54
  23. package/docs/configuration/seo.mdx +17 -48
  24. package/docs/configuration/theming.mdx +20 -42
  25. package/docs/content/components.mdx +95 -101
  26. package/docs/content/i18n.mdx +21 -72
  27. package/docs/content/index.mdx +18 -48
  28. package/docs/content/islands.mdx +25 -52
  29. package/docs/content/meta.mdx +23 -50
  30. package/docs/content/navigation.mdx +23 -62
  31. package/docs/content/sources.mdx +20 -83
  32. package/docs/content/syntax.mdx +37 -105
  33. package/docs/index.mdx +12 -41
  34. package/docs/reference/cli.mdx +47 -30
  35. package/docs/reference/frontmatter.mdx +7 -5
  36. package/package.json +11 -1
  37. package/src/astro/generate.ts +18 -8
  38. package/src/astro/integration.ts +26 -3
  39. package/src/astro/islands.ts +6 -2
  40. package/src/astro/markdown-negotiation.ts +17 -3
  41. package/src/astro/pages.ts +6 -1
  42. package/src/astro/static-assets.ts +117 -0
  43. package/src/astro/templates.ts +76 -30
  44. package/src/cli/args.ts +23 -0
  45. package/src/cli/commands/build.ts +129 -62
  46. package/src/cli/commands/check.ts +20 -0
  47. package/src/cli/commands/dev.ts +11 -2
  48. package/src/cli/commands/doctor.ts +10 -1
  49. package/src/cli/commands/eject.ts +3 -1
  50. package/src/cli/commands/init.ts +21 -1
  51. package/src/cli/commands/preview.ts +2 -1
  52. package/src/cli/commands/validate.ts +12 -1
  53. package/src/cli/dev-lock.ts +92 -0
  54. package/src/cli/log.ts +11 -0
  55. package/src/cli/prepare.ts +3 -0
  56. package/src/components/BlumePage.astro +8 -0
  57. package/src/components/Icon.astro +13 -10
  58. package/src/components/content/ApiField.astro +75 -0
  59. package/src/components/content/ParamField.astro +39 -0
  60. package/src/components/content/RequestField.astro +23 -0
  61. package/src/components/content/ResponseField.astro +23 -0
  62. package/src/components/content/Step.astro +1 -1
  63. package/src/components/content/YouTube.astro +35 -0
  64. package/src/components/content/youtube.ts +46 -0
  65. package/src/components/islands/ask-ai.tsx +14 -14
  66. package/src/components/layout/Breadcrumbs.astro +7 -2
  67. package/src/components/layout/NavTree.astro +24 -8
  68. package/src/components/layout/RootLayout.astro +56 -34
  69. package/src/components/layout/Search.astro +1 -1
  70. package/src/components/openapi/ApiOverview.astro +84 -0
  71. package/src/components/openapi/MethodBadge.astro +28 -0
  72. package/src/components/openapi/Operation.astro +140 -0
  73. package/src/components/openapi/ParametersTable.astro +97 -0
  74. package/src/components/openapi/RequestBody.astro +58 -0
  75. package/src/components/openapi/RequestPanel.astro +169 -0
  76. package/src/components/openapi/Responses.astro +91 -0
  77. package/src/components/openapi/SchemaProperty.astro +118 -0
  78. package/src/components/openapi/SchemaTable.astro +86 -0
  79. package/src/components/openapi/helpers.ts +238 -0
  80. package/src/components/openapi/panel.ts +59 -0
  81. package/src/components/openapi/snippets.ts +201 -0
  82. package/src/components/props.ts +3 -0
  83. package/src/core/assets.ts +31 -0
  84. package/src/core/bridge.ts +10 -0
  85. package/src/core/builtin-tags.ts +6 -0
  86. package/src/core/data.ts +2 -0
  87. package/src/core/diagnostics.ts +6 -1
  88. package/src/core/gitignore.ts +30 -0
  89. package/src/core/links.ts +60 -19
  90. package/src/core/project-graph.ts +5 -1
  91. package/src/core/project.ts +25 -3
  92. package/src/core/schema.ts +54 -6
  93. package/src/core/sources/mdx-remote.ts +54 -8
  94. package/src/core/sources/mintlify.ts +1 -1
  95. package/src/core/sources/normalize.ts +6 -1
  96. package/src/core/sources/notion.ts +49 -5
  97. package/src/core/sources/resolve.ts +28 -6
  98. package/src/core/sources/sanity.ts +5 -1
  99. package/src/core/types.ts +7 -0
  100. package/src/deploy/rss.ts +1 -8
  101. package/src/deploy/sitemap.ts +20 -1
  102. package/src/deploy/xml.ts +8 -0
  103. package/src/markdown/directives.ts +15 -7
  104. package/src/markdown/package-commands.ts +26 -4
  105. package/src/migrate/fumadocs/content.ts +14 -1
  106. package/src/migrate/fumadocs/groups.ts +7 -0
  107. package/src/migrate/fumadocs/index.ts +5 -2
  108. package/src/migrate/mintlify/assets.ts +46 -0
  109. package/src/migrate/mintlify/config.ts +153 -1
  110. package/src/migrate/mintlify/content.ts +8 -2
  111. package/src/migrate/mintlify/index.ts +111 -46
  112. package/src/migrate/shared.ts +12 -27
  113. package/src/og/card.ts +14 -2
  114. package/src/openapi/model.ts +174 -0
  115. package/src/openapi/parse.ts +48 -0
  116. package/src/openapi/references.ts +164 -0
  117. package/src/openapi/render-mdx.ts +76 -0
  118. package/src/openapi/scalar.ts +15 -103
  119. package/src/openapi/source.ts +140 -0
  120. package/src/registry/eject.ts +28 -5
  121. package/src/registry/registry.ts +6 -0
  122. package/src/registry/rewrite-imports.ts +31 -19
  123. package/src/search/documents.ts +23 -5
  124. package/src/search/sync/algolia.ts +5 -1
  125. package/src/search/sync/typesense.ts +24 -16
  126. package/src/theme/chrome-icons.ts +22 -0
  127. package/src/theme/icons.ts +151 -161
  128. package/src/theme/palette.ts +26 -7
@@ -3,16 +3,11 @@ title: Components
3
3
  description: The built-in JSX components — cards, columns, steps, tabs, accordions, badges, code groups, frames, trees, tooltips, type tables, live component previews, diffs, and a GitHub card — usable in any MDX page.
4
4
  ---
5
5
 
6
- Blume ships an accessible, themeable component set available in any `.mdx` page
7
- with **no imports**. Each one is shown below with a live preview and its source.
8
- Components are vanilla and React-free; React only switches on if you add your own
9
- island.
6
+ Blume ships an accessible, themeable component set available in any `.mdx` page with **no imports**. Each one is shown below with a live preview and its source. Components are vanilla and React-free; React only switches on if you add your own island.
10
7
 
11
8
  ## Card and CardGroup
12
9
 
13
- Cards link to a destination with an icon, title, and short blurb. Group them with
14
- `CardGroup` for a responsive grid. Reach for them on landing pages, section
15
- indexes, and “next steps” — anywhere you’re guiding the reader onward.
10
+ Cards link to a destination with an icon, title, and short blurb. Group them with `CardGroup` for a responsive grid. Reach for them on landing pages, section indexes, and “next steps” — anywhere you’re guiding the reader onward.
16
11
 
17
12
  <CardGroup cols={2}>
18
13
  <Card title="Quickstart" href="/docs/quickstart" icon="rocket">
@@ -34,13 +29,11 @@ indexes, and “next steps” — anywhere you’re guiding the reader onward.
34
29
  </CardGroup>
35
30
  ```
36
31
 
37
- `Card` takes `title`, an optional `href` (omit it for a non-clickable card), and
38
- an `icon` from Blume's built-in icon set. `CardGroup` takes `cols` (default `2`).
32
+ `Card` takes `title`, an optional `href` (omit it for a non-clickable card), and an `icon` from Blume's built-in icon set. `CardGroup` takes `cols` (default `2`).
39
33
 
40
34
  ## Steps
41
35
 
42
- A numbered vertical sequence for ordered instructions — installs, setup flows,
43
- and tutorials where the order matters. Each `Step` takes a `title`.
36
+ A numbered vertical sequence for ordered instructions — installs, setup flows, and tutorials where the order matters. Each `Step` takes a `title`.
44
37
 
45
38
  <Steps>
46
39
  <Step title="Install Blume">Add the package to your project.</Step>
@@ -62,9 +55,7 @@ and tutorials where the order matters. Each `Step` takes a `title`.
62
55
 
63
56
  ## Tabs
64
57
 
65
- Switch between equivalent content in place — language variants, OS-specific
66
- commands, or alternative approaches — without stacking everything on the page.
67
- Each `Tab` takes a `title`.
58
+ Switch between equivalent content in place — language variants, OS-specific commands, or alternative approaches — without stacking everything on the page. Each `Tab` takes a `title`.
68
59
 
69
60
  <Tabs>
70
61
  <Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
@@ -80,8 +71,7 @@ Each `Tab` takes a `title`.
80
71
 
81
72
  ## Badge
82
73
 
83
- A small inline label for status or metadata — version tags, “new” or “beta”
84
- markers, stability levels. The `variant` tunes the color to the meaning.
74
+ A small inline label for status or metadata — version tags, “new” or “beta” markers, stability levels. The `variant` tunes the color to the meaning.
85
75
 
86
76
  ### Default
87
77
 
@@ -135,9 +125,7 @@ A negative or breaking state, such as a deprecation.
135
125
 
136
126
  ## Icon
137
127
 
138
- Render an icon from Blume's built-in set by name — the same set the `icon` props
139
- on cards, tiles, tabs, and sidebar entries draw from. Names are lowercase and
140
- kebab-cased (`rocket`, `book-open`, `chevron-right`).
128
+ Render an icon by name — the same `icon` props power cards, steps, tiles, tabs, and sidebar entries. Names come from three bundled libraries: [Lucide](https://lucide.dev) (the default), [Font Awesome](https://fontawesome.com/icons) (its free set), and [Tabler](https://tabler.io/icons). Names are lowercase and kebab-cased (`rocket`, `gauge-high`, `book-open`).
141
129
 
142
130
  <Icon icon="rocket" size={20} />
143
131
 
@@ -145,16 +133,30 @@ kebab-cased (`rocket`, `book-open`, `chevron-right`).
145
133
  <Icon icon="rocket" size={20} />
146
134
  ```
147
135
 
148
- `icon` is the icon name; `size` sets the pixel size (default `16`) and `color`
149
- tints it (any CSS color; defaults to `currentColor`). Pass a raw `<svg>` string,
150
- an image URL, or a local image path in place of a name to render your own art,
151
- and add a `label` to expose it to assistive tech without one, the icon is
152
- decorative.
136
+ A bare name resolves against your project's [`icons.library`](#default-library) (Lucide unless you change it). Two ways to reach another library for a single icon:
137
+
138
+ - **`iconType`** selects a Font Awesome style — `solid` (default), `regular`, or `brands`: `<Icon icon="github" iconType="brands" />`. Font Awesome Pro styles (`light`, `thin`, `duotone`, `sharp-solid`) aren't in the bundled free data and fall back to solid.
139
+ - **A `library:name` prefix** overrides the default per icon: `fa6-solid:gauge-high`, `fa6-brands:github`, `lucide:rocket`, `tabler:heart`.
140
+
141
+ `size` sets the pixel size (default `16`) and `color` tints it (any CSS color; defaults to `currentColor`). Pass a raw `<svg>` string, an image URL, or a local image path in place of a name to render your own art, and add a `label` to expose it to assistive tech — without one, the icon is decorative.
142
+
143
+ Icons resolve at build time and inline as zero-JS SVG — nothing is fetched at runtime.
144
+
145
+ ### Default library
146
+
147
+ Set which library bare icon names resolve against:
148
+
149
+ ```ts title="blume.config.ts"
150
+ export default defineConfig({
151
+ icons: { library: "fontawesome" }, // "lucide" (default) | "fontawesome" | "tabler"
152
+ });
153
+ ```
154
+
155
+ A `library:name` prefix always wins over this, so you can mix libraries on any default. Migrating from Mintlify sets this to `fontawesome` for you (Mintlify's default), so your existing icon names keep working.
153
156
 
154
157
  ## File tree
155
158
 
156
- Illustrate a project or folder layout. Wrap a normal Markdown list and Blume
157
- styles it as a tree — handy for explaining structure in setup and config guides.
159
+ Illustrate a project or folder layout. Wrap a normal Markdown list and Blume styles it as a tree — handy for explaining structure in setup and config guides.
158
160
 
159
161
  <FileTree>
160
162
 
@@ -180,10 +182,7 @@ styles it as a tree — handy for explaining structure in setup and config guide
180
182
 
181
183
  ## Accordion
182
184
 
183
- Stack related collapsibles in a single bordered container with dividers between
184
- them — FAQs, optional steps, or long examples. Each child is an `AccordionItem`
185
- (`title`, optional `icon`, `description`, `defaultOpen`). For a single standalone
186
- disclosure, use [Expandable](#expandable).
185
+ Stack related collapsibles in a single bordered container with dividers between them — FAQs, optional steps, or long examples. Each child is an `AccordionItem` (`title`, optional `icon`, `description`, `defaultOpen`). For a single standalone disclosure, use [Expandable](#expandable).
187
186
 
188
187
  <Accordion>
189
188
  <AccordionItem title="Does it support MDX?">
@@ -207,9 +206,7 @@ disclosure, use [Expandable](#expandable).
207
206
 
208
207
  ## Expandable
209
208
 
210
- A lightweight inline disclosure for nested detail — expanding a field's
211
- sub-properties or an optional aside. `title` labels the toggle (defaults to
212
- “Show more”); set `defaultOpen` to start expanded.
209
+ A lightweight inline disclosure for nested detail — expanding a field's sub-properties or an optional aside. `title` labels the toggle (defaults to “Show more”); set `defaultOpen` to start expanded.
213
210
 
214
211
  <Expandable title="Show advanced options">
215
212
  These settings are optional and rarely need changing.
@@ -223,8 +220,7 @@ sub-properties or an optional aside. `title` labels the toggle (defaults to
223
220
 
224
221
  ## Columns
225
222
 
226
- Lay cards or blocks out in a responsive grid of equal columns that reflows on
227
- mobile. `Columns` takes `cols`; wrap each cell in a `Column`.
223
+ Lay cards or blocks out in a responsive grid of equal columns that reflows on mobile. `Columns` takes `cols`; wrap each cell in a `Column`.
228
224
 
229
225
  <Columns cols={2}>
230
226
  <Column>
@@ -256,9 +252,7 @@ mobile. `Columns` takes `cols`; wrap each cell in a `Column`.
256
252
 
257
253
  ## CodeGroup
258
254
 
259
- Group several code blocks into one tabbed switcher — a tab per language or file.
260
- The tab label is each block's title (the text after the language). Add `dropdown`
261
- to switch with a menu instead of a tab bar.
255
+ Group several code blocks into one tabbed switcher — a tab per language or file. The tab label is each block's title (the text after the language). Add `dropdown` to switch with a menu instead of a tab bar.
262
256
 
263
257
  <CodeGroup>
264
258
 
@@ -302,8 +296,7 @@ fn greet(name: &str) -> String {
302
296
 
303
297
  ## Frame
304
298
 
305
- Wrap an image or any visual in a centered, bordered frame with an optional
306
- `caption` (rendered as Markdown) and `hint`.
299
+ Wrap an image or any visual in a centered, bordered frame with an optional `caption` (rendered as Markdown) and `hint`.
307
300
 
308
301
  <Frame
309
302
  caption="A **framed** illustration."
@@ -329,12 +322,20 @@ Wrap an image or any visual in a centered, bordered frame with an optional
329
322
  </Frame>
330
323
  ```
331
324
 
325
+ ## YouTube
326
+
327
+ Embed a YouTube video in a responsive, privacy-friendly (`youtube-nocookie.com`) 16:9 frame that ships no client JavaScript. Pass a video `id` or a full `url`, plus an optional `title` (for accessibility) and a `start` time in seconds.
328
+
329
+ <YouTube id="aqz-KE-bpKQ" title="Big Buck Bunny" />
330
+
331
+ ```astro lineNumbers
332
+ <YouTube id="aqz-KE-bpKQ" title="Big Buck Bunny" />
333
+ <YouTube url="https://youtu.be/aqz-KE-bpKQ" start={30} />
334
+ ```
335
+
332
336
  ## Color
333
337
 
334
- Show color swatches with copyable hex values — useful for documenting a palette
335
- or brand colors. Use `variant="compact"` for a swatch list, or `variant="table"`
336
- with `Color.Row` to group them. Each `Color.Item` takes a `name` and a `value`
337
- (a hex string, or `{ light, dark }` for theme-aware colors).
338
+ Show color swatches with copyable hex values — useful for documenting a palette or brand colors. Use `variant="compact"` for a swatch list, or `variant="table"` with `Color.Row` to group them. Each `Color.Item` takes a `name` and a `value` (a hex string, or `{ light, dark }` for theme-aware colors).
338
339
 
339
340
  <Color variant="compact">
340
341
  <Color.Item name="blue-500" value="#3B82F6" />
@@ -352,10 +353,7 @@ with `Color.Row` to group them. Each `Color.Item` takes a `name` and a `value`
352
353
 
353
354
  ## Tree
354
355
 
355
- Render a hierarchical file/folder structure with expandable folders. (For a
356
- quick, list-driven version see [File tree](#file-tree); `Tree` gives per-folder
357
- control.) Use `Tree.Folder` (`name`, optional `defaultOpen`, `openable`) and
358
- `Tree.File` (`name`).
356
+ Render a hierarchical file/folder structure with expandable folders. (For a quick, list-driven version see [File tree](#file-tree); `Tree` gives per-folder control.) Use `Tree.Folder` (`name`, optional `defaultOpen`, `openable`) and `Tree.File` (`name`).
359
357
 
360
358
  <Tree>
361
359
  <Tree.Folder name="src" defaultOpen>
@@ -395,8 +393,7 @@ A titled container for supplementary, set-aside content. `title` is optional.
395
393
 
396
394
  ## Tooltip
397
395
 
398
- Reveal a definition or hint on hover for an inline term. `tip` is the hover text;
399
- add an optional `headline` and a `cta` + `href` for a follow-up link.
396
+ Reveal a definition or hint on hover for an inline term. `tip` is the hover text; add an optional `headline` and a `cta` + `href` for a follow-up link.
400
397
 
401
398
  Hover the <Tooltip tip="A set of protocols software uses to communicate." headline="API" cta="Read the guide" href="/docs/quickstart">API</Tooltip> term to learn more.
402
399
 
@@ -406,9 +403,7 @@ Hover the <Tooltip tip="A set of protocols software uses to communicate." headli
406
403
 
407
404
  ## Tile
408
405
 
409
- A clickable preview that leads with a visual — an icon or image — above a title
410
- and description. Good for galleries and showcases. Takes `title`, `description`,
411
- and `href`; the child is the visual.
406
+ A clickable preview that leads with a visual — an icon or image — above a title and description. Good for galleries and showcases. Takes `title`, `description`, and `href`; the child is the visual.
412
407
 
413
408
  <Tile
414
409
  title="Quickstart"
@@ -430,10 +425,7 @@ and `href`; the child is the visual.
430
425
 
431
426
  ## Prompt
432
427
 
433
- A single row with a label and a copy button. The `description` (Markdown) is the
434
- visible label; the body is the prompt itself — hidden, and copied to the
435
- clipboard when the **Copy prompt** button is pressed. `actions` controls the
436
- buttons (e.g. `["copy", "cursor"]`).
428
+ A single row with a label and a copy button. The `description` (Markdown) is the visible label; the body is the prompt itself — hidden, and copied to the clipboard when the **Copy prompt** button is pressed. `actions` controls the buttons (e.g. `["copy", "cursor"]`).
437
429
 
438
430
  <Prompt
439
431
  description="Ask the model to **document** an endpoint."
@@ -453,8 +445,7 @@ buttons (e.g. `["copy", "cursor"]`).
453
445
 
454
446
  ## Visibility
455
447
 
456
- Show or hide content by audience. `for="web"` renders only on the site;
457
- `for="agents"` targets the generated Markdown (`llms.txt`) that AI agents read.
448
+ Show or hide content by audience. `for="web"` renders only on the site; `for="agents"` targets the generated Markdown (`llms.txt`) that AI agents read.
458
449
 
459
450
  <Visibility for="web">
460
451
  This note appears on the website but is omitted from the agent-facing
@@ -466,19 +457,47 @@ Show or hide content by audience. `for="web"` renders only on the site;
466
457
  <Visibility for="agents">Shown only in the generated Markdown.</Visibility>
467
458
  ```
468
459
 
460
+ ## API fields
461
+
462
+ Document a single request/response field — a CLI flag, an SDK argument, an endpoint parameter — with its name, type, and description. `ParamField`, `ResponseField`, and `RequestField` are Mintlify-compatible, so a migrated site's field markup renders unchanged. Each takes a `type`, plus `required`, `deprecated`, and `default`; the description is the element's body and may hold rich MDX, including a nested [Expandable](#expandable) for sub-properties.
463
+
464
+ `ParamField` names the field through the attribute that marks its location — `path`, `query`, `header`, or `body` (or a plain `name`); the location shows as a small label.
465
+
466
+ <ParamField path="userId" type="string" required>
467
+ The unique identifier of the user.
468
+ </ParamField>
469
+
470
+ <ParamField query="limit" type="integer" default="20">
471
+ Maximum number of results to return per page.
472
+ </ParamField>
473
+
474
+ <ResponseField name="createdAt" type="string">
475
+ ISO 8601 timestamp for when the record was created.
476
+ </ResponseField>
477
+
478
+ ```mdx
479
+ <ParamField path="userId" type="string" required>
480
+ The unique identifier of the user.
481
+ </ParamField>
482
+
483
+ <ParamField query="limit" type="integer" default="20">
484
+ Maximum number of results to return per page.
485
+ </ParamField>
486
+
487
+ <ResponseField name="createdAt" type="string">
488
+ ISO 8601 timestamp for when the record was created.
489
+ </ResponseField>
490
+ ```
491
+
492
+ For a full spec-driven API reference — one page per operation with generated schemas — use the [OpenAPI reference](/docs/advanced/api-reference) instead.
493
+
469
494
  ## Type tables
470
495
 
471
- Tables for documenting an object's properties — its props, types, and defaults.
472
- Write the rows by hand with `TypeTable`, or generate them straight from a
473
- TypeScript interface or type alias with `AutoTypeTable`.
496
+ Tables for documenting an object's properties — its props, types, and defaults. Write the rows by hand with `TypeTable`, or generate them straight from a TypeScript interface or type alias with `AutoTypeTable`.
474
497
 
475
498
  ### Type table
476
499
 
477
- A **Prop / Type** grid where each row expands to reveal its description and
478
- details. Pass a `type` map keyed by property name; each entry takes a `type`,
479
- plus an optional `description`, `default`, `required` flag, `typeDescription`,
480
- and `typeDescriptionLink`. Optional props (`required` unset) show a `?` after the
481
- name.
500
+ A **Prop / Type** grid where each row expands to reveal its description and details. Pass a `type` map keyed by property name; each entry takes a `type`, plus an optional `description`, `default`, `required` flag, `typeDescription`, and `typeDescriptionLink`. Optional props (`required` unset) show a `?` after the name.
482
501
 
483
502
  <TypeTable
484
503
  type={{
@@ -516,17 +535,13 @@ name.
516
535
 
517
536
  ### Auto type table
518
537
 
519
- Generate a type table from a TypeScript type so the docs stay in sync with the
520
- source. Point `AutoTypeTable` at a file with `path` (resolved from your project
521
- root) and a type `name`. Descriptions come from JSDoc comments, defaults from
522
- `@default` tags, and optional properties (`?`) are marked accordingly.
538
+ Generate a type table from a TypeScript type so the docs stay in sync with the source. Point `AutoTypeTable` at a file with `path` (resolved from your project root) and a type `name`. Descriptions come from JSDoc comments, defaults from `@default` tags, and optional properties (`?`) are marked accordingly.
523
539
 
524
540
  ```astro
525
541
  <AutoTypeTable path="./src/button.ts" name="ButtonProps" />
526
542
  ```
527
543
 
528
- You can also pass the type inline with `type` instead of a `path` — handy for
529
- small examples:
544
+ You can also pass the type inline with `type` instead of a `path` — handy for small examples:
530
545
 
531
546
  <AutoTypeTable
532
547
  name="ButtonProps"
@@ -566,11 +581,7 @@ export interface ButtonProps {
566
581
 
567
582
  ## GitHub info
568
583
 
569
- A card linking to a GitHub repository with its live star and fork counts.
570
- Counts are fetched at build time — no client JavaScript — and the card still
571
- renders if the API is unreachable. Pass `owner` and `repo`, or omit them to use
572
- the repository from your `blume.config`. Set a `GITHUB_TOKEN` environment
573
- variable to lift the API rate limit.
584
+ A card linking to a GitHub repository with its live star and fork counts. Counts are fetched at build time — no client JavaScript — and the card still renders if the API is unreachable. Pass `owner` and `repo`, or omit them to use the repository from your `blume.config`. Set a `GITHUB_TOKEN` environment variable to lift the API rate limit.
574
585
 
575
586
  <GithubInfo owner="withastro" repo="astro" />
576
587
 
@@ -584,16 +595,9 @@ variable to lift the API rate limit.
584
595
 
585
596
  ## Component
586
597
 
587
- `Component` renders an example file from your project's `examples/` directory as
588
- a live preview alongside its highlighted source, in tabs. Point it at a file with
589
- `path` — its location under `examples/`, without the extension (so
590
- `examples/counter.tsx` is `path="counter"`). React, Vue, Svelte, and Astro
591
- examples are all supported; framework examples hydrate, Astro ones render
592
- statically. It keeps the preview and the code in sync from a single file.
598
+ `Component` renders an example file from your project's `examples/` directory as a live preview alongside its highlighted source, in tabs. Point it at a file with `path` — its location under `examples/`, without the extension (so `examples/counter.tsx` is `path="counter"`). React, Vue, Svelte, and Astro examples are all supported; framework examples hydrate, Astro ones render statically. It keeps the preview and the code in sync from a single file.
593
599
 
594
- The directory is configurable — set `examples` in `blume.config.ts` when your
595
- examples live elsewhere (e.g. a registry layout). `path` is always relative to
596
- it:
600
+ The directory is configurable — set `examples` in `blume.config.ts` when your examples live elsewhere (e.g. a registry layout). `path` is always relative to it:
597
601
 
598
602
  ```ts
599
603
  // blume.config.ts
@@ -607,11 +611,7 @@ export default defineConfig({
607
611
  <Component path="file-list/basic" />
608
612
  ```
609
613
 
610
- `examples` can also be a glob (anything with `*`, `?`, `[]`, `{}`, or `!`). Only
611
- matching files are discovered, and `path` is relative to the glob's static prefix
612
- (the part before the first wildcard). This is for a registry that colocates each
613
- component's source with its example — point at just the examples so the sources,
614
- which have no default export to preview, aren't swept in:
614
+ `examples` can also be a glob (anything with `*`, `?`, `[]`, `{}`, or `!`). Only matching files are discovered, and `path` is relative to the glob's static prefix (the part before the first wildcard). This is for a registry that colocates each component's source with its example — point at just the examples so the sources, which have no default export to preview, aren't swept in:
615
615
 
616
616
  ```ts
617
617
  // blume.config.ts
@@ -640,9 +640,7 @@ An Astro example renders live with no client JavaScript:
640
640
 
641
641
  ## CodeBlock
642
642
 
643
- `CodeBlock` highlights a code string with the same Shiki theme and transformers
644
- as your fenced code — including the light/dark swap — for places a fence can't
645
- go, like a landing page or a custom component. Pass `code` and a `lang`:
643
+ `CodeBlock` highlights a code string with the same Shiki theme and transformers as your fenced code — including the light/dark swap — for places a fence can't go, like a landing page or a custom component. Pass `code` and a `lang`:
646
644
 
647
645
  <CodeBlock
648
646
  lang="ts"
@@ -658,8 +656,7 @@ import CodeBlock from "blume/components/content/CodeBlock.astro";
658
656
  <CodeBlock lang="ts" code={source} />
659
657
  ```
660
658
 
661
- To highlight to an HTML string yourself (e.g. inside your own component), import
662
- the underlying helper from `blume/markdown`:
659
+ To highlight to an HTML string yourself (e.g. inside your own component), import the underlying helper from `blume/markdown`:
663
660
 
664
661
  ```ts
665
662
  import { highlightCode } from "blume/markdown";
@@ -669,10 +666,7 @@ const html = await highlightCode(source, "ts");
669
666
 
670
667
  ## Diff
671
668
 
672
- `Diff` renders a git-style diff, highlighted with the same Shiki theme as your
673
- code blocks and produced entirely at build time — no client JavaScript. Give it
674
- two inline strings (`old` / `new`), two file paths (`before` / `after`), or a
675
- unified patch (an inline `patch` string or a `src` file).
669
+ `Diff` renders a git-style diff, highlighted with the same Shiki theme as your code blocks and produced entirely at build time — no client JavaScript. Give it two inline strings (`old` / `new`), two file paths (`before` / `after`), or a unified patch (an inline `patch` string or a `src` file).
676
670
 
677
671
  <Diff
678
672
  lang="ts"
@@ -3,10 +3,7 @@ title: Internationalization
3
3
  description: Serve your docs in multiple languages with locale-aware routing, per-language navigation, translated UI, and SEO — all convention-first.
4
4
  ---
5
5
 
6
- Blume serves one project in many languages. Drop translated files into the right
7
- place and Blume wires up routing, the language switcher, per-locale navigation,
8
- and SEO for you — there's no separate routing layer to maintain. It's opt-in:
9
- without an `i18n` block, your site stays single-language exactly as before.
6
+ Blume serves one project in many languages. Drop translated files into the right place and Blume wires up routing, the language switcher, per-locale navigation, and SEO for you — there's no separate routing layer to maintain. It's opt-in: without an `i18n` block, your site stays single-language exactly as before.
10
7
 
11
8
  ## Enable it
12
9
 
@@ -23,20 +20,13 @@ i18n: {
23
20
  }
24
21
  ```
25
22
 
26
- Each locale has a `code` (used in URLs), a `label` (shown in the language
27
- switcher), and an optional `dir` for right-to-left scripts (`"ltr"` by default).
23
+ Each locale has a `code` (used in URLs), a `label` (shown in the language switcher), and an optional `dir` for right-to-left scripts (`"ltr"` by default).
28
24
 
29
- :::tip
30
- Migrating from Mintlify? `blume migrate mintlify` reads
31
- `navigation.languages[]` and writes the `i18n` block for you — the `default: true`
32
- language becomes `defaultLocale`, and translated folders already match Blume's
33
- layout.
34
- :::
25
+ :::tip Migrating from Mintlify? [`blume migrate mintlify`](/docs/advanced/migrate) reads `navigation.languages[]` and writes the `i18n` block for you — the `default: true` language becomes `defaultLocale`, and translated folders already match Blume's layout. :::
35
26
 
36
27
  ## Organize translated content
37
28
 
38
- The default locale lives at your content root. Every other locale is a top-level
39
- folder named by its `code`, mirroring the default structure:
29
+ The default locale lives at your content root. Every other locale is a top-level folder named by its `code`, mirroring the default structure:
40
30
 
41
31
  ```txt
42
32
  docs/
@@ -55,13 +45,11 @@ docs/
55
45
  | `docs/guides/quickstart.mdx` | `/guides/quickstart` |
56
46
  | `docs/fr/guides/quickstart.mdx` | `/fr/guides/quickstart` |
57
47
 
58
- You only translate the files you want — everything else falls back automatically
59
- (see [Fallbacks](#fallbacks)).
48
+ You only translate the files you want — everything else falls back automatically (see [Fallbacks](#fallbacks)).
60
49
 
61
50
  ### Filename suffixes
62
51
 
63
- Prefer to keep translations next to the original? Set `parser: "dot"` and name
64
- files with a locale suffix instead of using folders:
52
+ Prefer to keep translations next to the original? Set `parser: "dot"` and name files with a locale suffix instead of using folders:
65
53
 
66
54
  ```txt
67
55
  docs/
@@ -69,13 +57,11 @@ docs/
69
57
  guides/quickstart.fr.mdx -> /fr/guides/quickstart (French)
70
58
  ```
71
59
 
72
- Good for sparse translations — colocate the few pages you've translated without
73
- mirroring the whole tree.
60
+ Good for sparse translations — colocate the few pages you've translated without mirroring the whole tree.
74
61
 
75
62
  ### Shared files
76
63
 
77
- For content that's the same in every language — a changelog, a status page — add
78
- a `$` marker so one file serves all locales without duplication:
64
+ For content that's the same in every language — a changelog, a status page — add a `$` marker so one file serves all locales without duplication:
79
65
 
80
66
  ```txt
81
67
  docs/changelog.$.mdx -> /changelog and /fr/changelog (same content)
@@ -86,9 +72,7 @@ A locale-specific `meta.ts` still overrides the shared one for that language.
86
72
 
87
73
  ## Default-locale URLs
88
74
 
89
- By default the default locale has no URL prefix (`/`, `/guides/quickstart`) while
90
- other locales are prefixed (`/fr/…`). This keeps your primary language's URLs
91
- clean. To prefix every locale, including the default:
75
+ By default the default locale has no URL prefix (`/`, `/guides/quickstart`) while other locales are prefixed (`/fr/…`). This keeps your primary language's URLs clean. To prefix every locale, including the default:
92
76
 
93
77
  ```ts blume.config.ts lineNumbers
94
78
  i18n: {
@@ -99,17 +83,11 @@ i18n: {
99
83
 
100
84
  ## Per-locale navigation
101
85
 
102
- Each language gets its own sidebar, built from that locale's files — so
103
- translations can diverge in structure, ordering, or labels. Folder
104
- [`meta.ts`](/docs/content/meta) files resolve per locale, too: put a `meta.ts`
105
- under `fr/guides/` to order the French group independently. Everything else about
106
- [navigation](/docs/content/navigation) works the same, per language.
86
+ Each language gets its own sidebar, built from that locale's files — so translations can diverge in structure, ordering, or labels. Folder [`meta.ts`](/docs/content/meta) files resolve per locale, too: put a `meta.ts` under `fr/guides/` to order the French group independently. Everything else about [navigation](/docs/content/navigation) works the same, per language.
107
87
 
108
88
  ## Fallbacks
109
89
 
110
- When a page isn't translated yet, Blume renders the fallback locale's content at
111
- the localized URL — so the link works, the page is fully pre-rendered, and search
112
- engines aren't sent to a dead end. The fallback defaults to your `defaultLocale`:
90
+ When a page isn't translated yet, Blume renders the fallback locale's content at the localized URL — so the link works, the page is fully pre-rendered, and search engines aren't sent to a dead end. The fallback defaults to your `defaultLocale`:
113
91
 
114
92
  ```ts blume.config.ts lineNumbers
115
93
  i18n: {
@@ -118,40 +96,21 @@ i18n: {
118
96
  }
119
97
  ```
120
98
 
121
- Fallback pages are excluded from the search index and aren't advertised as real
122
- translations in `hreflang`, so untranslated content doesn't compete for ranking.
123
- They still appear in that locale's sidebar, so navigation stays complete — a
124
- reader can reach every page in any language.
99
+ Fallback pages are excluded from the search index and aren't advertised as real translations in `hreflang`, so untranslated content doesn't compete for ranking. They still appear in that locale's sidebar, so navigation stays complete — a reader can reach every page in any language.
125
100
 
126
- :::tip
127
- Start by translating your most important pages — the homepage, quickstart, and
128
- top guides — and let the rest fall back. You can fill in translations over time
129
- without breaking any links.
130
- :::
101
+ :::tip Start by translating your most important pages — the homepage, quickstart, and top guides — and let the rest fall back. You can fill in translations over time without breaking any links. :::
131
102
 
132
103
  ## The language switcher
133
104
 
134
- When i18n is on, a language switcher appears in the header automatically,
135
- generated from your `locales`. For each page it links the matching translation in
136
- every language; where a translation is missing it links the fallback page and
137
- marks it as not translated. There's nothing to configure.
105
+ When i18n is on, a language switcher appears in the header automatically, generated from your `locales`. For each page it links the matching translation in every language; where a translation is missing it links the fallback page and marks it as not translated. There's nothing to configure.
138
106
 
139
107
  ## Translated UI
140
108
 
141
- Blume ships built-in translations for its own interface chrome — “On this page”,
142
- “Search”, “Edit on GitHub”, and the rest — so a locale with a built-in pack gets
143
- translated UI out of the box. **You only translate your content.**
109
+ Blume ships built-in translations for its own interface chrome — “On this page”, “Search”, “Edit on GitHub”, and the rest — so a locale with a built-in pack gets translated UI out of the box. **You only translate your content.**
144
110
 
145
- Packs ship for 36 languages — Arabic, Bengali, Bulgarian, Catalan, Chinese
146
- (Simplified and Traditional), Croatian, Czech, Danish, Dutch, Finnish, French,
147
- German, Greek, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean,
148
- Norwegian, Persian, Polish, Portuguese (and Brazilian Portuguese), Romanian,
149
- Russian, Serbian, Slovak, Spanish, Swedish, Thai, Turkish, Ukrainian, and
150
- Vietnamese. They're community-maintained — open a PR to add a locale or sharpen a
151
- translation.
111
+ Packs ship for 36 languages — Arabic, Bengali, Bulgarian, Catalan, Chinese (Simplified and Traditional), Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Norwegian, Persian, Polish, Portuguese (and Brazilian Portuguese), Romanian, Russian, Serbian, Slovak, Spanish, Swedish, Thai, Turkish, Ukrainian, and Vietnamese. They're community-maintained — open a PR to add a locale or sharpen a translation.
152
112
 
153
- Missing or unshipped strings fall back to the default locale, then to English.
154
- To override a string or supply your own language, set `i18n.ui`, keyed by locale:
113
+ Missing or unshipped strings fall back to the default locale, then to English. To override a string or supply your own language, set `i18n.ui`, keyed by locale:
155
114
 
156
115
  ```ts blume.config.ts lineNumbers
157
116
  i18n: {
@@ -170,28 +129,18 @@ i18n: {
170
129
  Localized SEO is handled for you — no per-page metadata to write:
171
130
 
172
131
  - `<html lang>` and `dir` are set from the active locale.
173
- - `hreflang` alternates link every real translation of a page, plus an
174
- `x-default` pointing at the default locale.
132
+ - `hreflang` alternates link every real translation of a page, plus an `x-default` pointing at the default locale.
175
133
  - Canonical URLs are locale-correct, and JSON-LD carries `inLanguage`.
176
134
 
177
- Set [`deployment.site`](/docs/deployment) so these can be emitted as absolute
178
- URLs.
135
+ Set [`deployment.site`](/docs/deployment) so these can be emitted as absolute URLs.
179
136
 
180
137
  ## Search
181
138
 
182
- Search is scoped to the active language: on a `/fr/…` page the dialog returns
183
- French results, with an **All languages** toggle to search across every locale at
184
- once. The default (Orama) and FlexSearch indexes filter in the browser; hosted
185
- providers carry a `locale` facet on each record.
139
+ Search is scoped to the active language: on a `/fr/…` page the dialog returns French results, with an **All languages** toggle to search across every locale at once. The default (Orama) and FlexSearch indexes filter in the browser; hosted providers carry a `locale` facet on each record.
186
140
 
187
141
  ## Right-to-left
188
142
 
189
- Set `dir: "rtl"` on a locale and Blume mirrors the whole interface — the sidebar,
190
- header, table of contents, pagination, search, and menus — and sets `<html dir>`
191
- to match. Two things deliberately stay left-to-right: **code blocks** (code reads
192
- LTR in any language) and **fallback content** — an untranslated page keeps the
193
- direction of the language it's actually written in, so English shown under an RTL
194
- locale still reads correctly while the surrounding chrome mirrors.
143
+ Set `dir: "rtl"` on a locale and Blume mirrors the whole interface — the sidebar, header, table of contents, pagination, search, and menus — and sets `<html dir>` to match. Two things deliberately stay left-to-right: **code blocks** (code reads LTR in any language) and **fallback content** — an untranslated page keeps the direction of the language it's actually written in, so English shown under an RTL locale still reads correctly while the surrounding chrome mirrors.
195
144
 
196
145
  ## Where to next
197
146