blume 0.3.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 (81) hide show
  1. package/dist/cli/index.js +747 -471
  2. package/dist/cli/index.js.map +45 -38
  3. package/dist/types/core/schema.d.ts +289 -278
  4. package/dist/types/migrate/mintlify/assets.d.ts +8 -0
  5. package/docs/01-quickstart.mdx +5 -16
  6. package/docs/02-deployment.mdx +21 -54
  7. package/docs/advanced/api-reference.mdx +10 -37
  8. package/docs/advanced/blog.mdx +9 -25
  9. package/docs/advanced/changelog.mdx +10 -33
  10. package/docs/advanced/custom-pages.mdx +21 -78
  11. package/docs/configuration/ai.mdx +42 -103
  12. package/docs/configuration/analytics.mdx +20 -38
  13. package/docs/configuration/customization.mdx +40 -73
  14. package/docs/configuration/export.mdx +9 -34
  15. package/docs/configuration/index.mdx +67 -87
  16. package/docs/configuration/search.mdx +17 -54
  17. package/docs/configuration/seo.mdx +17 -48
  18. package/docs/configuration/theming.mdx +20 -42
  19. package/docs/content/components.mdx +42 -101
  20. package/docs/content/i18n.mdx +21 -72
  21. package/docs/content/index.mdx +18 -48
  22. package/docs/content/islands.mdx +25 -52
  23. package/docs/content/meta.mdx +23 -50
  24. package/docs/content/navigation.mdx +23 -62
  25. package/docs/content/sources.mdx +20 -83
  26. package/docs/content/syntax.mdx +37 -105
  27. package/docs/index.mdx +11 -40
  28. package/docs/reference/cli.mdx +18 -29
  29. package/docs/reference/frontmatter.mdx +2 -5
  30. package/package.json +1 -1
  31. package/src/astro/integration.ts +26 -3
  32. package/src/astro/islands.ts +6 -2
  33. package/src/astro/markdown-negotiation.ts +17 -3
  34. package/src/astro/pages.ts +6 -1
  35. package/src/astro/static-assets.ts +117 -0
  36. package/src/astro/templates.ts +48 -26
  37. package/src/cli/args.ts +23 -0
  38. package/src/cli/commands/build.ts +23 -0
  39. package/src/cli/commands/dev.ts +11 -2
  40. package/src/cli/commands/doctor.ts +10 -1
  41. package/src/cli/commands/eject.ts +3 -1
  42. package/src/cli/commands/init.ts +21 -1
  43. package/src/cli/commands/preview.ts +2 -1
  44. package/src/cli/commands/validate.ts +12 -1
  45. package/src/cli/dev-lock.ts +84 -0
  46. package/src/cli/log.ts +11 -0
  47. package/src/components/BlumePage.astro +2 -0
  48. package/src/components/content/YouTube.astro +35 -0
  49. package/src/components/content/youtube.ts +46 -0
  50. package/src/components/islands/ask-ai.tsx +14 -14
  51. package/src/components/props.ts +3 -0
  52. package/src/core/assets.ts +31 -0
  53. package/src/core/bridge.ts +10 -0
  54. package/src/core/builtin-tags.ts +1 -0
  55. package/src/core/diagnostics.ts +6 -1
  56. package/src/core/gitignore.ts +30 -0
  57. package/src/core/links.ts +60 -19
  58. package/src/core/schema.ts +7 -0
  59. package/src/core/sources/mdx-remote.ts +54 -8
  60. package/src/core/sources/normalize.ts +6 -1
  61. package/src/core/sources/notion.ts +49 -5
  62. package/src/core/sources/sanity.ts +5 -1
  63. package/src/deploy/rss.ts +1 -8
  64. package/src/deploy/sitemap.ts +20 -1
  65. package/src/deploy/xml.ts +8 -0
  66. package/src/markdown/directives.ts +15 -7
  67. package/src/markdown/package-commands.ts +26 -4
  68. package/src/migrate/fumadocs/content.ts +14 -1
  69. package/src/migrate/fumadocs/groups.ts +7 -0
  70. package/src/migrate/fumadocs/index.ts +5 -2
  71. package/src/migrate/mintlify/assets.ts +46 -0
  72. package/src/migrate/mintlify/index.ts +53 -45
  73. package/src/migrate/shared.ts +12 -27
  74. package/src/og/card.ts +14 -2
  75. package/src/registry/eject.ts +13 -3
  76. package/src/registry/registry.ts +6 -0
  77. package/src/registry/rewrite-imports.ts +31 -19
  78. package/src/search/documents.ts +23 -5
  79. package/src/search/sync/algolia.ts +5 -1
  80. package/src/search/sync/typesense.ts +24 -16
  81. package/src/theme/palette.ts +26 -7
