blume 1.0.4 → 1.1.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 (106) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/cli/index.js +13255 -10232
  3. package/dist/cli/index.js.map +91 -60
  4. package/dist/types/core/config-input.d.ts +61 -1
  5. package/dist/types/core/data.d.ts +9 -0
  6. package/dist/types/core/deployment-env.d.ts +6 -0
  7. package/dist/types/core/diagnostics.d.ts +23 -0
  8. package/dist/types/core/i18n-ui.d.ts +8 -8
  9. package/dist/types/core/schema.d.ts +131 -22
  10. package/dist/types/core/sources/types.d.ts +3 -1
  11. package/dist/types/core/standard-schema.d.ts +41 -0
  12. package/dist/types/core/types.d.ts +13 -0
  13. package/dist/types/og/card.d.ts +63 -0
  14. package/dist/types/og/dimensions.d.ts +12 -0
  15. package/docs/01-quickstart.mdx +1 -1
  16. package/docs/02-deployment.mdx +9 -1
  17. package/docs/advanced/api-reference.mdx +11 -0
  18. package/docs/advanced/changelog.mdx +1 -1
  19. package/docs/advanced/skills.mdx +1 -1
  20. package/docs/configuration/ai.mdx +1 -1
  21. package/docs/configuration/customization.mdx +1 -1
  22. package/docs/configuration/export.mdx +1 -1
  23. package/docs/configuration/index.mdx +21 -1
  24. package/docs/configuration/search.mdx +28 -1
  25. package/docs/configuration/seo.mdx +21 -2
  26. package/docs/configuration/theming.mdx +1 -1
  27. package/docs/content/components.mdx +14 -0
  28. package/docs/content/index.mdx +1 -1
  29. package/docs/content/meta.mdx +1 -1
  30. package/docs/content/navigation.mdx +1 -1
  31. package/docs/content/sources.mdx +1 -1
  32. package/docs/reference/cli.mdx +79 -1
  33. package/docs/reference/frontmatter.mdx +29 -1
  34. package/package.json +3 -3
  35. package/skills/blume-migrate/SKILL.md +1 -1
  36. package/skills/blume-migrate/references/mintlify.md +3 -2
  37. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +16 -4
  38. package/src/ai/llms.ts +15 -0
  39. package/src/astro/adapter-root.ts +70 -0
  40. package/src/astro/generate.ts +50 -19
  41. package/src/astro/index.ts +1 -0
  42. package/src/astro/pages.ts +18 -3
  43. package/src/astro/templates.ts +65 -22
  44. package/src/audit/agent.ts +114 -0
  45. package/src/audit/catalog.ts +826 -0
  46. package/src/audit/checks/assets.ts +177 -0
  47. package/src/audit/checks/content.ts +231 -0
  48. package/src/audit/checks/duplicates.ts +131 -0
  49. package/src/audit/checks/i18n.ts +246 -0
  50. package/src/audit/checks/indexability.ts +213 -0
  51. package/src/audit/checks/links.ts +223 -0
  52. package/src/audit/checks/llms.ts +135 -0
  53. package/src/audit/checks/network.ts +272 -0
  54. package/src/audit/checks/og-image.ts +113 -0
  55. package/src/audit/checks/redirects.ts +87 -0
  56. package/src/audit/checks/robots.ts +114 -0
  57. package/src/audit/checks/sitemap.ts +229 -0
  58. package/src/audit/checks/social.ts +238 -0
  59. package/src/audit/crawl.ts +259 -0
  60. package/src/audit/graph.ts +74 -0
  61. package/src/audit/html.ts +54 -0
  62. package/src/audit/image-size.ts +63 -0
  63. package/src/audit/locate.ts +33 -0
  64. package/src/audit/redirects.ts +74 -0
  65. package/src/audit/report.ts +278 -0
  66. package/src/audit/run.ts +198 -0
  67. package/src/audit/snapshot.ts +189 -0
  68. package/src/audit/types.ts +214 -0
  69. package/src/audit/url.ts +103 -0
  70. package/src/cli/commands/audit.ts +205 -0
  71. package/src/cli/commands/build.ts +51 -12
  72. package/src/cli/index.ts +2 -0
  73. package/src/components/content/Tabs.astro +98 -15
  74. package/src/components/layout/Breadcrumbs.astro +1 -1
  75. package/src/components/layout/Header.astro +1 -0
  76. package/src/components/layout/PageFeedback.astro +1 -1
  77. package/src/components/layout/PageLayout.astro +5 -1
  78. package/src/components/layout/Pagination.astro +1 -1
  79. package/src/components/layout/RootLayout.astro +5 -3
  80. package/src/components/layout/Search.astro +35 -6
  81. package/src/components/layout/TableOfContents.astro +1 -1
  82. package/src/components/openapi/Authorization.astro +80 -0
  83. package/src/components/openapi/Operation.astro +19 -1
  84. package/src/components/openapi/ParametersTable.astro +1 -1
  85. package/src/components/openapi/security.ts +201 -0
  86. package/src/components/openapi/snippets.ts +42 -13
  87. package/src/core/config-input.ts +66 -1
  88. package/src/core/data.ts +9 -1
  89. package/src/core/deployment-env.ts +9 -0
  90. package/src/core/diagnostics.ts +59 -12
  91. package/src/core/links.ts +2 -91
  92. package/src/core/nav-diagnostics.ts +48 -4
  93. package/src/core/probe.ts +136 -0
  94. package/src/core/project-graph.ts +8 -0
  95. package/src/core/schema.ts +86 -3
  96. package/src/core/sources/normalize.ts +198 -25
  97. package/src/core/sources/types.ts +3 -1
  98. package/src/core/standard-schema.ts +54 -0
  99. package/src/core/types.ts +13 -0
  100. package/src/deploy/adapter-output.ts +27 -15
  101. package/src/deploy/headers.ts +66 -0
  102. package/src/deploy/redirects.ts +49 -9
  103. package/src/og/card.ts +98 -33
  104. package/src/og/index.ts +1 -1
  105. package/src/search/popular.ts +33 -0
  106. package/src/theme/entry.ts +6 -1
