blume 1.2.0 → 1.3.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 (77) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/cli/index.js +1715 -539
  3. package/dist/cli/index.js.map +40 -31
  4. package/dist/types/core/config-input.d.ts +131 -11
  5. package/dist/types/core/config.d.ts +9 -1
  6. package/dist/types/core/data.d.ts +24 -5
  7. package/dist/types/core/i18n-ui.d.ts +58 -799
  8. package/dist/types/core/schema.d.ts +534 -3305
  9. package/dist/types/theme/fonts.d.ts +55 -11
  10. package/docs/02-deployment.mdx +2 -0
  11. package/docs/07-faq.mdx +14 -14
  12. package/docs/advanced/skills.mdx +2 -2
  13. package/docs/configuration/ai.mdx +126 -2
  14. package/docs/configuration/index.mdx +19 -1
  15. package/docs/configuration/search.mdx +17 -0
  16. package/docs/configuration/seo.mdx +26 -3
  17. package/docs/configuration/theming.mdx +44 -2
  18. package/docs/content/syntax.mdx +18 -2
  19. package/docs/reference/cli.mdx +3 -3
  20. package/package.json +9 -8
  21. package/skills/blume/SKILL.md +6 -4
  22. package/skills/blume-migrate/SKILL.md +5 -3
  23. package/skills/blume-migrate/references/mintlify.md +5 -5
  24. package/skills/blume-migrate/references/monorepo.md +2 -1
  25. package/src/ai/agent-readability.ts +31 -1
  26. package/src/ai/api-catalog.ts +81 -0
  27. package/src/ai/ask-context.ts +7 -1
  28. package/src/ai/ask-data.ts +1 -0
  29. package/src/ai/link-headers.ts +52 -0
  30. package/src/ai/llms.ts +12 -1
  31. package/src/ai/markdown.ts +15 -2
  32. package/src/ai/mcp/data.ts +7 -0
  33. package/src/ai/mcp/discovery.ts +70 -15
  34. package/src/ai/mcp/server.ts +14 -8
  35. package/src/ai/mcp/stdio.ts +4 -1
  36. package/src/ai/skills.ts +193 -0
  37. package/src/ai/tar.ts +104 -0
  38. package/src/ai/web-bot-auth.ts +30 -0
  39. package/src/astro/generate.ts +116 -6
  40. package/src/astro/integration.ts +52 -14
  41. package/src/astro/templates.ts +191 -37
  42. package/src/audit/catalog.ts +20 -0
  43. package/src/audit/checks/dns-aid.ts +190 -0
  44. package/src/audit/report.ts +5 -0
  45. package/src/audit/run.ts +2 -0
  46. package/src/cli/commands/build.ts +178 -9
  47. package/src/cli/init/scaffold.ts +1 -1
  48. package/src/components/islands/ask-ai.tsx +4 -1
  49. package/src/components/islands/webmcp.ts +203 -0
  50. package/src/components/layout/NavTree.astro +4 -4
  51. package/src/components/layout/PageLayout.astro +2 -0
  52. package/src/components/layout/ReferenceLayout.astro +2 -0
  53. package/src/components/layout/RootLayout.astro +63 -11
  54. package/src/components/layout/Search.astro +2 -2
  55. package/src/components/layout/WebMcp.astro +49 -0
  56. package/src/components/layout/search/orama.ts +5 -2
  57. package/src/core/config-input.ts +143 -11
  58. package/src/core/config.ts +17 -1
  59. package/src/core/content-assets.ts +199 -0
  60. package/src/core/data.ts +21 -5
  61. package/src/core/diagnostics.ts +6 -5
  62. package/src/core/i18n-ui.ts +19 -28
  63. package/src/core/project-graph.ts +6 -0
  64. package/src/core/schema.ts +224 -71
  65. package/src/core/sources/normalize.ts +5 -5
  66. package/src/deploy/headers.ts +45 -3
  67. package/src/deploy/vercel-negotiation.ts +233 -0
  68. package/src/markdown/mermaid.ts +7 -1
  69. package/src/markdown/table-wrap.ts +33 -1
  70. package/src/og/card.ts +91 -22
  71. package/src/og/derive.ts +200 -0
  72. package/src/og/index.ts +6 -1
  73. package/src/search/orama-index.ts +151 -7
  74. package/src/theme/entry.ts +34 -13
  75. package/src/theme/fonts.ts +183 -30
  76. package/dist/types/og/card.d.ts +0 -63
  77. package/dist/types/og/dimensions.d.ts +0 -12
@@ -330,14 +330,50 @@ export interface NavigationConfig {
330
330
  /** Top-level tabs shown in the header. */
331
331
  tabs?: NavTab[];
332
332
  }
