blume 0.2.0 → 0.4.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 (119) hide show
  1. package/dist/cli/index.js +2429 -792
  2. package/dist/cli/index.js.map +63 -44
  3. package/dist/types/core/data.d.ts +16 -0
  4. package/dist/types/core/define-components.d.ts +9 -2
  5. package/dist/types/core/diagnostics.d.ts +5 -0
  6. package/dist/types/core/schema.d.ts +313 -778
  7. package/dist/types/core/types.d.ts +2 -2
  8. package/dist/types/migrate/mintlify/assets.d.ts +8 -0
  9. package/docs/01-quickstart.mdx +5 -16
  10. package/docs/02-deployment.mdx +26 -40
  11. package/docs/advanced/api-reference.mdx +10 -37
  12. package/docs/advanced/blog.mdx +9 -25
  13. package/docs/advanced/changelog.mdx +10 -33
  14. package/docs/advanced/custom-pages.mdx +66 -61
  15. package/docs/configuration/ai.mdx +47 -91
  16. package/docs/configuration/analytics.mdx +20 -38
  17. package/docs/configuration/customization.mdx +92 -27
  18. package/docs/configuration/export.mdx +9 -34
  19. package/docs/configuration/index.mdx +78 -85
  20. package/docs/configuration/search.mdx +17 -54
  21. package/docs/configuration/seo.mdx +18 -44
  22. package/docs/configuration/theming.mdx +20 -42
  23. package/docs/content/components.mdx +42 -101
  24. package/docs/content/i18n.mdx +21 -72
  25. package/docs/content/index.mdx +18 -48
  26. package/docs/content/islands.mdx +79 -33
  27. package/docs/content/meta.mdx +23 -50
  28. package/docs/content/navigation.mdx +42 -56
  29. package/docs/content/sources.mdx +20 -83
  30. package/docs/content/syntax.mdx +37 -105
  31. package/docs/index.mdx +13 -51
  32. package/docs/reference/cli.mdx +49 -18
  33. package/docs/reference/frontmatter.mdx +2 -5
  34. package/package.json +3 -1
  35. package/src/ai/ask-context.ts +131 -0
  36. package/src/ai/ask-data.ts +25 -0
  37. package/src/astro/component-slots.ts +165 -0
  38. package/src/astro/generate.ts +132 -13
  39. package/src/astro/integration.ts +85 -3
  40. package/src/astro/islands.ts +6 -2
  41. package/src/astro/markdown-negotiation.ts +17 -3
  42. package/src/astro/pages.ts +11 -13
  43. package/src/astro/static-assets.ts +117 -0
  44. package/src/astro/templates.ts +120 -50
  45. package/src/blume-modules.d.ts +25 -0
  46. package/src/cli/args.ts +23 -0
  47. package/src/cli/commands/build.ts +209 -1
  48. package/src/cli/commands/check.ts +62 -0
  49. package/src/cli/commands/dev.ts +32 -3
  50. package/src/cli/commands/doctor.ts +32 -6
  51. package/src/cli/commands/eject.ts +3 -1
  52. package/src/cli/commands/init.ts +184 -16
  53. package/src/cli/commands/preview.ts +2 -1
  54. package/src/cli/commands/validate.ts +27 -2
  55. package/src/cli/dev-lock.ts +84 -0
  56. package/src/cli/index.ts +15 -0
  57. package/src/cli/internal-error.ts +63 -0
  58. package/src/cli/log.ts +41 -1
  59. package/src/cli/prepare.ts +17 -3
  60. package/src/cli/required-secrets.ts +44 -0
  61. package/src/components/BlumePage.astro +109 -0
  62. package/src/components/content/YouTube.astro +35 -0
  63. package/src/components/content/youtube.ts +46 -0
  64. package/src/components/index.ts +3 -3
  65. package/src/components/islands/ask-ai.tsx +29 -15
  66. package/src/components/islands/hooks.ts +188 -0
  67. package/src/components/layout/Empty.astro +6 -0
  68. package/src/components/layout/Header.astro +24 -39
  69. package/src/components/layout/Logo.astro +50 -0
  70. package/src/components/layout/NavSelector.astro +75 -0
  71. package/src/components/layout/PageLayout.astro +38 -2
  72. package/src/components/layout/RootLayout.astro +70 -4
  73. package/src/components/layout/hydration-hint.ts +30 -0
  74. package/src/components/layout/overrides.ts +6 -4
  75. package/src/components/props.ts +71 -0
  76. package/src/core/assets.ts +31 -0
  77. package/src/core/bridge.ts +10 -0
  78. package/src/core/builtin-tags.ts +40 -0
  79. package/src/core/component-diagnostics.ts +44 -0
  80. package/src/core/component-overrides.ts +478 -0
  81. package/src/core/config.ts +8 -0
  82. package/src/core/data.ts +14 -0
  83. package/src/core/define-components.ts +9 -2
  84. package/src/core/diagnostics.ts +95 -1
  85. package/src/core/gitignore.ts +30 -0
  86. package/src/core/graph.ts +7 -0
  87. package/src/core/links.ts +60 -19
  88. package/src/core/nav-diagnostics.ts +205 -0
  89. package/src/core/project-graph.ts +40 -1
  90. package/src/core/schema.ts +35 -96
  91. package/src/core/sources/mdx-remote.ts +54 -8
  92. package/src/core/sources/normalize.ts +57 -1
  93. package/src/core/sources/notion.ts +49 -5
  94. package/src/core/sources/sanity.ts +5 -1
  95. package/src/core/types.ts +2 -2
  96. package/src/deploy/redirects.ts +43 -0
  97. package/src/deploy/rss.ts +1 -8
  98. package/src/deploy/sitemap.ts +20 -1
  99. package/src/deploy/xml.ts +8 -0
  100. package/src/markdown/directives.ts +15 -7
  101. package/src/markdown/package-commands.ts +26 -4
  102. package/src/migrate/fumadocs/content.ts +14 -1
  103. package/src/migrate/fumadocs/groups.ts +7 -0
  104. package/src/migrate/fumadocs/index.ts +5 -2
  105. package/src/migrate/mintlify/assets.ts +46 -0
  106. package/src/migrate/mintlify/config.ts +1 -176
  107. package/src/migrate/mintlify/index.ts +53 -45
  108. package/src/migrate/shared.ts +12 -27
  109. package/src/migrate/starlight/config.ts +0 -4
  110. package/src/og/card.ts +175 -38
  111. package/src/registry/eject.ts +52 -12
  112. package/src/registry/registry.ts +172 -0
  113. package/src/registry/rewrite-imports.ts +31 -19
  114. package/src/runtime/index.ts +61 -0
  115. package/src/search/documents.ts +23 -5
  116. package/src/search/sync/algolia.ts +5 -1
  117. package/src/search/sync/typesense.ts +24 -16
  118. package/src/theme/palette.ts +26 -7
  119. package/src/vite-env.d.ts +14 -0