@@ -2,6 +2,7 @@ import type { ComponentMarkdown } from "../ai/component-markdown.ts";
2
2
  import type { FontSlug } from "../theme/fonts.ts";
3
3
  import type { OpenApiSource, SearchProvider, SidebarDisplay, SidebarItemConfig } from "./schema.ts";
4
4
  import type { ContentSource } from "./sources/types.ts";
5
+ import type { StandardSchema } from "./standard-schema.ts";
5
6
  /**
6
7
  * The public, hand-documented authoring type for `blume.config.ts`.
7
8
  *
@@ -382,6 +383,15 @@ export interface TypesenseSearch {
382
383
  export interface MixedbreadSearch {
383
384
  storeId: string;
384
385
  }
386
+ /** A curated link for the search dialog empty state. */
387
+ export interface SearchPopularLink {
388
+ /** Internal route or external URL. */
389
+ href: string;
390
+ /** Built-in icon name shown beside the label; defaults to the file glyph. */
391
+ icon?: string;
392
+ /** Link label shown in the dialog. */
393
+ label: string;
394
+ }
385
395
  /**
386
396
  * Search backend. The default `orama` builds a local index at build time (and
387
397
  * runs in dev); hosted providers need their credential block below. `none`
@@ -399,6 +409,11 @@ export interface SearchConfig {
399
409
  mixedbread?: MixedbreadSearch;
400
410
  /** Orama Cloud credentials (required when `provider` is `orama-cloud`). */
401
411
  oramaCloud?: OramaCloudSearch;
412
+ /**
413
+ * Curated links for the Cmd+K empty state. When omitted or empty, the first
414
+ * sidebar pages are shown instead.
415
+ */
416
+ popular?: SearchPopularLink[];
402
417
  /** Which backend powers search. Defaults to `orama`. */
403
418
  provider?: SearchProvider;
404
419
  /** Typesense credentials (required when `provider` is `typesense`). */
@@ -602,7 +617,7 @@ export interface RssConfig {
602
617
  /** Content types that each get a feed at `/<type>/rss.xml`. Defaults to blog + changelog. */
603
618
  types?: string[];
604
619
  }