333
- /** The three type roles, each a curated Google Font slug. */
333
+ /** Fallback stack category for a custom font. */
334
+ export type FontFallback = "sans" | "serif" | "mono";
335
+ /**
336
+ * Any family from a zero-config Astro font provider, by name. Self-hosted and
337
+ * optimized like the curated slugs.
338
+ */
339
+ export interface RemoteFontInput {
340
+ /** Fallback stack. Defaults to `mono` for the mono role, `sans` otherwise. */
341
+ fallback?: FontFallback;
342
+ /** Family name as the provider lists it, e.g. `"Noto Sans JP"`. */
343
+ name: string;
344
+ /** Which provider serves the family. Defaults to `google`. */
345
+ provider?: "google" | "fontsource" | "bunny" | "fontshare";
346
+ /** Weights (or variable ranges like `"100..900"`) to load. Defaults to `[400, 500, 600, 700]`. */
347
+ weights?: (number | string)[];
348
+ }
349
+ /** One local `@font-face`: a file plus optional weight/style (else inferred). */
350
+ export interface LocalFontVariantInput {
351
+ /** Font file path, relative to the project root. */
352
+ src: string;
353
+ /** Face style; inferred from the file when omitted. */
354
+ style?: "normal" | "italic" | "oblique";
355
+ /** Face weight (a number or `"100..900"` range); inferred when omitted. */
356
+ weight?: number | string;
357
+ }
358
+ /** A self-hosted family loaded from font files in the project. */
359
+ export interface LocalFontInput {
360
+ /** Fallback stack. Defaults to `mono` for the mono role, `sans` otherwise. */
361
+ fallback?: FontFallback;
362
+ /** Family name used in CSS and the OG card. */
363
+ name: string;
364
+ /** The faces to declare (at least one). */
365
+ variants: LocalFontVariantInput[];
366
+ }
367
+ /** A role's font: curated slug, remote-provider family, or local files. */
368
+ export type FontInput = LiteralUnion<FontSlug> | RemoteFontInput | LocalFontInput;
369
+ /** The three type roles: a curated slug, any provider family, or local files. */
334
370
  export interface FontsConfig {
335
371
  /** Body / prose font. Defaults to `inter`. */
336
- body?: LiteralUnion<FontSlug>;
372
+ body?: FontInput;
337
373
  /** Display / heading font. Defaults to `inter-tight`. */
338
- display?: LiteralUnion<FontSlug>;
374
+ display?: FontInput;
339
375
  /** Monospace / code font. Defaults to `ibm-plex-mono`. */
340
- mono?: LiteralUnion<FontSlug>;
376
+ mono?: FontInput;
341
377
  }
342
378
  /** Colors, fonts, radius, and color-mode behavior. */
343
379
  /** Corner radius scale (`none`/`sm` tighter, `md`/`lg` rounder). */
@@ -524,6 +560,39 @@ export interface AiConfig {
524
560
  markdownComponents?: Record<string, ComponentMarkdown>;
525
561
  /** Expose the docs as an MCP server for agents. */
526
562
  mcp?: McpConfig;
563
+ /**
564
+ * Publish Agent Skills for discovery: a directory (resolved against the
565
+ * project root) whose subdirectories each hold a `SKILL.md`. Skills are
566
+ * copied under `/.well-known/agent-skills/` — single-file skills verbatim,
567
+ * skills with supporting resources as `.tar.gz` archives — and enumerated
568
+ * in a discovery index with SHA-256 digests (Agent Skills Discovery RFC).
569
+ *
570
+ * ```ts
571
+ * ai: {
572
+ * skills: "./skills",
573
+ * }
574
+ * ```
575
+ */
576
+ skills?: string;
577
+ /**
578
+ * Web Bot Auth: publish the org's HTTP Message Signature public keys at
579
+ * `/.well-known/http-message-signatures-directory`, so sites receiving
580
+ * requests from your agents can verify them. Public keys only — a key
581
+ * containing private material (`d`, `p`, `q`, …) is rejected.
582
+ */
583
+ webBotAuth?: WebBotAuthConfig;
584
+ /**
585
+ * WebMCP: register in-page tools (search, page Markdown, the docs index)
586
+ * on the browser's model context, so agentic browsers can drive the docs
587
+ * without a separate MCP connection. The script is tiny and no-ops in
588
+ * browsers without the API. Defaults to `true`; set `false` to opt out.
589
+ */
590
+ webmcp?: boolean;
591
+ }
592
+ /** Web Bot Auth signature directory. Off until at least one key is listed. */
593
+ export interface WebBotAuthConfig {
594
+ /** Public JWKs to publish (e.g. an Ed25519 key: `kty: "OKP"`, `crv: "Ed25519"`, `x: …`). */
595
+ keys?: Record<string, unknown>[];
527
596
  }