@@ -3,38 +3,23 @@ title: Search
3
3
  description: Client-side search out of the box, with optional hosted and semantic backends.
4
4
  ---
5
5
 
6
- Blume ships local search with no hosted infrastructure and no API keys. It runs
7
- in the browser, works in both `blume dev` and `blume build`, and indexes only
8
- your real content — navigation chrome and excluded pages are skipped. When you
9
- outgrow it, you can switch to a hosted or semantic backend without changing how
10
- search looks or behaves — only the `search.provider` you configure changes.
6
+ Blume ships local search with no hosted infrastructure and no API keys. It runs in the browser, works in both `blume dev` and `blume build`, and indexes only your real content — navigation chrome and excluded pages are skipped. When you outgrow it, you can switch to a hosted or semantic backend without changing how search looks or behaves — only the `search.provider` you configure changes.
11
7
 
12
- Blume reaches parity with Fumadocs' provider set: **Orama**, **FlexSearch**,
13
- **Algolia**, **Orama Cloud**, **Typesense**, and **Mixedbread** (plus
14
- **Pagefind**). Only the configured provider's SDK is installed into your project,
15
- so picking one backend never pulls in the others.
8
+ Blume reaches parity with Fumadocs' provider set: **Orama**, **FlexSearch**, **Algolia**, **Orama Cloud**, **Typesense**, and **Mixedbread** (plus **Pagefind**). Only the configured provider's SDK is installed into your project, so picking one backend never pulls in the others.
16
9
 
17
10
  ## Using search
18
11
 
19
- Open search with <Badge variant="accent">⌘K</Badge> (or `Ctrl K`), or press `/`
20
- when you're not typing in a field. `Esc` closes it, and `⌘J` (or `Ctrl J`)
21
- toggles the result preview pane.
12
+ Open search with <Badge variant="accent">⌘K</Badge> (or `Ctrl K`), or press `/` when you're not typing in a field. `Esc` closes it, and `⌘J` (or `Ctrl J`) toggles the result preview pane.
22
13
 
23
- Queries match page **titles**, **descriptions**, and **body text**, with title
24
- matches ranked highest and descriptions above body.
14
+ Queries match page **titles**, **descriptions**, and **body text**, with title matches ranked highest and descriptions above body.
25
15
 
26
16
  ## What's indexed
27
17
 
28
- For every indexable page, Blume indexes its title, description, and body reduced
29
- to plain text — code blocks, images, and markup are stripped, so results stay
30
- relevant. The index is built from your source files, so it's identical in dev and
31
- production.
18
+ For every indexable page, Blume indexes its title, description, and body reduced to plain text — code blocks, images, and markup are stripped, so results stay relevant. The index is built from your source files, so it's identical in dev and production.
32
19
 
33
20
  ## Tags
34
21
 
35
- Add `search.tags` to a page's frontmatter to group it under a filter in the
36
- search dialog — readers can narrow results to a tag with a click. Tags also
37
- become a facet on the hosted providers.
22
+ Add `search.tags` to a page's frontmatter to group it under a filter in the search dialog — readers can narrow results to a tag with a click. Tags also become a facet on the hosted providers.
38
23
 