@@ -108,6 +108,8 @@ export interface PageRecord {
108
108
  format: "md" | "mdx";
109
109
  /** Internal/asset links discovered in the page (for validation). */
110
110
  links: PageLink[];
111
+ /** Capitalized JSX component tags used in the body (`.mdx` only). */
112
+ componentsUsed?: string[];
111
113
  /** Resolved "last updated" ISO date, when the feature is enabled. */
112
114
  lastModified?: string;
113
115
  }
@@ -168,8 +170,6 @@ export interface NavSidebarVariant {
168
170
  export interface NavChromeVariant {
169
171
  path: string;
170
172
  banner?: ResolvedConfig["banner"];
171
- footer?: ResolvedConfig["footer"];
172
- navbar?: ResolvedConfig["navbar"];
173
173
  }
174
174
  /** The complete navigation model derived from the content graph. */
175
175
  export interface Navigation {
@@ -0,0 +1,8 @@
1
+ import type { BlumeConfig } from "../../core/schema.ts";
2
+ /**
3
+ * Top-level path segments referenced as static assets by a Mintlify config
4
+ * (the conventional `/images`, plus logo/favicon/background paths). These are
5
+ * the root-served folders Mintlify exposes at the site root; Blume serves them
6
+ * via `content.assets` (bridge) or relocates them under `public/` (migrator).
7
+ */
8
+ export declare const assetSegments: (config: BlumeConfig) => string[];
@@ -6,9 +6,7 @@ sidebar:
6
6
  order: 1
7
7
  ---
8
8
 
9
- Go from an empty folder to a running docs site in a few commands. Blume needs
10
- **Node.js 22 or newer** and a `docs/` folder with at least one `.md` or `.mdx`
11
- file — there's nothing else to set up.
9
+ Go from an empty folder to a running docs site in a few commands. Blume needs **Node.js 22 or newer** and a `docs/` folder with at least one `.md` or `.mdx` file — there's nothing else to set up.
12
10
 
13
11
  ## Install and run
14
12
 
@@ -53,16 +51,11 @@ file — there's nothing else to set up.
53
51
  </Step>
54
52
  </Steps>
55
53
 
56
- :::tip
57
- Blume works with any package manager and never requires you to set up Astro or
58
- Tailwind yourself.
59
- :::
54
+ :::tip Blume works with any package manager and never requires you to set up Astro or Tailwind yourself. :::
60
55
 
61
56
  ## Write your first page
62
57
 
63
- Every page is Markdown or MDX with a little frontmatter — the `title` and
64
- `description` render as the page heading and intro automatically. Drop this into
65
- `docs/index.mdx`:
58
+ Every page is Markdown or MDX with a little frontmatter — the `title` and `description` render as the page heading and intro automatically. Drop this into `docs/index.mdx`:
66
59
 
67
60
  ```mdx docs/index.mdx lineNumbers
68
61
  ---
@@ -72,14 +65,10 @@ description: Welcome to my docs.
72
65
 
73
66
  Welcome! Use **Markdown** and built-in components — no imports required:
74
67
 
75
- :::note
76
- Blume ships callouts, cards, tabs, steps, and more.
77
- :::
68
+ :::note Blume ships callouts, cards, tabs, steps, and more. :::
78
69
  ```
79
70
 
80
- Save it, and the dev server reloads instantly. Navigation, search, and page
81
- metadata are inferred from your files as you add them — keep writing, and the
82
- site keeps up.
71
+ Save it, and the dev server reloads instantly. Navigation, search, and page metadata are inferred from your files as you add them — keep writing, and the site keeps up.
83
72
 
84
73
  ## Next steps
85
74
 
@@ -8,8 +8,7 @@ sidebar:
8
8
 
9
9
  ## Deploy anywhere (static)
10
10
 
11
- `blume build` compiles your docs to plain HTML, CSS, and a local search index in
12
- `dist/`. There's no server to run — point any static host at the folder.
11
+ `blume build` compiles your docs to plain HTML, CSS, and a local search index in `dist/`. There's no server to run — point any static host at the folder.
13
12
 
14
13
  | Setting | Value |
15
14
  | ---------------- | ------------- |
@@ -17,9 +16,7 @@ sidebar:
17
16
  | Output directory | `dist` |
18
17
  | Node version | 22 or newer |
19
18
 
20
- These settings work on Vercel, Netlify, Cloudflare Pages, GitHub Pages, Amazon
21
- S3 + CloudFront, or any bucket or CDN. Make sure `blume` is a dependency so the
22
- host can run the build.
19
+ These settings work on Vercel, Netlify, Cloudflare Pages, GitHub Pages, Amazon S3 + CloudFront, or any bucket or CDN. Make sure `blume` is a dependency so the host can run the build.
23
20
 
24
21
  A static build includes:
25
22
 
@@ -32,12 +29,9 @@ A static build includes:
32
29
 
33
30
  ### Set your site URL
34
31
 
35
- Sitemaps, canonical tags, RSS, and Open Graph images need an absolute origin. On
36
- **Vercel**, **Netlify**, and **Cloudflare Pages**, Blume detects it from the
37
- platform's environment at build time — no config required.
32
+ Sitemaps, canonical tags, RSS, and Open Graph images need an absolute origin. On **Vercel**, **Netlify**, and **Cloudflare Pages**, Blume detects it from the platform's environment at build time — no config required.
38
33
 
39
- Set `deployment.site` to override the detected value, or to provide one on hosts
40
- that don't expose it (GitHub Pages, S3, a custom CDN):
34
+ Set `deployment.site` to override the detected value, or to provide one on hosts that don't expose it (GitHub Pages, S3, a custom CDN):
41
35
 
42
36
  ```ts blume.config.ts lineNumbers
43
37
  deployment: {
@@ -45,18 +39,13 @@ deployment: {
45
39
  }
46
40
  ```
47
41
 
48
- When detecting automatically, Blume prefers your stable production domain over
49
- per-deploy preview URLs, so the canonical origin stays put across deploys.
42
+ When detecting automatically, Blume prefers your stable production domain over per-deploy preview URLs, so the canonical origin stays put across deploys.
50
43
 
51
- During `blume dev`, the site URL falls back to your local dev server (e.g.
52
- `http://localhost:4321`) when none is set, so site-gated features — Open Graph
53
- images, canonicals, the sitemap — work out of the box. Builds never use this
54
- fallback, so production output is never pointed at localhost.
44
+ During `blume dev`, the site URL falls back to your local dev server (e.g. `http://localhost:4321`) when none is set, so site-gated features — Open Graph images, canonicals, the sitemap — work out of the box. Builds never use this fallback, so production output is never pointed at localhost.
55
45
 
56
46
  ## Preview locally
57
47
 
58
- Before you ship, preview the production build exactly as a static host would
59
- serve it:
48
+ Before you ship, preview the production build exactly as a static host would serve it:
60
49
 
61
50
  ```bash
62
51
  blume build
@@ -65,9 +54,7 @@ blume preview
65
54
 
66
55
  ## Subpath deploys
67
56
 
68
- Serving docs under a path like `example.com/docs`? Set `deployment.base` — common
69
- for GitHub Pages project sites. Internal links and assets are rewritten to
70
- include the base path.
57
+ Serving docs under a path like `example.com/docs`? Set `deployment.base` — common for GitHub Pages project sites. Internal links and assets are rewritten to include the base path.
71
58
 
72
59
  ```ts blume.config.ts lineNumbers
73
60
  deployment: {
@@ -77,8 +64,7 @@ deployment: {
77
64
 
78
65
  ## Server rendering
79
66
 
80
- Static output covers most docs. Switch to server output when you need
81
- request-time features — most notably the [Ask AI](/docs/configuration/ai) endpoint:
67
+ Static output covers most docs. Switch to server output when you need request-time features — most notably the [Ask AI](/docs/configuration/ai) endpoint:
82
68
 
83
69
  ```ts blume.config.ts lineNumbers
84
70
  deployment: {
@@ -96,19 +82,11 @@ Choosing an adapter pulls in the matching Astro adapter automatically:
96
82
  | `node` | `@astrojs/node` | Self-hosted Node servers, containers |
97
83
  | `cloudflare` | `@astrojs/cloudflare` | Cloudflare Workers and Pages |
98
84
 
99
- On **Vercel**, **Netlify**, and **Cloudflare Pages**, Blume picks the matching
100
- adapter automatically for server output — set `output: "server"` and deploy. Set
101
- `adapter` explicitly to override the detected value, or when self-hosting with
102
- `node`.
85
+ On **Vercel**, **Netlify**, and **Cloudflare Pages**, Blume picks the matching adapter automatically for server output — set `output: "server"` and deploy. Set `adapter` explicitly to override the detected value, or when self-hosting with `node`.
103
86
 
104
- A server build includes everything a static build does, plus any Astro endpoints
105
- or middleware you add. The `node` adapter produces a standalone server you can
106
- run directly.
87
+ A server build includes everything a static build does, plus any Astro endpoints or middleware you add. The `node` adapter produces a standalone server you can run directly.
107
88
 
108
- :::note
109
- Server features have their own configuration — for example, Ask AI needs a model
110
- API key. See the [AI guide](/docs/configuration/ai) for setup.
111
- :::
89
+ :::note Server features have their own configuration — for example, Ask AI needs a model API key. See the [AI guide](/docs/configuration/ai) for setup. :::
112
90
 
113
91
  ## Redirects
114
92
 
@@ -118,12 +96,20 @@ Map old URLs to new ones in `blume.config.ts`:
118
96
  redirects: [{ from: "/old", to: "/new", status: 301 }];
119
97
  ```
120
98
 
121
- `status` accepts `301`, `302`, `307`, or `308` (default `301`). Static builds
122
- emit redirect pages; server builds handle redirects at request time.
99
+ `status` accepts `301`, `302`, `307`, or `308` (default `301`). Server builds handle redirects at request time. Static builds emit redirect pages **and** platform files so your host issues a real HTTP redirect: `_redirects` (Netlify, Cloudflare Pages), `vercel.json` (Vercel), and `blume-redirects.json` — a structured manifest for anything else (nginx/Apache rules, an edge worker). A `_redirects` or `vercel.json` you ship in `public/` is left untouched.
100
+
101
+ ## Environment variables
102
+
103
+ When a feature needs a runtime secret, Blume warns at `blume dev`/`build` if it's missing — so the problem surfaces early instead of at the first request:
104
+
105
+ | Feature | Variable |
106
+ | --- | --- |
107
+ | Ask AI (AI Gateway) | `AI_GATEWAY_API_KEY` (or Vercel OIDC) |
108
+ | Ask AI (OpenRouter / OpenAI-compatible) | the provider's `apiKeyEnv` |
109
+ | Mixedbread search | `MIXEDBREAD_API_KEY` |
110
+
111
+ Set them in `.env.local` for local dev and in your host's environment for production. Build-time secrets for search-index sync (Algolia, Orama Cloud, Typesense) are warned about separately during the sync step.
123
112
 
124
113
  ## Build summary
125
114
 
126
- Every build prints a summary — output mode, adapter, resolved site URL, search
127
- provider, redirect count, sitemap and `llms.txt` status, and any enabled server
128
- features — so you can confirm what shipped (including anything auto-detected)
129
- before you deploy.
115
+ Every build prints a summary — output mode, adapter, resolved site URL, search provider, redirect count, sitemap and `llms.txt` status, and any enabled server features — so you can confirm what shipped (including anything auto-detected) before you deploy.
@@ -3,11 +3,7 @@ title: OpenAPI / AsyncAPI
3
3
  description: Drop in an OpenAPI or AsyncAPI spec and get an interactive reference, rendered by Scalar.
4
4
  ---
5
5
 
6
- Point Blume at an OpenAPI or AsyncAPI spec and it generates an interactive API
7
- reference — schemas, authentication, examples, and a request playground — on its
8
- own route. The reference is rendered by [Scalar](https://scalar.com), not by
9
- Blume: API reference isn't core to Blume, so the whole surface is delegated to a
10
- tool that has already solved its large edge-case space.
6
+ Point Blume at an OpenAPI or AsyncAPI spec and it generates an interactive API reference — schemas, authentication, examples, and a request playground — on its own route. The reference is rendered by [Scalar](https://scalar.com), not by Blume: API reference isn't core to Blume, so the whole surface is delegated to a tool that has already solved its large edge-case space.
11
7
 
12
8
  ```ts blume.config.ts lineNumbers
13
9
  openapi: {
@@ -16,20 +12,13 @@ openapi: {
16
12
  }
17
13
  ```
18
14
 
19
- That mounts the reference at `/reference` and adds a header link to it. The
20
- `spec` is either an `http(s)` URL or a path to a local file in your project.
15
+ That mounts the reference at `/reference` and adds a header link to it. The `spec` is either an `http(s)` URL or a path to a local file in your project.
21
16
 
22
- :::note
23
- The reference mounts inside Blume's shell — your navbar stays on top — but the
24
- body is a **self-contained Scalar embed** with its own sidebar, search, and
25
- theme. By design it doesn't weave into Blume's content sidebar, site search, or
26
- `llms.txt`.
27
- :::
17
+ :::note The reference mounts inside Blume's shell — your navbar stays on top — but the body is a **self-contained Scalar embed** with its own sidebar, search, and theme. By design it doesn't weave into Blume's content sidebar, site search, or `llms.txt`. :::
28
18
 
29
19
  ## A local spec
30
20
 
31
- A relative path is resolved from your project root and inlined at build time, so
32
- nothing is copied into your source tree and the page works offline:
21
+ A relative path is resolved from your project root and inlined at build time, so nothing is copied into your source tree and the page works offline:
33
22
 
34
23
  ```ts blume.config.ts lineNumbers
35
24
  openapi: {
@@ -54,9 +43,7 @@ openapi: {
54
43
 
55
44
  ## Multiple specs
56
45
 
57
- Use `sources` to publish more than one spec. Each source gets its own route and
58
- header link. Give each a `label` (used for the link and to derive its route), or
59
- set an explicit `route`:
46
+ Use `sources` to publish more than one spec. Each source gets its own route and header link. Give each a `label` (used for the link and to derive its route), or set an explicit `route`:
60
47
 
61
48
  ```ts blume.config.ts lineNumbers
62
49
  openapi: {
@@ -68,14 +55,11 @@ openapi: {
68
55
  }
69
56
  ```
70
57
 
71
- `spec` is shorthand for a single-entry `sources`, so you only reach for `sources`
72
- when you have more than one.
58
+ `spec` is shorthand for a single-entry `sources`, so you only reach for `sources` when you have more than one.
73
59
 
74
60
  ## AsyncAPI
75
61
 
76
- Event-driven APIs use a sibling `asyncapi` block with the **same shape** — Scalar
77
- renders AsyncAPI through the same component. Only the default route differs
78
- (`/events`):
62
+ Event-driven APIs use a sibling `asyncapi` block with the **same shape** — Scalar renders AsyncAPI through the same component. Only the default route differs (`/events`):
79
63
 
80
64
  ```ts blume.config.ts lineNumbers
81
65
  asyncapi: {
@@ -84,18 +68,11 @@ asyncapi: {
84
68
  }
85
69
  ```
86
70
 
87
- :::warning
88
- Scalar's AsyncAPI support is still a work in progress — it renders channels,
89
- operations, messages, and a Models section, but there's **no interactive
90
- playground** for events yet. It improves upstream over time.
91
- :::
71
+ :::warning Scalar's AsyncAPI support is still a work in progress — it renders channels, operations, messages, and a Models section, but there's **no interactive playground** for events yet. It improves upstream over time. :::
92
72
 
93
73
  ## Theming
94
74
 
95
- By default Blume layers your [accent and radius](/docs/configuration/theming) onto
96
- Scalar's theme so the reference doesn't feel jarring. It's best-effort, not
97
- pixel-identical — Scalar carries its own design system. To pick a specific
98
- [Scalar theme](https://github.com/scalar/scalar) instead, set `theme`:
75
+ By default Blume layers your [accent and radius](/docs/configuration/theming) onto Scalar's theme so the reference doesn't feel jarring. It's best-effort, not pixel-identical — Scalar carries its own design system. To pick a specific [Scalar theme](https://github.com/scalar/scalar) instead, set `theme`:
99
76
 
100
77
  ```ts blume.config.ts lineNumbers
101
78
  openapi: {
@@ -107,8 +84,4 @@ openapi: {
107
84
 
108
85
  ## The playground and CORS
109
86
 
110
- Scalar's "Try it" playground calls your **target API directly from the
111
- browser** — Blume doesn't proxy the request. For it to succeed, the API must
112
- allow cross-origin requests from the docs site (send the appropriate
113
- `Access-Control-Allow-Origin` headers). This is a property of the API being
114
- documented, not of Blume.
87
+ Scalar's "Try it" playground calls your **target API directly from the browser** — Blume doesn't proxy the request. For it to succeed, the API must allow cross-origin requests from the docs site (send the appropriate `Access-Control-Allow-Origin` headers). This is a property of the API being documented, not of Blume.
@@ -3,16 +3,11 @@ title: Blog
3
3
  description: Publish posts as content, get an RSS feed and article structured data for free, and build a custom index page.
4
4
  ---
5
5
 
6
- A blog in Blume is just content with a type. Mark a page `type: blog` and Blume
7
- gives it an RSS feed and richer article metadata automatically. Unlike the
8
- [changelog](/docs/advanced/changelog), there's no generated index page — you compose
9
- the landing page yourself, which keeps the design entirely in your hands.
6
+ A blog in Blume is just content with a type. Mark a page `type: blog` and Blume gives it an RSS feed and richer article metadata automatically. Unlike the [changelog](/docs/advanced/changelog), there's no generated index page — you compose the landing page yourself, which keeps the design entirely in your hands.
10
7
 
11
8
  ## Write a post
12
9
 
13
- A post is a regular `.md` or `.mdx` page with `type: blog` in its frontmatter. By
14
- convention posts live under `blog/`, but the type — not the folder — is what
15
- matters:
10
+ A post is a regular `.md` or `.mdx` page with `type: blog` in its frontmatter. By convention posts live under `blog/`, but the type — not the folder — is what matters:
16
11
 
17
12
  ```mdx blog/introducing-blume.mdx lineNumbers
18
13
  ---
@@ -22,19 +17,14 @@ date: 2026-06-22
22
17
  description: Why we built a markdown-first docs framework.
23
18
  ---
24
19
 
25
- Documentation should be fast, AI-ready, and zero-config — down to not needing a
26
- starter template at all. Here's the thinking behind Blume.
20
+ Documentation should be fast, AI-ready, and zero-config — down to not needing a starter template at all. Here's the thinking behind Blume.
27
21
  ```
28
22
 
29
- Give every post a `date` so feed items sort newest-first and carry a `pubDate`,
30
- and a `description` — it's used for both the feed summary and SEO.
23
+ Give every post a `date` so feed items sort newest-first and carry a `pubDate`, and a `description` — it's used for both the feed summary and SEO.
31
24
 
32
25
  ## The RSS feed
33
26
 
34
- Blume builds a blog feed at **`/blog/rss.xml`**, sorted newest-first by `date`.
35
- Feeds need an absolute site URL, so set [`deployment.site`](/docs/deployment); Blume
36
- then injects a `<link rel="alternate">` tag on every page so readers discover it
37
- automatically.
27
+ Blume builds a blog feed at **`/blog/rss.xml`**, sorted newest-first by `date`. Feeds need an absolute site URL, so set [`deployment.site`](/docs/deployment); Blume then injects a `<link rel="alternate">` tag on every page so readers discover it automatically.
38
28
 
39
29
  The feed is on by default. Tune it under [`seo.rss`](/docs/configuration/seo#rss-feeds):
40
30
 
@@ -52,14 +42,11 @@ Remove `"blog"` from `rss.types` to skip the feed.
52
42
 
53
43
  ## Structured data
54
44
 
55
- When [structured data](/docs/configuration/seo#structured-data) is on, each post is
56
- emitted as a schema.org **`BlogPosting`** with its description and publish date —
57
- the richer article type search engines expect for blog content.
45
+ When [structured data](/docs/configuration/seo#structured-data) is on, each post is emitted as a schema.org **`BlogPosting`** with its description and publish date — the richer article type search engines expect for blog content.
58
46
 
59
47
  ## Building an index
60
48
 
61
- Blume doesn't generate a `/blog` landing page, so you build one. The simplest
62
- option is a content page that links to each post by hand:
49
+ Blume doesn't generate a `/blog` landing page, so you build one. The simplest option is a content page that links to each post by hand:
63
50
 
64
51
  ```mdx blog/index.mdx lineNumbers
65
52
  ---
@@ -74,9 +61,7 @@ description: News and writing from the team.
74
61
  </CardGroup>
75
62
  ```
76
63
 
77
- To list posts automatically instead, add a [custom page](/docs/advanced/custom-pages)
78
- at `pages/blog/index.astro` that reads from Astro's `docs` content collection and
79
- pairs each entry with its route from `blume:data`:
64
+ To list posts automatically instead, add a [custom page](/docs/advanced/custom-pages) at `pages/blog/index.astro` that reads from Astro's `docs` content collection and pairs each entry with its route from `blume:data`:
80
65
 
81
66
  ```astro pages/blog/index.astro lineNumbers
82
67
  ---
@@ -108,8 +93,7 @@ const posts = (await getCollection("docs"))
108
93
  </ul>
109
94
  ```
110
95
 
111
- See [Custom Pages](/docs/advanced/custom-pages#using-the-site-layout) for wrapping this
112
- in the full site layout.
96
+ See [Custom Pages](/docs/advanced/custom-pages#using-the-site-layout) for wrapping this in the full site layout.
113
97
 
114
98
  <CardGroup cols={2}>
115
99
  <Card title="Custom Pages" href="/docs/advanced/custom-pages" icon="folder">
@@ -3,16 +3,11 @@ title: Changelog
3
3
  description: Author release notes as content, and Blume builds a timeline page and an RSS feed automatically.
4
4
  ---
5
5
 
6
- Blume ships a changelog out of the box. Write each release as a normal content
7
- file, mark it `type: changelog`, and Blume collects every entry into a generated
8
- timeline page and an RSS feed — no layout to build, no list to maintain. Or skip
9
- the files entirely and [source your changelog from GitHub Releases](#from-github-releases).
6
+ Blume ships a changelog out of the box. Write each release as a normal content file, mark it `type: changelog`, and Blume collects every entry into a generated timeline page and an RSS feed — no layout to build, no list to maintain. Or skip the files entirely and [source your changelog from GitHub Releases](#from-github-releases).
10
7
 
11
8
  ## Write an entry
12
9
 
13
- A changelog entry is a regular `.md` or `.mdx` page with `type: changelog` in its
14
- frontmatter. By convention they live under `changelog/`, but the type — not the
15
- folder — is what matters:
10
+ A changelog entry is a regular `.md` or `.mdx` page with `type: changelog` in its frontmatter. By convention they live under `changelog/`, but the type — not the folder — is what matters:
16
11
 
17
12
  ```mdx changelog/v1-2-0.mdx lineNumbers
18
13
  ---
@@ -24,15 +19,13 @@ changelog:
24
19
  category: Features
25
20
  ---
26
21
 
27
- A big batch of components landed this release — columns, frames, trees, and
28
- tooltips, plus code groups that render as proper language tabs.
22
+ A big batch of components landed this release — columns, frames, trees, and tooltips, plus code groups that render as proper language tabs.
29
23
 
30
24
  - New `Accordion`, `Expandable`, and `Tooltip` components
31
25
  - `CodeGroup` tabs with flush code blocks
32
26
  ```
33
27
 
34
- Give every entry a `date` so the timeline and feed sort newest-first. An
35
- unquoted YAML date is fine — Blume normalizes it.
28
+ Give every entry a `date` so the timeline and feed sort newest-first. An unquoted YAML date is fine — Blume normalizes it.
36
29
 
37
30
  ### The `changelog` object
38
31
 
@@ -60,25 +53,17 @@ The optional `changelog` object adds richer metadata for the timeline and feed:
60
53
 
61
54
  ## The timeline page
62
55
 
63
- Once you have at least one `type: changelog` entry, Blume generates a
64
- **`/changelog`** page automatically. Each entry renders newest-first with its
65
- date, label, and `category` tag in a left rail beside its content:
56
+ Once you have at least one `type: changelog` entry, Blume generates a **`/changelog`** page automatically. Each entry renders newest-first with its date, label, and `category` tag in a left rail beside its content:
66
57
 
67
58
  - The entry **title** becomes its label — or `v{version}` when there's no title.
68
59
  - The `category` renders as a tag next to the date.
69
60
  - Drafts and `sidebar.hidden` entries are skipped.
70
61
 
71
- The page appears only when nothing already occupies the `/changelog` route. To
72
- replace it with your own design, add a [custom page](/docs/advanced/custom-pages) at
73
- `pages/changelog.astro` — it takes over and Blume stops generating the default
74
- timeline.
62
+ The page appears only when nothing already occupies the `/changelog` route. To replace it with your own design, add a [custom page](/docs/advanced/custom-pages) at `pages/changelog.astro` — it takes over and Blume stops generating the default timeline.
75
63
 
76
64
  ## From GitHub Releases
77
65
 
78
- Rather than authoring entries by hand, point the built-in
79
- [`github-releases` source](/docs/content/sources#github-releases) at a repo and
80
- every release becomes a `type: changelog` entry — the same timeline and feed,
81
- fed straight from the releases you already publish:
66
+ Rather than authoring entries by hand, point the built-in [`github-releases` source](/docs/content/sources#github-releases) at a repo and every release becomes a `type: changelog` entry — the same timeline and feed, fed straight from the releases you already publish:
82
67
 
83
68
  ```ts blume.config.ts
84
69
  content: {
@@ -94,17 +79,11 @@ content: {
94
79
  }
95
80
  ```
96
81
 
97
- The release name becomes the title, its tag becomes `changelog.version`, and its
98
- published date sorts the timeline. A private repo authenticates with the
99
- `GITHUB_TOKEN` environment variable. See
100
- [Content sources](/docs/content/sources#github-releases) for every option.
82
+ The release name becomes the title, its tag becomes `changelog.version`, and its published date sorts the timeline. A private repo authenticates with the `GITHUB_TOKEN` environment variable. See [Content sources](/docs/content/sources#github-releases) for every option.
101
83
 
102
84
  ## The RSS feed
103
85
 
104
- Blume also builds a changelog feed at **`/changelog/rss.xml`**, sorted
105
- newest-first by `date`. Feeds need an absolute site URL, so set
106
- [`deployment.site`](/docs/deployment); Blume then injects a `<link rel="alternate">`
107
- tag on every page so readers discover it automatically.
86
+ Blume also builds a changelog feed at **`/changelog/rss.xml`**, sorted newest-first by `date`. Feeds need an absolute site URL, so set [`deployment.site`](/docs/deployment); Blume then injects a `<link rel="alternate">` tag on every page so readers discover it automatically.
108
87
 
109
88
  The feed is on by default. Tune it under [`seo.rss`](/docs/configuration/seo#rss-feeds):
110
89
 
@@ -122,9 +101,7 @@ Remove `"changelog"` from `rss.types` to skip the feed while keeping the timelin
122
101
 
123
102
  ## Structured data
124
103
 
125
- When [structured data](/docs/configuration/seo#structured-data) is on, each changelog
126
- entry is emitted as a schema.org **`TechArticle`** with its description and
127
- publish date, so search engines can index releases as dated articles.
104
+ When [structured data](/docs/configuration/seo#structured-data) is on, each changelog entry is emitted as a schema.org **`TechArticle`** with its description and publish date, so search engines can index releases as dated articles.
128
105
 
129
106
  <CardGroup cols={2}>
130
107
  <Card