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.
- package/dist/cli/index.js +1631 -940
- package/dist/cli/index.js.map +62 -50
- package/dist/types/core/data.d.ts +2 -0
- package/dist/types/core/project.d.ts +12 -2
- package/dist/types/core/schema.d.ts +442 -292
- package/dist/types/core/types.d.ts +7 -0
- package/dist/types/migrate/mintlify/assets.d.ts +8 -0
- package/docs/01-quickstart.mdx +5 -16
- package/docs/02-deployment.mdx +21 -54
- package/docs/advanced/api-reference.mdx +34 -51
- package/docs/advanced/blog.mdx +9 -25
- package/docs/advanced/bridge.mdx +74 -0
- package/docs/advanced/changelog.mdx +10 -33
- package/docs/advanced/custom-pages.mdx +21 -78
- package/docs/advanced/meta.ts +8 -1
- package/docs/advanced/migrate.mdx +119 -0
- package/docs/configuration/ai.mdx +42 -103
- package/docs/configuration/analytics.mdx +20 -38
- package/docs/configuration/customization.mdx +40 -73
- package/docs/configuration/export.mdx +9 -34
- package/docs/configuration/index.mdx +67 -87
- package/docs/configuration/search.mdx +17 -54
- package/docs/configuration/seo.mdx +17 -48
- package/docs/configuration/theming.mdx +20 -42
- package/docs/content/components.mdx +95 -101
- package/docs/content/i18n.mdx +21 -72
- package/docs/content/index.mdx +18 -48
- package/docs/content/islands.mdx +25 -52
- package/docs/content/meta.mdx +23 -50
- package/docs/content/navigation.mdx +23 -62
- package/docs/content/sources.mdx +20 -83
- package/docs/content/syntax.mdx +37 -105
- package/docs/index.mdx +12 -41
- package/docs/reference/cli.mdx +47 -30
- package/docs/reference/frontmatter.mdx +7 -5
- package/package.json +11 -1
- package/src/astro/generate.ts +18 -8
- package/src/astro/integration.ts +26 -3
- package/src/astro/islands.ts +6 -2
- package/src/astro/markdown-negotiation.ts +17 -3
- package/src/astro/pages.ts +6 -1
- package/src/astro/static-assets.ts +117 -0
- package/src/astro/templates.ts +76 -30
- package/src/cli/args.ts +23 -0
- package/src/cli/commands/build.ts +129 -62
- package/src/cli/commands/check.ts +20 -0
- package/src/cli/commands/dev.ts +11 -2
- package/src/cli/commands/doctor.ts +10 -1
- package/src/cli/commands/eject.ts +3 -1
- package/src/cli/commands/init.ts +21 -1
- package/src/cli/commands/preview.ts +2 -1
- package/src/cli/commands/validate.ts +12 -1
- package/src/cli/dev-lock.ts +92 -0
- package/src/cli/log.ts +11 -0
- package/src/cli/prepare.ts +3 -0
- package/src/components/BlumePage.astro +8 -0
- package/src/components/Icon.astro +13 -10
- package/src/components/content/ApiField.astro +75 -0
- package/src/components/content/ParamField.astro +39 -0
- package/src/components/content/RequestField.astro +23 -0
- package/src/components/content/ResponseField.astro +23 -0
- package/src/components/content/Step.astro +1 -1
- package/src/components/content/YouTube.astro +35 -0
- package/src/components/content/youtube.ts +46 -0
- package/src/components/islands/ask-ai.tsx +14 -14
- package/src/components/layout/Breadcrumbs.astro +7 -2
- package/src/components/layout/NavTree.astro +24 -8
- package/src/components/layout/RootLayout.astro +56 -34
- package/src/components/layout/Search.astro +1 -1
- package/src/components/openapi/ApiOverview.astro +84 -0
- package/src/components/openapi/MethodBadge.astro +28 -0
- package/src/components/openapi/Operation.astro +140 -0
- package/src/components/openapi/ParametersTable.astro +97 -0
- package/src/components/openapi/RequestBody.astro +58 -0
- package/src/components/openapi/RequestPanel.astro +169 -0
- package/src/components/openapi/Responses.astro +91 -0
- package/src/components/openapi/SchemaProperty.astro +118 -0
- package/src/components/openapi/SchemaTable.astro +86 -0
- package/src/components/openapi/helpers.ts +238 -0
- package/src/components/openapi/panel.ts +59 -0
- package/src/components/openapi/snippets.ts +201 -0
- package/src/components/props.ts +3 -0
- package/src/core/assets.ts +31 -0
- package/src/core/bridge.ts +10 -0
- package/src/core/builtin-tags.ts +6 -0
- package/src/core/data.ts +2 -0
- package/src/core/diagnostics.ts +6 -1
- package/src/core/gitignore.ts +30 -0
- package/src/core/links.ts +60 -19
- package/src/core/project-graph.ts +5 -1
- package/src/core/project.ts +25 -3
- package/src/core/schema.ts +54 -6
- package/src/core/sources/mdx-remote.ts +54 -8
- package/src/core/sources/mintlify.ts +1 -1
- package/src/core/sources/normalize.ts +6 -1
- package/src/core/sources/notion.ts +49 -5
- package/src/core/sources/resolve.ts +28 -6
- package/src/core/sources/sanity.ts +5 -1
- package/src/core/types.ts +7 -0
- package/src/deploy/rss.ts +1 -8
- package/src/deploy/sitemap.ts +20 -1
- package/src/deploy/xml.ts +8 -0
- package/src/markdown/directives.ts +15 -7
- package/src/markdown/package-commands.ts +26 -4
- package/src/migrate/fumadocs/content.ts +14 -1
- package/src/migrate/fumadocs/groups.ts +7 -0
- package/src/migrate/fumadocs/index.ts +5 -2
- package/src/migrate/mintlify/assets.ts +46 -0
- package/src/migrate/mintlify/config.ts +153 -1
- package/src/migrate/mintlify/content.ts +8 -2
- package/src/migrate/mintlify/index.ts +111 -46
- package/src/migrate/shared.ts +12 -27
- package/src/og/card.ts +14 -2
- package/src/openapi/model.ts +174 -0
- package/src/openapi/parse.ts +48 -0
- package/src/openapi/references.ts +164 -0
- package/src/openapi/render-mdx.ts +76 -0
- package/src/openapi/scalar.ts +15 -103
- package/src/openapi/source.ts +140 -0
- package/src/registry/eject.ts +28 -5
- package/src/registry/registry.ts +6 -0
- package/src/registry/rewrite-imports.ts +31 -19
- package/src/search/documents.ts +23 -5
- package/src/search/sync/algolia.ts +5 -1
- package/src/search/sync/typesense.ts +24 -16
- package/src/theme/chrome-icons.ts +22 -0
- package/src/theme/icons.ts +151 -161
- package/src/theme/palette.ts +26 -7
|
@@ -44,6 +44,13 @@ export interface ProjectContext {
|
|
|
44
44
|
pagesRoot: string | null;
|
|
45
45
|
/** Absolute path to the generated runtime (`<root>/.blume`). */
|
|
46
46
|
outDir: string;
|
|
47
|
+
/**
|
|
48
|
+
* Absolute path to the Astro build output. `<root>/dist` normally; for a
|
|
49
|
+
* relocated runtime (isolated verify build) it lives under the runtime dir so
|
|
50
|
+
* it never empties the real `dist/`. Optional so hand-built test contexts and
|
|
51
|
+
* older callers still typecheck; `resolveProjectContext` always sets it.
|
|
52
|
+
*/
|
|
53
|
+
distDir?: string;
|
|
47
54
|
/** Absolute path to the user `theme.css`, if present. */
|
|
48
55
|
themeFile: string | null;
|
|
49
56
|
/** Absolute path to the user `components.ts`/`.tsx`, if present. */
|
|
@@ -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[];
|
package/docs/01-quickstart.mdx
CHANGED
|
@@ -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
|
|
package/docs/02-deployment.mdx
CHANGED
|
@@ -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,31 +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`). Server builds
|
|
122
|
-
handle redirects at request time. Static builds emit redirect pages **and**
|
|
123
|
-
platform files so your host issues a real HTTP redirect: `_redirects` (Netlify,
|
|
124
|
-
Cloudflare Pages), `vercel.json` (Vercel), and `blume-redirects.json` — a
|
|
125
|
-
structured manifest for anything else (nginx/Apache rules, an edge worker). A
|
|
126
|
-
`_redirects` or `vercel.json` you ship in `public/` is left untouched.
|
|
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.
|
|
127
100
|
|
|
128
101
|
## Environment variables
|
|
129
102
|
|
|
130
|
-
When a feature needs a runtime secret, Blume warns at `blume dev`/`build` if it's
|
|
131
|
-
missing — so the problem surfaces early instead of at the first request:
|
|
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:
|
|
132
104
|
|
|
133
|
-
| Feature
|
|
134
|
-
|
|
|
135
|
-
| Ask AI (AI Gateway)
|
|
136
|
-
| Ask AI (OpenRouter / OpenAI-compatible) | the provider's `apiKeyEnv`
|
|
137
|
-
| Mixedbread search
|
|
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` |
|
|
138
110
|
|
|
139
|
-
Set them in `.env.local` for local dev and in your host's environment for
|
|
140
|
-
production. Build-time secrets for search-index sync (Algolia, Orama Cloud,
|
|
141
|
-
Typesense) are warned about separately during the sync step.
|
|
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.
|
|
142
112
|
|
|
143
113
|
## Build summary
|
|
144
114
|
|
|
145
|
-
Every build prints a summary — output mode, adapter, resolved site URL, search
|
|
146
|
-
provider, redirect count, sitemap and `llms.txt` status, and any enabled server
|
|
147
|
-
features — so you can confirm what shipped (including anything auto-detected)
|
|
148
|
-
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.
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: OpenAPI / AsyncAPI
|
|
3
|
-
description: Drop in an OpenAPI
|
|
3
|
+
description: Drop in an OpenAPI spec and get a native API reference — one real page per operation, in your sidebar and search.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Point Blume at an OpenAPI
|
|
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 spec and it generates a native API reference: one **real page per operation**, grouped by tag in a tab-scoped sidebar, with schema tables, request/response examples, and generated code samples. Because each operation is a genuine Blume page, it gets its own URL, shows up in **site search** and `llms.txt`, and gets an Open Graph image — the same as any hand-written doc.
|
|
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
|
|
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` (an overview page) with each operation at `/reference/<tag>/<operation>`, and adds a header tab. The `spec` is either an `http(s)` URL or a path to a local file in your project. Blume parses it with [Scalar's OpenAPI parser](https://github.com/scalar/scalar) — Swagger 2.0 and OpenAPI 3.0 specs are upgraded to 3.1 automatically.
|
|
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 Operations are indexed for search by their **summary and tag**. The rendered schema tables and code samples aren't full-text indexed; search matches an operation's title and section, then links to its own page. :::
|
|
28
18
|
|
|
29
19
|
## A local spec
|
|
30
20
|
|
|
31
|
-
A relative path is resolved from your project root and
|
|
32
|
-
nothing is copied into your source tree and the page works offline:
|
|
21
|
+
A relative path is resolved from your project root and read at build time. Both JSON and YAML work:
|
|
33
22
|
|
|
34
23
|
```ts blume.config.ts lineNumbers
|
|
35
24
|
openapi: {
|
|
@@ -38,25 +27,34 @@ openapi: {
|
|
|
38
27
|
}
|
|
39
28
|
```
|
|
40
29
|
|
|
41
|
-
Both JSON and YAML specs work; Scalar auto-detects the format.
|
|
42
|
-
|
|
43
30
|
## Route
|
|
44
31
|
|
|
45
|
-
`route` controls where the reference mounts (and the header
|
|
32
|
+
`route` controls where the reference mounts — the overview page and the prefix for every operation route (and the header tab's target):
|
|
46
33
|
|
|
47
34
|
```ts blume.config.ts lineNumbers
|
|
48
35
|
openapi: {
|
|
49
36
|
enabled: true,
|
|
50
|
-
route: "/api",
|
|
37
|
+
route: "/api", // overview at /api, operations at /api/<tag>/<operation>
|
|
51
38
|
spec: "./openapi.yaml",
|
|
52
39
|
}
|
|
53
40
|
```
|
|
54
41
|
|
|
42
|
+
## Code samples and schemas
|
|
43
|
+
|
|
44
|
+
`codeSamples` picks which languages render per operation (built in: `curl`, `js`, `python`); `expandSchemas` starts nested schema rows expanded rather than collapsed:
|
|
45
|
+
|
|
46
|
+
```ts blume.config.ts lineNumbers
|
|
47
|
+
openapi: {
|
|
48
|
+
enabled: true,
|
|
49
|
+
spec: "./openapi.yaml",
|
|
50
|
+
codeSamples: ["curl", "js"],
|
|
51
|
+
expandSchemas: true,
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
55
|
## Multiple specs
|
|
56
56
|
|
|
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`:
|
|
57
|
+
Use `sources` to publish more than one spec. Each source gets its own overview route, operation pages, and header tab. Give each a `label` (used for the tab and to derive its route), or set an explicit `route`:
|
|
60
58
|
|
|
61
59
|
```ts blume.config.ts lineNumbers
|
|
62
60
|
openapi: {
|
|
@@ -68,47 +66,32 @@ openapi: {
|
|
|
68
66
|
}
|
|
69
67
|
```
|
|
70
68
|
|
|
71
|
-
`spec` is shorthand for a single-entry `sources`, so you only reach for `sources`
|
|
72
|
-
when you have more than one.
|
|
69
|
+
`spec` is shorthand for a single-entry `sources`, so you only reach for `sources` when you have more than one.
|
|
73
70
|
|
|
74
|
-
##
|
|
71
|
+
## The Scalar renderer
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
renders AsyncAPI through the same component. Only the default route differs
|
|
78
|
-
(`/events`):
|
|
73
|
+
The native renderer is the default. If you'd rather embed [Scalar](https://scalar.com)'s self-contained API reference — its own sidebar, search, theme, and "Try it" playground on a single route — set `renderer: "scalar"`:
|
|
79
74
|
|
|
80
75
|
```ts blume.config.ts lineNumbers
|
|
81
|
-
|
|
76
|
+
openapi: {
|
|
82
77
|
enabled: true,
|
|
83
|
-
|
|
78
|
+
renderer: "scalar",
|
|
79
|
+
spec: "./openapi.yaml",
|
|
80
|
+
theme: "purple", // a Scalar theme name (Scalar renderer only)
|
|
84
81
|
}
|
|
85
82
|
```
|
|
86
83
|
|
|
87
|
-
|
|
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
|
-
:::
|
|
84
|
+
A Scalar-rendered reference is a self-contained embed on its own route — it doesn't weave into Blume's sidebar, search, or `llms.txt`. Its "Try it" playground calls your **target API directly from the browser** (Blume doesn't proxy), so the API must allow cross-origin requests from the docs site (`Access-Control-Allow-Origin`). `theme` and the playground apply to the Scalar renderer only.
|
|
92
85
|
|
|
93
|
-
##
|
|
86
|
+
## AsyncAPI
|
|
94
87
|
|
|
95
|
-
|
|
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`:
|
|
88
|
+
Event-driven APIs use a sibling `asyncapi` block with the same shape. AsyncAPI is rendered by Scalar (the native renderer is OpenAPI-only for now); only the default route differs (`/events`):
|
|
99
89
|
|
|
100
90
|
```ts blume.config.ts lineNumbers
|
|
101
|
-
|
|
91
|
+
asyncapi: {
|
|
102
92
|
enabled: true,
|
|
103
|
-
spec: "./
|
|
104
|
-
theme: "purple",
|
|
93
|
+
spec: "./asyncapi.yaml",
|
|
105
94
|
}
|
|
106
95
|
```
|
|
107
96
|
|
|
108
|
-
|
|
109
|
-
|
|
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.
|
|
97
|
+
:::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. :::
|
package/docs/advanced/blog.mdx
CHANGED
|
@@ -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">
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Bridge
|
|
3
|
+
description: Run blume dev directly on a Mintlify codebase — no config, no migration, no file changes. Blume detects docs.json and serves it in place.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Bridge mode lets you point Blume at a **Mintlify** project and run it as-is. There's no config to write and no migration to commit: drop `blume dev` into a directory that has a `docs.json` (or legacy `mint.json`) and Blume detects it, synthesizes an equivalent config in memory, and serves your existing MDX — transformed to Blume idiom on the fly, on disk untouched.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cd my-mintlify-docs
|
|
10
|
+
npx blume dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```txt
|
|
14
|
+
ℹ Detected docs.json — running in Mintlify bridge mode (no migration).
|
|
15
|
+
Run "blume migrate mintlify" to convert permanently.
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
It's the zero-commitment way to see what your docs look like on Blume — you can keep running `mintlify dev` in one terminal and `blume dev` in another, side by side, and decide later.
|
|
19
|
+
|
|
20
|
+
## When it activates
|
|
21
|
+
|
|
22
|
+
Bridge mode is entirely automatic, gated on two conditions:
|
|
23
|
+
|
|
24
|
+
- **No Blume config.** There's no `blume.config.{ts,js,mjs}` at the project root. An explicit Blume config always wins — the moment one exists, Blume runs a normal project and bridge mode never triggers.
|
|
25
|
+
- **A Mintlify config is present.** A `docs.json` or `mint.json` sits at the root.
|
|
26
|
+
|
|
27
|
+
With both true, Blume treats the Mintlify config as its source of truth for that run.
|
|
28
|
+
|
|
29
|
+
:::note Bridge mode applies to `blume build` too, not just `blume dev` — you can produce a static site from an unconverted Mintlify project. Only `blume dev` prints the detection notice. :::
|
|
30
|
+
|
|
31
|
+
## What happens under the hood
|
|
32
|
+
|
|
33
|
+
Bridge mode is the **read-only twin** of [`blume migrate mintlify`](/docs/advanced/migrate#mintlify): the same translation, without writing anything back.
|
|
34
|
+
|
|
35
|
+
- **Config is synthesized in memory.** `docs.json` is translated to a Blume config — navigation, theme, and chrome mapped across — exactly as the migrator would, but nothing is written to disk.
|
|
36
|
+
- **Content is served through a Mintlify source.** The config's content block is rewired to a single [`mintlify` content source](/docs/content/sources) rooted at the project. Each MDX page is transformed to Blume markup **at scan time** as it's read, so your files never change.
|
|
37
|
+
- **Variables are inlined at scan time.** `docs.json` `variables` (`{{name}}`) are substituted into content as it's scanned — Blume has no runtime substitution.
|
|
38
|
+
- **Assets are served in place.** Referenced folders like `images/` are served through [`content.assets`](/docs/content/sources) rather than moved to `public/`, so nothing is relocated.
|
|
39
|
+
- **Languages map to i18n.** A multi-language `docs.json` maps to Blume's [`i18n`](/docs/content/i18n), with the language switch handled by Blume's locale routing instead of a nav selector.
|
|
40
|
+
|
|
41
|
+
Because it reads the same `docs.json` and runs the same transforms, what you see in bridge mode is what you'd get from a full migration.
|
|
42
|
+
|
|
43
|
+
## Bridge vs. migrate
|
|
44
|
+
|
|
45
|
+
<CardGroup cols={2}>
|
|
46
|
+
<Card title="Bridge mode" icon="cable">
|
|
47
|
+
**Try Blume with zero changes.** Nothing is written; your Mintlify project
|
|
48
|
+
stays exactly as it is. Ideal for evaluating Blume, running both dev servers
|
|
49
|
+
side by side, or a reversible spike.
|
|
50
|
+
</Card>
|
|
51
|
+
<Card title="Migrate" href="/docs/advanced/migrate" icon="arrow-right">
|
|
52
|
+
**Convert for good.** [`blume migrate mintlify`](/docs/advanced/migrate)
|
|
53
|
+
rewrites your pages, config, and assets in place so Blume becomes the source
|
|
54
|
+
of truth. Do this once you've decided to switch.
|
|
55
|
+
</Card>
|
|
56
|
+
</CardGroup>
|
|
57
|
+
|
|
58
|
+
Everything you can do in bridge mode, you can do permanently by migrating — bridge is the preview, migrate is the commit.
|
|
59
|
+
|
|
60
|
+
## Limitations
|
|
61
|
+
|
|
62
|
+
- **Mintlify only.** Bridge detection is Mintlify-specific. The other frameworks — Fumadocs, Nextra, Starlight — need a [one-shot migration](/docs/advanced/migrate).
|
|
63
|
+
- **Same idiom gaps as the migrator.** Components without a Blume equivalent are transformed on a best-effort basis; when you hit one, [migrate](/docs/advanced/migrate) and address the warnings, or switch that page to a Blume-native equivalent such as the [OpenAPI reference](/docs/advanced/api-reference).
|
|
64
|
+
- **No runtime variables.** As with a migration, `{{variable}}` values are inlined at scan time rather than substituted at runtime.
|
|
65
|
+
|
|
66
|
+
<CardGroup cols={2}>
|
|
67
|
+
<Card title="Migrate" href="/docs/advanced/migrate" icon="arrow-right">
|
|
68
|
+
Convert a Mintlify, Fumadocs, Nextra, or Starlight project permanently.
|
|
69
|
+
</Card>
|
|
70
|
+
<Card title="Content sources" href="/docs/content/sources" icon="folder-tree">
|
|
71
|
+
How the `mintlify` source and `content.assets` fit into Blume's content
|
|
72
|
+
graph.
|
|
73
|
+
</Card>
|
|
74
|
+
</CardGroup>
|
|
@@ -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
|