39
24
  ```yaml
40
25
  search:
@@ -43,16 +28,11 @@ search:
43
28
 
44
29
  ## Providers
45
30
 
46
- The client-side providers are keyless and need no extra config. The hosted ones
47
- take **public** credentials in `blume.config.ts` (safe to ship to the browser)
48
- and read their **secret** admin key from an environment variable at build time —
49
- the secret never lands in the config or the client bundle.
31
+ The client-side providers are keyless and need no extra config. The hosted ones take **public** credentials in `blume.config.ts` (safe to ship to the browser) and read their **secret** admin key from an environment variable at build time — the secret never lands in the config or the client bundle.
50
32
 
51
33
  ### Orama (default)
52
34
 
53
- Blume's default engine. It builds a JSON index served at `/blume-search.json` and
54
- queries it in the browser — instant, client-side, and live in `blume dev` as you
55
- edit. No keys, no service.
35
+ Blume's default engine. It builds a JSON index served at `/blume-search.json` and queries it in the browser — instant, client-side, and live in `blume dev` as you edit. No keys, no service.
56
36
 
57
37
  ```ts blume.config.ts lineNumbers
58
38
  search: {
@@ -62,9 +42,7 @@ search: {
62
42
 
63
43
  ### FlexSearch
64
44
 
65
- A second keyless, client-side option. It reuses the same `/blume-search.json`
66
- index Orama ships and builds a [FlexSearch](https://github.com/nextapps-de/flexsearch)
67
- document index in the browser. Works in `blume dev` and `blume build`.
45
+ A second keyless, client-side option. It reuses the same `/blume-search.json` index Orama ships and builds a [FlexSearch](https://github.com/nextapps-de/flexsearch) document index in the browser. Works in `blume dev` and `blume build`.
68
46
 
69
47
  ```ts blume.config.ts lineNumbers
70
48
  search: {
@@ -74,9 +52,7 @@ search: {
74
52
 
75
53
  ### Pagefind
76
54
 
77
- For very large docs, opt into [Pagefind](https://pagefind.app). It indexes your
78
- built HTML and loads the index in shards on demand, keeping the initial payload
79
- tiny no matter how big the site grows.
55
+ For very large docs, opt into [Pagefind](https://pagefind.app). It indexes your built HTML and loads the index in shards on demand, keeping the initial payload tiny no matter how big the site grows.
80
56
 
81
57
  ```ts blume.config.ts lineNumbers
82
58
  search: {
@@ -84,14 +60,11 @@ search: {
84
60
  }
85
61
  ```
86
62
 
87
- Pagefind only runs during `blume build`, so search isn't available in `blume dev`
88
- with this provider.
63
+ Pagefind only runs during `blume build`, so search isn't available in `blume dev` with this provider.
89
64
 
90
65
  ### Algolia
91
66
 
92
- The browser queries [Algolia](https://www.algolia.com) directly with your
93
- search-only key. Each `blume build` uploads the index using the admin key from
94
- `ALGOLIA_ADMIN_API_KEY` (the build warns and skips the upload if it's unset).
67
+ The browser queries [Algolia](https://www.algolia.com) directly with your search-only key. Each `blume build` replaces the index using the admin key from `ALGOLIA_ADMIN_API_KEY` (the build warns and skips the upload if it's unset). The whole index is replaced on every sync, so pages you delete or rename don't linger as stale results.
95
68
 
96
69
  ```ts blume.config.ts lineNumbers
97
70
  search: {
@@ -106,9 +79,7 @@ search: {
106
79
 
107
80
  ### Orama Cloud
108
81
 
109
- Hosted Orama. The browser queries your index endpoint with the public API key;
110
- `blume build` pushes records to the index using `ORAMA_PRIVATE_API_KEY`. Set
111
- `indexId` to enable the sync.
82
+ Hosted Orama. The browser queries your index endpoint with the public API key; `blume build` pushes records to the index using `ORAMA_PRIVATE_API_KEY`. Set `indexId` to enable the sync.
112
83
 
113
84
  ```ts blume.config.ts lineNumbers
114
85
  search: {
@@ -123,9 +94,7 @@ search: {
123
94
 
124
95
  ### Typesense
125
96
 
126
- Self-hosted or cloud [Typesense](https://typesense.org). The browser queries the
127
- collection with the search-only key; `blume build` creates the collection (if
128
- needed) and imports documents using `TYPESENSE_ADMIN_API_KEY`.
97
+ Self-hosted or cloud [Typesense](https://typesense.org). The browser queries the collection with the search-only key; `blume build` recreates the collection and imports documents using `TYPESENSE_ADMIN_API_KEY`. The collection is dropped and rebuilt on every sync so deleted or renamed pages don't linger as stale results — if you hand-tune the collection's settings, reapply them after a build.
129
98
 
130
99
  ```ts blume.config.ts lineNumbers
131
100
  search: {
@@ -141,11 +110,7 @@ search: {
141
110
 
142
111
  ### Mixedbread
143
112
 
144
- Semantic search via [Mixedbread](https://www.mixedbread.com). Queries are proxied
145
- through a generated `/api/search` endpoint that holds your key, so this provider
146
- **requires server output** (`deployment.output: "server"`). The endpoint reads
147
- `MIXEDBREAD_API_KEY`. Sync your content to the store with the Mixedbread CLI in
148
- your build, e.g. `mxbai vs sync <STORE_ID> ./content --ci`.
113
+ Semantic search via [Mixedbread](https://www.mixedbread.com). Queries are proxied through a generated `/api/search` endpoint that holds your key, so this provider **requires server output** (`deployment.output: "server"`). The endpoint reads `MIXEDBREAD_API_KEY`. Sync your content to the store with the Mixedbread CLI in your build, e.g. `mxbai vs sync <STORE_ID> ./content --ci`.
149
114
 
150
115
  ```ts blume.config.ts lineNumbers
151
116
  search: {
@@ -166,16 +131,14 @@ search: {
166
131
 
167
132
  ## Excluding pages
168
133
 
169
- Only indexable pages are searched. A page is left out of the index when it sets
170
- `search.exclude` in frontmatter:
134
+ Only indexable pages are searched. A page is left out of the index when it sets `search.exclude` in frontmatter:
171
135
 
172
136
  ```yaml
173
137
  search:
174
138
  exclude: true
175
139
  ```
176
140
 
177
- [Hidden pages](/docs/content/navigation#hidden-pages) are also excluded by default.
178
- To index them anyway, opt in:
141
+ [Hidden pages](/docs/content/navigation#hidden-pages) are also excluded by default. To index them anyway, opt in:
179
142
 
180
143
  ```ts blume.config.ts lineNumbers
181
144
  search: {
@@ -5,9 +5,7 @@ sidebar:
5
5
  label: SEO
6
6
  ---
7
7
 
8
- Blume handles the discoverability layer for you: page metadata, social share
9
- images, feeds, and structured data. The three configurable features live under
10
- the `seo` key in `blume.config.ts`; metadata is driven by your content.
8
+ Blume handles the discoverability layer for you: page metadata, social share images, feeds, and structured data. The three configurable features live under the `seo` key in `blume.config.ts`; metadata is driven by your content.
11
9
 
12
10
  ```ts blume.config.ts lineNumbers
13
11
  seo: {
@@ -19,20 +17,16 @@ seo: {
19
17
  }
20
18
  ```
21
19
 
22
- Most of this is sharper with an absolute site URL — set
23
- [`deployment.site`](/docs/deployment) so feeds, OG images, canonicals, the sitemap,
24
- and JSON-LD can emit full URLs.
20
+ Most of this is sharper with an absolute site URL — set [`deployment.site`](/docs/deployment) so feeds, OG images, canonicals, the sitemap, and JSON-LD can emit full URLs.
25
21
 
26
22
  ## Metadata
27
23
 
28
24
  Every page renders the standard `<head>` tags from your config and frontmatter:
29
25
 
30
26
  - `<title>` — the page title plus your site `title`.
31
- - `<meta name="description">` and `og:description` — the page `description`,
32
- falling back to the site `description`.
27
+ - `<meta name="description">` and `og:description` — the page `description`, falling back to the site `description`.
33
28
  - `og:title` — the page title.
34
- - `<link rel="canonical">` — the page's absolute URL (when `deployment.site` is
35
- set).
29
+ - `<link rel="canonical">` — the page's absolute URL (when `deployment.site` is set).
36
30
 
37
31
  Override any of these per page with `seo` frontmatter:
38
32
 
@@ -74,11 +68,7 @@ seo:
74
68
 
75
69
  ## Open Graph images
76
70
 
77
- Blume can render a 1200×630 social card for every page at build time — no
78
- headless browser, thanks to [Takumi](https://takumi.kane.tw), so builds stay
79
- fast. On by default once [`deployment.site`](/docs/deployment) is set or
80
- auto-detected (the `og:image` URL has to be absolute to be useful to crawlers),
81
- and off otherwise. Set `enabled` to override that either way:
71
+ Blume can render a 1200×630 social card for every page at build time — no headless browser, thanks to [Takumi](https://takumi.kane.tw), so builds stay fast. On by default once [`deployment.site`](/docs/deployment) is set or auto-detected (the `og:image` URL has to be absolute to be useful to crawlers), and off otherwise. Set `enabled` to override that either way:
82
72
 
83
73
  ```ts blume.config.ts lineNumbers
84
74
  seo: {
@@ -86,10 +76,7 @@ seo: {
86
76
  }
87
77
  ```
88
78
 
89
- Each card is derived from your content and theme — the **page title** as the
90
- headline, your **site title** as the eyebrow, and your theme **accent** for the
91
- mark. Images are served at `/og/<slug>.png`, mirroring each route, and are
92
- prerendered as static files even in server mode:
79
+ Each card is derived from your content and theme — the **page title** as the headline, your **site title** as the eyebrow, and your theme **accent** for the mark. Images are served at `/og/<slug>.png`, mirroring each route, and are prerendered as static files even in server mode:
93
80
 
94
81
  | Page route | Image URL |
95
82
  | ------------------- | -------------------------- |
@@ -97,9 +84,7 @@ prerendered as static files even in server mode:
97
84
  | `/quickstart` | `/og/quickstart.png` |
98
85
  | `/configuration/ai` | `/og/configuration/ai.png` |
99
86
 
100
- Override the generated card for any page with `seo.image` — a file in `public/`
101
- or an external URL. It takes precedence over the generated card and works even
102
- when `og` is off, so you can mix custom images with generated ones:
87
+ Override the generated card for any page with `seo.image` — a file in `public/` or an external URL. It takes precedence over the generated card and works even when `og` is off, so you can mix custom images with generated ones:
103
88
 
104
89
  ```yaml lineNumbers
105
90
  ---
@@ -109,21 +94,13 @@ seo:
109
94
  ---
110
95
  ```
111
96
 
112
- :::note
113
- OG rendering uses hex internally, so an `oklch` custom accent falls back to the
114
- default. Use a named accent (`blue`, `teal`, …) or a hex value for custom cards.
115
- :::
97
+ :::note OG rendering uses hex internally, so an `oklch` custom accent falls back to the default. Use a named accent (`blue`, `teal`, …) or a hex value for custom cards. :::
116
98
 
117
- `seo.image` is frontmatter, so it only covers Markdown and MDX content. To give a
118
- custom [`.astro` page](/docs/advanced/custom-pages) its own social image — a
119
- marketing home or landing page, and the way to give the home page alone a bespoke
120
- share image — pass the `ogImage` prop to `PageLayout`.
99
+ `seo.image` is frontmatter, so it only covers Markdown and MDX content. To give a custom [`.astro` page](/docs/advanced/custom-pages) its own social image — a marketing home or landing page, and the way to give the home page alone a bespoke share image — pass the `ogImage` prop to `PageLayout`.
121
100
 
122
101
  ## RSS feeds
123
102
 
124
- Blume builds an RSS feed for each content type in `rss.types` — `blog` and
125
- `changelog` by default — that has pages, served at `/<type>/rss.xml`. See
126
- [Feeds](/docs/content#feeds) for authoring blog and changelog entries with dates.
103
+ Blume builds an RSS feed for each content type in `rss.types` — `blog` and `changelog` by default — that has pages, served at `/<type>/rss.xml`. See [Feeds](/docs/content#feeds) for authoring blog and changelog entries with dates.
127
104
 
128
105
  ```ts blume.config.ts lineNumbers
129
106
  seo: {
@@ -141,13 +118,11 @@ seo: {
141
118
  | `types` | `["blog", "changelog"]` | Content types that each get a feed. |
142
119
  | `limit` | `50` | Maximum items per feed, newest first. |
143
120
 
144
- Blume injects `<link rel="alternate">` tags so browsers and feed readers discover
145
- the feeds automatically.
121
+ Blume injects `<link rel="alternate">` tags so browsers and feed readers discover the feeds automatically.
146
122
 
147
123
  ## Structured data
148
124
 
149
- Blume emits [schema.org](https://schema.org) JSON-LD in every page's `<head>` so
150
- search engines understand your content. On by default:
125
+ Blume emits [schema.org](https://schema.org) JSON-LD in every page's `<head>` so search engines understand your content. On by default:
151
126
 
152
127
  ```ts blume.config.ts lineNumbers
153
128
  seo: {
@@ -158,18 +133,14 @@ seo: {
158
133
  Each page includes:
159
134
 
160
135
  - a **WebSite** node for site identity,
161
- - the page as an **article** — `BlogPosting` for blog posts, `TechArticle` for
162
- changelog and docs — with its description and publish date,
136
+ - the page as an **article** — `BlogPosting` for blog posts, `TechArticle` for changelog and docs — with its description and publish date,
163
137
  - a **BreadcrumbList** built from the navigation trail.
164
138
 
165
- URLs are absolute when `deployment.site` is set. Pages marked `seo.noindex` are
166
- skipped.
139
+ URLs are absolute when `deployment.site` is set. Pages marked `seo.noindex` are skipped.
167
140
 
168
141
  ## Sitemap
169
142
 
170
- Blume writes a `sitemap.xml` of every indexable page at build time. It needs an
171
- absolute [`deployment.site`](/docs/deployment) and lists every page except drafts,
172
- hidden, and `noindex` pages. On by default:
143
+ Blume writes a `sitemap.xml` of every indexable page at build time. It needs an absolute [`deployment.site`](/docs/deployment) and lists every page except drafts, hidden, and `noindex` pages. On by default:
173
144
 
174
145
  ```ts blume.config.ts lineNumbers
175
146
  seo: {
@@ -177,13 +148,11 @@ seo: {
177
148
  }
178
149
  ```
179
150
 
180
- Ship your own `public/sitemap.xml` to take over — Blume never overwrites a file
181
- you place in `public/`.
151
+ Ship your own `public/sitemap.xml` to take over — Blume never overwrites a file you place in `public/`.
182
152
 
183
153
  ## Robots
184
154
 
185
- Blume writes a `robots.txt` that allows all crawlers and adds a `Sitemap:` line
186
- pointing to the sitemap when one is available. On by default:
155
+ Blume writes a `robots.txt` that allows all crawlers and adds a `Sitemap:` line pointing to the sitemap when one is available. On by default:
187
156
 
188
157
  ```ts blume.config.ts lineNumbers
189
158
  seo: {
@@ -3,10 +3,7 @@ title: Theming
3
3
  description: Tune the look with config tokens, override any CSS variable in theme.css, or use Tailwind utilities.
4
4
  ---
5
5
 
6
- Blume's theme is token-driven and works in light and dark mode out of the box.
7
- Reach for as little or as much as you need: a few config tokens for the common
8
- cases, a `theme.css` to override any design token, or Tailwind utilities for
9
- custom components.
6
+ Blume's theme is token-driven and works in light and dark mode out of the box. Reach for as little or as much as you need: a few config tokens for the common cases, a `theme.css` to override any design token, or Tailwind utilities for custom components.
10
7
 
11
8
  ## Config tokens
12
9
 
@@ -27,8 +24,7 @@ theme: {
27
24
 
28
25
  ### Accent
29
26
 
30
- The accent color tints interactive and highlighted elements — step markers,
31
- active tabs, badges, card hovers, and more. Use a named preset or any CSS color:
27
+ The accent color tints interactive and highlighted elements — step markers, active tabs, badges, card hovers, and more. Use a named preset or any CSS color:
32
28
 
33
29
  ```ts blume.config.ts lineNumbers
34
30
  theme: {
@@ -36,13 +32,11 @@ theme: {
36
32
  }
37
33
  ```
38
34
 
39
- Named presets: `blue` (default), `green`, `orange`, `pink`, `purple`, `red`, and
40
- `teal`.
35
+ Named presets: `blue` (default), `green`, `orange`, `pink`, `purple`, `red`, and `teal`.
41
36
 
42
37
  ### Radius
43
38
 
44
- `radius` sets the corner rounding shared by cards, code blocks, callouts, and
45
- inputs — `none`, `sm`, `md` (default), or `lg`.
39
+ `radius` sets the corner rounding shared by cards, code blocks, callouts, and inputs — `none`, `sm`, `md` (default), or `lg`.
46
40
 
47
41
  ### Color mode
48
42
 
@@ -51,9 +45,7 @@ inputs — `none`, `sm`, `md` (default), or `lg`.
51
45
  - **`system`** (default) — follow the reader's OS preference
52
46
  - **`light`** / **`dark`** — default to one scheme
53
47
 
54
- A toggle in the header always lets readers switch, and their choice is remembered
55
- across visits. Dark mode is applied with a `data-theme="dark"` attribute on the
56
- `<html>` element.
48
+ A toggle in the header always lets readers switch, and their choice is remembered across visits. Dark mode is applied with a `data-theme="dark"` attribute on the `<html>` element.
57
49
 
58
50
  ### Fonts
59
51
 
@@ -83,26 +75,21 @@ theme: {
83
75
  }
84
76
  ```
85
77
 
86
- Fonts are **self-hosted**: Blume downloads them at build time and serves them from
87
- your own site, so there's no runtime request to Google and no layout shift (Astro
88
- generates fallback-metric faces automatically).
78
+ Fonts are **self-hosted**: Blume downloads them at build time and serves them from your own site, so there's no runtime request to Google and no layout shift (Astro generates fallback-metric faces automatically).
89
79
 
90
80
  Each value is a Google Fonts slug from the curated set below:
91
81
 
92
- | Category | Slugs |
93
- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
- | Sans | `dm-sans` `figtree` `geist` `ibm-plex-sans` `inter` `inter-tight` `manrope` `open-sans` `plus-jakarta-sans` `roboto` `source-sans-3` `space-grotesk` `work-sans` |
95
- | Serif | `ibm-plex-serif` `lora` `merriweather` `playfair-display` `source-serif-4` |
96
- | Mono | `fira-code` `geist-mono` `ibm-plex-mono` `jetbrains-mono` `roboto-mono` `source-code-pro` `space-mono` |
82
+ | Category | Slugs |
83
+ | --- | --- |
84
+ | Sans | `dm-sans` `figtree` `geist` `ibm-plex-sans` `inter` `inter-tight` `manrope` `open-sans` `plus-jakarta-sans` `roboto` `source-sans-3` `space-grotesk` `work-sans` |
85
+ | Serif | `ibm-plex-serif` `lora` `merriweather` `playfair-display` `source-serif-4` |
86
+ | Mono | `fira-code` `geist-mono` `ibm-plex-mono` `jetbrains-mono` `roboto-mono` `source-code-pro` `space-mono` |
97
87
 
98
- Need a font that isn't listed, or want to drop back to the system stack? Override
99
- the `--blume-font-*` tokens directly in [`theme.css`](#theme-css).
88
+ Need a font that isn't listed, or want to drop back to the system stack? Override the `--blume-font-*` tokens directly in [`theme.css`](#themecss).
100
89
 
101
90
  ### Dark-mode colors
102
91
 
103
- By default light and dark share one `accent`. Set `accentDark` for a different
104
- accent in dark mode, and `background` / `backgroundDark` to override the page
105
- background per mode:
92
+ By default light and dark share one `accent`. Set `accentDark` for a different accent in dark mode, and `background` / `backgroundDark` to override the page background per mode:
106
93
 
107
94
  ```ts blume.config.ts lineNumbers
108
95
  theme: {
@@ -117,8 +104,7 @@ Each takes a named preset or any CSS color, exactly like `accent`.
117
104
 
118
105
  ### Action color
119
106
 
120
- `action` is a secondary accent for primary calls to action and the `action`
121
- Tailwind utilities (`bg-action`, `text-action`). It defaults to your `accent`:
107
+ `action` is a secondary accent for primary calls to action and the `action` Tailwind utilities (`bg-action`, `text-action`). It defaults to your `accent`:
122
108
 
123
109
  ```ts blume.config.ts
124
110
  theme: {
@@ -128,8 +114,7 @@ theme: {
128
114
 
129
115
  ### Background decoration
130
116
 
131
- Add a subtle, theme-aware pattern behind your content with `backgroundDecoration`
132
- — `gradient`, `grid`, or `windows`:
117
+ Add a subtle, theme-aware pattern behind your content with `backgroundDecoration` — `gradient`, `grid`, or `windows`:
133
118
 
134
119
  ```ts blume.config.ts
135
120
  theme: {
@@ -137,8 +122,7 @@ theme: {
137
122
  }
138
123
  ```
139
124
 
140
- For a full background image, set `backgroundImage` (and `backgroundImageDark` for
141
- a dark variant) to a URL or a path under `public/`:
125
+ For a full background image, set `backgroundImage` (and `backgroundImageDark` for a dark variant) to a URL or a path under `public/`:
142
126
 
143
127
  ```ts blume.config.ts lineNumbers
144
128
  theme: {
@@ -149,8 +133,7 @@ theme: {
149
133
 
150
134
  ## theme.css
151
135
 
152
- Drop a `theme.css` in your project root to override any design token. It's the
153
- last layer in the cascade, so it wins over the defaults and config tokens:
136
+ Drop a `theme.css` in your project root to override any design token. It's the last layer in the cascade, so it wins over the defaults and config tokens:
154
137
 
155
138
  ```css theme.css lineNumbers
156
139
  :root {
@@ -163,8 +146,7 @@ last layer in the cascade, so it wins over the defaults and config tokens:
163
146
  }
164
147
  ```
165
148
 
166
- Set a token under `:root` for light mode and under `:root[data-theme="dark"]` for
167
- dark mode.
149
+ Set a token under `:root` for light mode and under `:root[data-theme="dark"]` for dark mode.
168
150
 
169
151
  ### Design tokens
170
152
 
@@ -184,8 +166,7 @@ dark mode.
184
166
  | `--blume-font-body` | Body / UI font |
185
167
  | `--blume-font-mono` | Code font |
186
168
 
187
- Set a `--blume-font-*` token to any font stack to use a font outside the curated
188
- list, or to fall back to the system stack:
169
+ Set a `--blume-font-*` token to any font stack to use a font outside the curated list, or to fall back to the system stack:
189
170
 
190
171
  ```css theme.css lineNumbers
191
172
  :root {
@@ -195,10 +176,7 @@ list, or to fall back to the system stack:
195
176
 
196
177
  ## Tailwind utilities
197
178
 
198
- Blume's theme is built with Tailwind v4 internally, and your project's `.astro`,
199
- `.tsx`, and `.jsx` files are scanned too — so you can style custom components and
200
- pages with utility classes, no Tailwind setup required. Every token is exposed as
201
- a utility, so your components track the theme automatically:
179
+ Blume's theme is built with Tailwind v4 internally, and your project's `.astro`, `.tsx`, and `.jsx` files are scanned too — so you can style custom components and pages with utility classes, no Tailwind setup required. Every token is exposed as a utility, so your components track the theme automatically:
202
180
 
203
181
  | Token | Utilities |
204
182
  | --------------------------- | -------------------------- |