528
597
  /** An arbitrary analytics `<script>`; set exactly one of `src` or `content`. */
529
598
  export interface AnalyticsScript {
@@ -601,6 +670,32 @@ export interface DeploymentConfig {
601
670
  */
602
671
  site?: string;
603
672
  }
673
+ /**
674
+ * One authorized remote image source, passed through to Astro's
675
+ * `image.remotePatterns`. Hostnames accept `*.` (one level) and `**.` (any
676
+ * depth) wildcards; pathnames accept `/dir/*` and `/dir/**` the same way.
677
+ */
678
+ export interface ImageRemotePattern {
679
+ /** Hostname pattern, e.g. `"**.example.com"`. */
680
+ hostname?: string;
681
+ /** Pathname pattern, e.g. `"/images/**"`. */
682
+ pathname?: string;
683
+ /** Port, e.g. `"8080"`. */
684
+ port?: string;
685
+ /** URL scheme, e.g. `"https"`. */
686
+ protocol?: string;
687
+ }
688
+ /**
689
+ * Image optimization. Local images referenced by relative path are optimized
690
+ * automatically; remote images are only optimized when their host is
691
+ * authorized here. Both fields map directly onto Astro's `image` config.
692
+ */
693
+ export interface ImageConfig {
694
+ /** Hosts whose remote images may be optimized, e.g. `["cdn.example.com"]`. */
695
+ domains?: string[];
696
+ /** Pattern-based host authorization, for wildcards `domains` can't express. */
697
+ remotePatterns?: ImageRemotePattern[];
698
+ }
604
699
  /** HTTP redirect status codes: permanent (301/308) and temporary (302/307). */
605
700
  type RedirectStatusPermanent = 301 | 308;
606
701
  type RedirectStatusTemporary = 302 | 307;
@@ -651,6 +746,11 @@ export interface OgPaletteConfig {
651
746
  }
652
747
  /** Per-page Open Graph image generation. */
653
748
  export interface OgConfig {
749
+ /**
750
+ * Card subtitle. Defaults to the site description; a string overrides it,
751
+ * `false` renders the card without one.
752
+ */
753
+ description?: string | false;
654
754
  /**
655
755
  * Generate an OG image per page. Defaults to on once a deployment `site`
656
756
  * URL is known and off otherwise (`og:image` must be absolute). An explicit
@@ -658,21 +758,39 @@ export interface OgConfig {
658
758
  */
659
759
  enabled?: boolean;
660
760
  /**
661
- * Google Font families for the generated card, extending Takumi's Latin-only
662
- * default so non-Latin titles (CJK, and so on) render instead of tofu.
663
- * Fetched from Google Fonts at build. A bare string loads the family's
664
- * default weights; the object form pins weights (`700`, `[400, 700]`, or a
665
- * `"100..900"` variable range) and styles.
761
+ * Fonts for the generated card, extending Takumi's Latin-only default so
762
+ * non-Latin titles (CJK, and so on) render instead of tofu. A bare string is
763
+ * a Google Fonts family fetched at build; the name-only object form pins
764
+ * weights (`700`, `[400, 700]`, or a `"100..900"` variable range) and
765
+ * styles; the `src` form reads a local font file from the project instead.
766
+ * When omitted and `theme.fonts` is explicitly configured, the theme's
767
+ * display and body fonts are used automatically — pass `[]` to opt out.
666
768
  */
667
769
  fonts?: (string | {
668
770
  name: string;
669
771
  style?: "normal" | "italic" | ("normal" | "italic")[];
670
772
  weight?: number | number[] | string;
773
+ } | {
774
+ /** Family name registered for the file's faces. */
775
+ name: string;
776
+ /** Font file path, relative to the project root. */
777
+ src: string;
778
+ style?: "normal" | "italic";
779
+ weight?: number;
671
780
  })[];
672
- /** Local SVG used in the generated card instead of the site logo. */
673
- logo?: string;
781
+ /**
782
+ * Local SVG used in the generated card instead of the site logo; `false`
783
+ * renders the card without any brand mark.
784
+ */
785
+ logo?: string | false;
674
786
  /** Optional generated-card colors. */
675
787
  palette?: OgPaletteConfig;
788
+ /**
789
+ * Footer site text. Defaults to the deployment site's host plus
790
+ * `deployment.base` (`docs.acme.com`, `user.github.io/repo`); a string
791
+ * overrides it, `false` hides it.
792
+ */
793
+ site?: string | false;
676
794
  /**
677
795
  * Card headlines for custom `.astro` pages, keyed by route (`"/"`, `"/cli"`).
678
796
  * A custom page has no frontmatter to read, so its card is otherwise titled
@@ -977,6 +1095,8 @@ export interface BlumeConfig {
977
1095
  github?: GithubConfig;
978
1096
  /** Internationalization (opt-in multi-locale). */
979
1097
  i18n?: I18nConfig;
1098
+ /** Image optimization: remote-host authorization for the image service. */
1099
+ image?: ImageConfig;
980
1100
  /** Astro integrations appended after Blume's built-ins, in declaration order. */
981
1101
  integrations?: AstroIntegration[];
982
1102
  /** "Last updated" timestamps from git history or frontmatter. Defaults to `false`. */
@@ -47,7 +47,8 @@ import type { Diagnostic } from "./types.ts";
47
47
  * and the header repo link.
48
48
  *
49
49
  * **Appearance**
50
- * - `theme` — `accent` color, `fonts` (curated Google Font slugs), `radius`,
50
+ * - `theme` — `accent` color, `fonts` (curated slugs, any provider family, or
51
+ * local font files), `radius`,
51
52
  * `mode` (`system`/`light`/`dark`), and `background`.
52
53
  * - `markdown` — `code` (language icons, inline highlighting, line wrap),
53
54
  * `headingAnchors`, `imageZoom`, and opt-in KaTeX `math`.
@@ -140,6 +141,13 @@ export interface ConfigLoadResult {
140
141
  /** Absolute path of the config file used, or null when defaults were used. */
141
142
  configFile: string | null;
142
143
  diagnostics: Diagnostic[];
144
+ /**
145
+ * Whether the config file set `theme.fonts` itself. The schema always fills
146
+ * the roles with defaults, so the resolved config can't tell an intentional
147
+ * font choice from the fallback — and only intentional choices should flow
148
+ * into derived surfaces like OG card fonts.
149
+ */
150
+ themeFontsConfigured: boolean;
143
151
  }
144
152
  /**
145
153
  * Load and validate the project config. When no config file exists, schema
@@ -1,4 +1,3 @@
1
- import type { OgFont } from "../og/card.ts";
2
1
  import type { UIStrings } from "./i18n-ui.ts";
3
2
  import type { ResolvedConfig, SearchProvider } from "./schema.ts";
4
3
  import type { Navigation, RouteAlternate } from "./types.ts";
@@ -119,13 +118,25 @@ export interface BlumeDataConfig {
119
118
  name: string;
120
119
  route: string;
121
120
  } | null;
122
- /** Open Graph image generation. */
121
+ /**
122
+ * Open Graph image generation. Card fonts are baked into the generated OG
123
+ * endpoint (they can carry absolute build-machine paths) and deliberately
124
+ * kept out of this snapshot, which pages serialize into HTML.
125
+ */
123
126
  og: {
127
+ /** Card subtitle: `seo.og.description` (`false` omits it) over the site description. */
128
+ description?: string;
124
129
  enabled: boolean;
125
- /** Extra Google Font family specs for the card renderer, fetched at build. */
126
- fonts?: OgFont[];
127
- logo?: string;
130
+ /** Inlined SVG brand mark; `false` renders the card without any mark. */
131
+ logo?: string | false;
128
132
  palette?: ResolvedConfig["seo"]["og"]["palette"];
133
+ /**
134
+ * Footer site text: `seo.og.site` if set (`false` hides it), otherwise
135
+ * the deployment site's host plus `deployment.base` (`docs.acme.com`,
136
+ * `user.github.io/repo`) — so a subpath deploy's card names the actual
137
+ * site rather than the platform's shared apex host.
138
+ */
139
+ site?: string;
129
140
  };
130
141
  /** Repository URL for header/edit links, or `null`. */
131
142
  repoUrl: string | null;
@@ -146,6 +157,14 @@ export interface BlumeDataConfig {
146
157
  title: string;
147
158
  /** Table-of-contents settings: whether to show it and the heading range. */
148
159
  toc: ResolvedConfig["toc"];
160
+ /**
161
+ * WebMCP in-page tools (`ai.webmcp`), plus whether llms.txt exists for the
162
+ * list tool to fetch (`ai.llmsTxt.enabled`).
163
+ */
164
+ webmcp: {
165
+ enabled: boolean;
166
+ llms: boolean;
167
+ };
149
168
  /** X (Twitter) attribution: the site's account, and a default creator. */
150
169
  x: {
151
170
  creator?: string;