605
- /** Colors used by generated Open Graph cards. Values must be hex colors. */
620
+ /** Colors used by generated Open Graph cards. Any CSS color hex, `oklch(…)`, `rgb(…)`, named. */
606
621
  export interface OgPaletteConfig {
607
622
  /** Fallback mark color. Defaults to the light theme accent. */
608
623
  accent?: string;
@@ -623,6 +638,18 @@ export interface OgConfig {
623
638
  * value always wins.
624
639
  */
625
640
  enabled?: boolean;
641
+ /**
642
+ * Google Font families for the generated card, extending Takumi's Latin-only
643
+ * default so non-Latin titles (CJK, and so on) render instead of tofu.
644
+ * Fetched from Google Fonts at build. A bare string loads the family's
645
+ * default weights; the object form pins weights (`700`, `[400, 700]`, or a
646
+ * `"100..900"` variable range) and styles.
647
+ */
648
+ fonts?: (string | {
649
+ name: string;
650
+ style?: "normal" | "italic" | ("normal" | "italic")[];
651
+ weight?: number | number[] | string;
652
+ })[];
626
653
  /** Local SVG used in the generated card instead of the site logo. */
627
654
  logo?: string;
628
655
  /** Optional generated-card colors. */
@@ -780,6 +807,37 @@ export type ExportConfig = boolean | {
780
807
  /** Offer PDF export (via print). Defaults to `false`. */
781
808
  pdf?: boolean;
782
809
  };
810
+ /**
811
+ * Opt-in custom frontmatter keys. Page frontmatter is strictly validated —
812
+ * an unknown key fails the build so typos are caught — and `extend` carves
813
+ * out project-specific keys from that rule, each validated by a schema you
814
+ * supply.
815
+ */
816
+ export interface FrontmatterConfig {
817
+ /**
818
+ * Extra frontmatter keys pages may carry, mapped to their validation
819
+ * schemas — any library implementing Standard Schema works (Zod — the
820
+ * version your project installs, 3.24+ or 4 — Valibot, ArkType):
821
+ *
822
+ * ```ts
823
+ * import { z } from "zod";
824
+ *
825
+ * frontmatter: {
826
+ * extend: {
827
+ * owner: z.string(),
828
+ * reviewedAt: z.coerce.date().optional(),
829
+ * },
830
+ * },
831
+ * ```
832
+ *
833
+ * Every declared key is validated on every page — absent ones included —
834
+ * so a required schema enforces the key site-wide; mark it `.optional()`
835
+ * to validate only when present. Validated values are preserved on each
836
+ * page record's `custom` field. Built-in frontmatter fields cannot be
837
+ * redeclared.
838
+ */
839
+ extend?: Record<string, StandardSchema>;
840
+ }
783
841
  /**
784
842
  * "Last updated" timestamps. `false` (default) disables them; `true` derives
785
843
  * each date from git history; the object form selects the source. A page's
@@ -843,6 +901,8 @@ export interface BlumeConfig {
843
901
  export?: ExportConfig;
844
902
  /** Show the per-page "Was this helpful?" widget. Defaults to `true`. */
845
903
  feedback?: boolean;
904
+ /** Opt-in custom frontmatter keys, validated by schemas you supply. */
905
+ frontmatter?: FrontmatterConfig;
846
906
  /** Source repository (Edit-this-page links and the header repo link). */
847
907
  github?: GithubConfig;
848
908
  /** Internationalization (opt-in multi-locale). */
@@ -1,3 +1,4 @@
1
+ import type { OgFont } from "../og/card.ts";
1
2
  import type { UIStrings } from "./i18n-ui.ts";
2
3
  import type { ResolvedConfig, SearchProvider } from "./schema.ts";
3
4
  import type { Navigation, RouteAlternate } from "./types.ts";
@@ -118,6 +119,8 @@ export interface BlumeDataConfig {
118
119
  /** Open Graph image generation. */
119
120
  og: {
120
121
  enabled: boolean;
122
+ /** Extra Google Font family specs for the card renderer, fetched at build. */
123
+ fonts?: OgFont[];
121
124
  logo?: string;
122
125
  palette?: ResolvedConfig["seo"]["og"]["palette"];
123
126
  };
@@ -125,6 +128,12 @@ export interface BlumeDataConfig {
125
128
  repoUrl: string | null;
126
129
  search: {
127
130
  enabled: boolean;
131
+ /** Resolved empty-state links; empty when unset (Search falls back to sidebar). */
132
+ popular: {
133
+ icon?: string;
134
+ label: string;
135
+ route: string;
136
+ }[];
128
137
  provider: SearchProvider;
129
138
  };
130
139
  /** Deployment site URL, or `null` when none is configured/detected. */
@@ -1,4 +1,10 @@
1
1
  import type { ResolvedConfig } from "./schema.ts";
2
+ /**
3
+ * Adapters whose `deployment.site` arrives from platform env vars at deploy
4
+ * time. Consumers (e.g. the audit) use this to tell "site is missing" apart
5
+ * from "site is missing *here*, but the platform will set it".
6
+ */
7
+ export declare const SITE_INFERRING_ADAPTERS: ReadonlySet<string>;
2
8
  /**
3
9
  * Fill in `deployment.adapter` and `deployment.site` from platform env vars
4
10
  * (Vercel, Netlify, Cloudflare Pages) when the user hasn't set them. Explicit
@@ -10,6 +10,29 @@ export declare const createDiagnostic: (diagnostic: Diagnostic) => Diagnostic;
10
10
  export declare const resolveDocsUrl: (code: string) => string | undefined;
11
11
  /** Fill in `docsUrl` from the code map where a diagnostic doesn't set its own. */
12
12
  export declare const enrichDiagnostic: (diagnostic: Diagnostic) => Diagnostic;
13
+ /**
14
+ * Locate a front matter key in a content file, e.g. `["seo", "description"]` in
15
+ * `docs/api.mdx`. Scoped to the front matter block so a `title:` written in the
16
+ * page body can't be mistaken for the front matter key of the same name; returns
17
+ * undefined when the file has no front matter or the key isn't set (a missing
18
+ * key has no line to point at — callers anchor to the file instead).
19
+ */
20
+ export declare const locateFrontmatterKey: (source: string, path: readonly (string | number)[]) => {
21
+ column: number;
22
+ line: number;
23
+ } | undefined;
24
+ /**
25
+ * Convert generic validation issues (message + path, the shape shared by Zod
26
+ * and Standard Schema issues) into Blume diagnostics, anchored to a file.
27
+ */
28
+ export declare const diagnosticsFromIssues: (issues: readonly {
29
+ message: string;
30
+ path: readonly (string | number)[];
31
+ }[], options: {
32
+ code: string;
33
+ file?: string;
34
+ source?: string;
35
+ }) => Diagnostic[];
13
36
  /** Convert a ZodError into Blume diagnostics, anchored to a file. */
14
37
  export declare const diagnosticsFromZod: (error: ZodError, options: {
15
38
  code: string;
@@ -243,6 +243,7 @@ declare const uiStringsObject: z.ZodObject<{
243
243
  results: z.ZodDefault<z.ZodString>;
244
244
  }, "strip", z.ZodTypeAny, {
245
245
  label: string;
246
+ popular: string;
246
247
  error: string;
247
248
  placeholder: string;
248
249
  all: string;
@@ -254,11 +255,11 @@ declare const uiStringsObject: z.ZodObject<{
254
255
  askAiHint: string;
255
256
  navigate: string;
256
257
  open: string;
257
- popular: string;
258
258
  preview: string;
259
259
  results: string;
260
260
  }, {
261
261
  label?: string | undefined;
262
+ popular?: string | undefined;
262
263
  error?: string | undefined;
263
264
  placeholder?: string | undefined;
264
265
  all?: string | undefined;
@@ -270,7 +271,6 @@ declare const uiStringsObject: z.ZodObject<{
270
271
  askAiHint?: string | undefined;
271
272
  navigate?: string | undefined;
272
273
  open?: string | undefined;
273
- popular?: string | undefined;
274
274
  preview?: string | undefined;
275
275
  results?: string | undefined;
276
276
  }>>;
@@ -317,6 +317,7 @@ declare const uiStringsObject: z.ZodObject<{
317
317
  };
318
318
  search: {
319
319
  label: string;
320
+ popular: string;
320
321
  error: string;
321
322
  placeholder: string;
322
323
  all: string;
@@ -328,7 +329,6 @@ declare const uiStringsObject: z.ZodObject<{
328
329
  askAiHint: string;
329
330
  navigate: string;
330
331
  open: string;
331
- popular: string;
332
332
  preview: string;
333
333
  results: string;
334
334
  };
@@ -417,6 +417,7 @@ declare const uiStringsObject: z.ZodObject<{
417
417
  } | undefined;
418
418
  search?: {
419
419
  label?: string | undefined;
420
+ popular?: string | undefined;
420
421
  error?: string | undefined;
421
422
  placeholder?: string | undefined;
422
423
  all?: string | undefined;
@@ -428,7 +429,6 @@ declare const uiStringsObject: z.ZodObject<{
428
429
  askAiHint?: string | undefined;
429
430
  navigate?: string | undefined;
430
431
  open?: string | undefined;
431
- popular?: string | undefined;
432
432
  preview?: string | undefined;
433
433
  results?: string | undefined;
434
434
  } | undefined;
@@ -718,6 +718,7 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
718
718
  results: z.ZodDefault<z.ZodString>;
719
719
  }, "strip", z.ZodTypeAny, {
720
720
  label: string;
721
+ popular: string;
721
722
  error: string;
722
723
  placeholder: string;
723
724
  all: string;
@@ -729,11 +730,11 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
729
730
  askAiHint: string;
730
731
  navigate: string;
731
732
  open: string;
732
- popular: string;
733
733
  preview: string;
734
734
  results: string;
735
735
  }, {
736
736
  label?: string | undefined;
737
+ popular?: string | undefined;
737
738
  error?: string | undefined;
738
739
  placeholder?: string | undefined;
739
740
  all?: string | undefined;
@@ -745,7 +746,6 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
745
746
  askAiHint?: string | undefined;
746
747
  navigate?: string | undefined;
747
748
  open?: string | undefined;
748
- popular?: string | undefined;
749
749
  preview?: string | undefined;
750
750
  results?: string | undefined;
751
751
  }>>;
@@ -792,6 +792,7 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
792
792
  };
793
793
  search: {
794
794
  label: string;
795
+ popular: string;
795
796
  error: string;
796
797
  placeholder: string;
797
798
  all: string;
@@ -803,7 +804,6 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
803
804
  askAiHint: string;
804
805
  navigate: string;
805
806
  open: string;
806
- popular: string;
807
807
  preview: string;
808
808
  results: string;
809
809
  };
@@ -892,6 +892,7 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
892
892
  } | undefined;
893
893
  search?: {
894
894
  label?: string | undefined;
895
+ popular?: string | undefined;
895
896
  error?: string | undefined;
896
897
  placeholder?: string | undefined;
897
898
  all?: string | undefined;
@@ -903,7 +904,6 @@ export declare const uiStringsSchema: z.ZodDefault<z.ZodObject<{
903
904
  askAiHint?: string | undefined;
904
905
  navigate?: string | undefined;
905
906
  open?: string | undefined;
906
- popular?: string | undefined;
907
907
  preview?: string | undefined;
908
908
  results?: string | undefined;
909
909
  } | undefined;
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import type { ComponentMarkdown } from "../ai/component-markdown.ts";
3
3
  import type { ContentSource } from "./sources/types.ts";
4
+ import type { StandardSchema } from "./standard-schema.ts";
4
5
  declare const hydrationMode: z.ZodEnum<["load", "idle", "visible", "media", "only"]>;
5
6
  export type HydrationMode = z.infer<typeof hydrationMode>;
6
7
  /** Frontmatter accepted on any content page. */
@@ -1759,6 +1760,14 @@ export declare const blumeConfigSchema: z.ZodObject<{
1759
1760
  pdf?: boolean | undefined;
1760
1761
  }>>;
1761
1762
  feedback: z.ZodDefault<z.ZodBoolean>;
1763
+ /** Opt-in custom frontmatter keys, validated by user-supplied schemas. */
1764
+ frontmatter: z.ZodDefault<z.ZodObject<{
1765
+ extend: z.ZodEffects<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodType<StandardSchema<unknown, unknown>, z.ZodTypeDef, StandardSchema<unknown, unknown>>>>, Record<string, StandardSchema<unknown, unknown>>, Record<string, StandardSchema<unknown, unknown>> | undefined>;
1766
+ }, "strict", z.ZodTypeAny, {
1767
+ extend: Record<string, StandardSchema<unknown, unknown>>;
1768
+ }, {
1769
+ extend?: Record<string, StandardSchema<unknown, unknown>> | undefined;
1770
+ }>>;
1762
1771
  github: z.ZodOptional<z.ZodObject<{
1763
1772
  branch: z.ZodDefault<z.ZodString>;
1764
1773
  /** Path from the repo root to the project root (for monorepos). */
@@ -1848,9 +1857,9 @@ export declare const blumeConfigSchema: z.ZodObject<{
1848
1857
  lastModified: z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodObject<{
1849
1858
  type: z.ZodDefault<z.ZodEnum<["git", "frontmatter"]>>;
1850
1859
  }, "strict", z.ZodTypeAny, {
1851
- type: "git" | "frontmatter";
1860
+ type: "frontmatter" | "git";
1852
1861
  }, {
1853
- type?: "git" | "frontmatter" | undefined;
1862
+ type?: "frontmatter" | "git" | undefined;
1854
1863
  }>]>>;
1855
1864
  logo: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
1856
1865
  href: z.ZodOptional<z.ZodString>;
@@ -2288,6 +2297,20 @@ export declare const blumeConfigSchema: z.ZodObject<{
2288
2297
  endpoint: string;
2289
2298
  indexId?: string | undefined;
2290
2299
  }>>;
2300
+ /** Curated links for the Cmd+K empty state; defaults to the first sidebar pages. */
2301
+ popular: z.ZodDefault<z.ZodArray<z.ZodObject<{
2302
+ href: z.ZodString;
2303
+ icon: z.ZodOptional<z.ZodString>;
2304
+ label: z.ZodString;
2305
+ }, "strict", z.ZodTypeAny, {
2306
+ label: string;
2307
+ href: string;
2308
+ icon?: string | undefined;
2309
+ }, {
2310
+ label: string;
2311
+ href: string;
2312
+ icon?: string | undefined;
2313
+ }>, "many">>;
2291
2314
  provider: z.ZodDefault<z.ZodEnum<["orama", "pagefind", "flexsearch", "algolia", "orama-cloud", "typesense", "mixedbread", "none"]>>;
2292
2315
  typesense: z.ZodOptional<z.ZodObject<{
2293
2316
  collection: z.ZodString;
@@ -2313,6 +2336,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2313
2336
  indexing: {
2314
2337
  includeHiddenPages: boolean;
2315
2338
  };
2339
+ popular: {
2340
+ label: string;
2341
+ href: string;
2342
+ icon?: string | undefined;
2343
+ }[];
2316
2344
  algolia?: {
2317
2345
  appId: string;
2318
2346
  indexName: string;
@@ -2351,6 +2379,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2351
2379
  endpoint: string;
2352
2380
  indexId?: string | undefined;
2353
2381
  } | undefined;
2382
+ popular?: {
2383
+ label: string;
2384
+ href: string;
2385
+ icon?: string | undefined;
2386
+ }[] | undefined;
2354
2387
  typesense?: {
2355
2388
  host: string;
2356
2389
  searchApiKey: string;
@@ -2363,6 +2396,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2363
2396
  indexing: {
2364
2397
  includeHiddenPages: boolean;
2365
2398
  };
2399
+ popular: {
2400
+ label: string;
2401
+ href: string;
2402
+ icon?: string | undefined;
2403
+ }[];
2366
2404
  algolia?: {
2367
2405
  appId: string;
2368
2406
  indexName: string;
@@ -2401,6 +2439,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2401
2439
  endpoint: string;
2402
2440
  indexId?: string | undefined;
2403
2441
  } | undefined;
2442
+ popular?: {
2443
+ label: string;
2444
+ href: string;
2445
+ icon?: string | undefined;
2446
+ }[] | undefined;
2404
2447
  typesense?: {
2405
2448
  host: string;
2406
2449
  searchApiKey: string;
@@ -2446,6 +2489,24 @@ export declare const blumeConfigSchema: z.ZodObject<{
2446
2489
  * `loadConfig`. An explicit value here always wins.
2447
2490
  */
2448
2491
  enabled: z.ZodOptional<z.ZodBoolean>;
2492
+ /**
2493
+ * Google Font families for the generated card, extending Takumi's Latin-only
2494
+ * default so non-Latin titles (CJK, and so on) render instead of tofu.
2495
+ * Fetched from Google Fonts at build.
2496
+ */
2497
+ fonts: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
2498
+ name: z.ZodString;
2499
+ style: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["normal", "italic"]>, z.ZodArray<z.ZodEnum<["normal", "italic"]>, "many">]>>;
2500
+ weight: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodArray<z.ZodNumber, "many">, z.ZodString]>>;
2501
+ }, "strict", z.ZodTypeAny, {
2502
+ name: string;
2503
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
2504
+ weight?: string | number | number[] | undefined;
2505
+ }, {
2506
+ name: string;
2507
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
2508
+ weight?: string | number | number[] | undefined;
2509
+ }>]>, "many">>;
2449
2510
  /** Local SVG used in the generated card instead of the site logo. */
2450
2511
  logo: z.ZodOptional<z.ZodString>;
2451
2512
  /** Optional generated-card colors. */
@@ -2471,6 +2532,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2471
2532
  }, "strict", z.ZodTypeAny, {
2472
2533
  enabled?: boolean | undefined;
2473
2534
  logo?: string | undefined;
2535
+ fonts?: (string | {
2536
+ name: string;
2537
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
2538
+ weight?: string | number | number[] | undefined;
2539
+ })[] | undefined;
2474
2540
  palette?: {
2475
2541
  accent?: string | undefined;
2476
2542
  background?: string | undefined;
@@ -2481,6 +2547,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2481
2547
  }, {
2482
2548
  enabled?: boolean | undefined;
2483
2549
  logo?: string | undefined;
2550
+ fonts?: (string | {
2551
+ name: string;
2552
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
2553
+ weight?: string | number | number[] | undefined;
2554
+ })[] | undefined;
2484
2555
  palette?: {
2485
2556
  accent?: string | undefined;
2486
2557
  background?: string | undefined;
@@ -2533,6 +2604,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2533
2604
  og: {
2534
2605
  enabled?: boolean | undefined;
2535
2606
  logo?: string | undefined;
2607
+ fonts?: (string | {
2608
+ name: string;
2609
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
2610
+ weight?: string | number | number[] | undefined;
2611
+ })[] | undefined;
2536
2612
  palette?: {
2537
2613
  accent?: string | undefined;
2538
2614
  background?: string | undefined;
@@ -2563,6 +2639,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2563
2639
  og?: {
2564
2640
  enabled?: boolean | undefined;
2565
2641
  logo?: string | undefined;
2642
+ fonts?: (string | {
2643
+ name: string;
2644
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
2645
+ weight?: string | number | number[] | undefined;
2646
+ })[] | undefined;
2566
2647
  palette?: {
2567
2648
  accent?: string | undefined;
2568
2649
  background?: string | undefined;
@@ -2651,15 +2732,15 @@ export declare const blumeConfigSchema: z.ZodObject<{
2651
2732
  mode: z.ZodDefault<z.ZodEnum<["system", "light", "dark"]>>;
2652
2733
  radius: z.ZodDefault<z.ZodEnum<["none", "sm", "md", "lg"]>>;
2653
2734
  }, "strict", z.ZodTypeAny, {
2654
- accent: {
2655
- dark: string;
2656
- light: string;
2657
- };
2658
2735
  fonts: {
2659
2736
  mono: string;
2660
2737
  display: string;
2661
2738
  body: string;
2662
2739
  };
2740
+ accent: {
2741
+ dark: string;
2742
+ light: string;
2743
+ };
2663
2744
  layout: "sidebar";
2664
2745
  mode: "dark" | "light" | "system";
2665
2746
  radius: "none" | "sm" | "md" | "lg";
@@ -2673,6 +2754,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2673
2754
  light?: string | undefined;
2674
2755
  } | undefined;
2675
2756
  }, {
2757
+ fonts?: {
2758
+ mono?: string | undefined;
2759
+ display?: string | undefined;
2760
+ body?: string | undefined;
2761
+ } | undefined;
2676
2762
  accent?: string | {
2677
2763
  dark: string;
2678
2764
  light: string;
@@ -2686,11 +2772,6 @@ export declare const blumeConfigSchema: z.ZodObject<{
2686
2772
  dark?: string | undefined;
2687
2773
  light?: string | undefined;
2688
2774
  } | undefined;
2689
- fonts?: {
2690
- mono?: string | undefined;
2691
- display?: string | undefined;
2692
- body?: string | undefined;
2693
- } | undefined;
2694
2775
  layout?: "sidebar" | undefined;
2695
2776
  mode?: "dark" | "light" | "system" | undefined;
2696
2777
  radius?: "none" | "sm" | "md" | "lg" | undefined;
@@ -2839,15 +2920,15 @@ export declare const blumeConfigSchema: z.ZodObject<{
2839
2920
  })[] | undefined;
2840
2921
  };
2841
2922
  theme: {
2842
- accent: {
2843
- dark: string;
2844
- light: string;
2845
- };
2846
2923
  fonts: {
2847
2924
  mono: string;
2848
2925
  display: string;
2849
2926
  body: string;
2850
2927
  };
2928
+ accent: {
2929
+ dark: string;
2930
+ light: string;
2931
+ };
2851
2932
  layout: "sidebar";
2852
2933
  mode: "dark" | "light" | "system";
2853
2934
  radius: "none" | "sm" | "md" | "lg";
@@ -2863,7 +2944,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
2863
2944
  };
2864
2945
  basePath: string;
2865
2946
  lastModified: boolean | {
2866
- type: "git" | "frontmatter";
2947
+ type: "frontmatter" | "git";
2867
2948
  };
2868
2949
  deployment: {
2869
2950
  adapter: "vercel" | "node" | "netlify" | "cloudflare" | null;
@@ -2880,6 +2961,9 @@ export declare const blumeConfigSchema: z.ZodObject<{
2880
2961
  pdf: boolean;
2881
2962
  };
2882
2963
  feedback: boolean;
2964
+ frontmatter: {
2965
+ extend: Record<string, StandardSchema<unknown, unknown>>;
2966
+ };
2883
2967
  markdown: {
2884
2968
  code: {
2885
2969
  icons: boolean;
@@ -2942,6 +3026,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2942
3026
  indexing: {
2943
3027
  includeHiddenPages: boolean;
2944
3028
  };
3029
+ popular: {
3030
+ label: string;
3031
+ href: string;
3032
+ icon?: string | undefined;
3033
+ }[];
2945
3034
  algolia?: {
2946
3035
  appId: string;
2947
3036
  indexName: string;
@@ -2973,6 +3062,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
2973
3062
  og: {
2974
3063
  enabled?: boolean | undefined;
2975
3064
  logo?: string | undefined;
3065
+ fonts?: (string | {
3066
+ name: string;
3067
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
3068
+ weight?: string | number | number[] | undefined;
3069
+ })[] | undefined;
2976
3070
  palette?: {
2977
3071
  accent?: string | undefined;
2978
3072
  background?: string | undefined;
@@ -3181,6 +3275,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
3181
3275
  vercel?: boolean | undefined;
3182
3276
  } | undefined;
3183
3277
  theme?: {
3278
+ fonts?: {
3279
+ mono?: string | undefined;
3280
+ display?: string | undefined;
3281
+ body?: string | undefined;
3282
+ } | undefined;
3184
3283
  accent?: string | {
3185
3284
  dark: string;
3186
3285
  light: string;
@@ -3194,11 +3293,6 @@ export declare const blumeConfigSchema: z.ZodObject<{
3194
3293
  dark?: string | undefined;
3195
3294
  light?: string | undefined;
3196
3295
  } | undefined;
3197
- fonts?: {
3198
- mono?: string | undefined;
3199
- display?: string | undefined;
3200
- body?: string | undefined;
3201
- } | undefined;
3202
3296
  layout?: "sidebar" | undefined;
3203
3297
  mode?: "dark" | "light" | "system" | undefined;
3204
3298
  radius?: "none" | "sm" | "md" | "lg" | undefined;
@@ -3221,7 +3315,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
3221
3315
  } | undefined;
3222
3316
  description?: string | undefined;
3223
3317
  lastModified?: boolean | {
3224
- type?: "git" | "frontmatter" | undefined;
3318
+ type?: "frontmatter" | "git" | undefined;
3225
3319
  } | undefined;
3226
3320
  deployment?: {
3227
3321
  adapter?: "vercel" | "node" | "netlify" | "cloudflare" | null | undefined;
@@ -3238,6 +3332,9 @@ export declare const blumeConfigSchema: z.ZodObject<{
3238
3332
  pdf?: boolean | undefined;
3239
3333
  } | undefined;
3240
3334
  feedback?: boolean | undefined;
3335
+ frontmatter?: {
3336
+ extend?: Record<string, StandardSchema<unknown, unknown>> | undefined;
3337
+ } | undefined;
3241
3338
  i18n?: {
3242
3339
  locales: {
3243
3340
  code: string;
@@ -3334,6 +3431,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
3334
3431
  endpoint: string;
3335
3432
  indexId?: string | undefined;
3336
3433
  } | undefined;
3434
+ popular?: {
3435
+ label: string;
3436
+ href: string;
3437
+ icon?: string | undefined;
3438
+ }[] | undefined;
3337
3439
  typesense?: {
3338
3440
  host: string;
3339
3441
  searchApiKey: string;
@@ -3352,6 +3454,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
3352
3454
  og?: {
3353
3455
  enabled?: boolean | undefined;
3354
3456
  logo?: string | undefined;
3457
+ fonts?: (string | {
3458
+ name: string;
3459
+ style?: "normal" | "italic" | ("normal" | "italic")[] | undefined;
3460
+ weight?: string | number | number[] | undefined;
3461
+ })[] | undefined;
3355
3462
  palette?: {
3356
3463
  accent?: string | undefined;
3357
3464
  background?: string | undefined;
@@ -3380,6 +3487,8 @@ export declare const blumeConfigSchema: z.ZodObject<{
3380
3487
  }>;
3381
3488
  /** Resolved config: every field present after defaults are applied. */
3382
3489
  export type ResolvedConfig = z.infer<typeof blumeConfigSchema>;
3490
+ /** Resolved `frontmatter.extend`: custom key → user-supplied schema. */
3491
+ export type FrontmatterExtend = Record<string, StandardSchema>;
3383
3492
  /** Resolved i18n block (present only when the project opts into i18n). */
3384
3493
  export type ResolvedI18nConfig = z.infer<typeof i18nConfigSchema>;
3385
3494
  /** A configured locale with display metadata. */
@@ -1,4 +1,4 @@
1
- import type { ResolvedI18nConfig } from "../schema.ts";
1
+ import type { FrontmatterExtend, ResolvedI18nConfig } from "../schema.ts";
2
2
  import type { Diagnostic } from "../types.ts";
3
3
  /**
4
4
  * A single content item, normalized by a source adapter. Adapters lower their
@@ -111,5 +111,7 @@ export interface NormalizeContext {
111
111
  /** Site-wide route mount point (`""` or `/seg`), prepended to every route. */
112
112
  basePath?: string;
113
113
  defaultType: string;
114
+ /** Opt-in custom frontmatter keys (`frontmatter.extend`), schema per key. */
115
+ frontmatterExtend?: FrontmatterExtend;
114
116
  i18n?: ResolvedI18nConfig;
115
117
  }