@farming-labs/docs 0.0.2-beta.9 → 0.0.2

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/index.d.mts CHANGED
@@ -137,6 +137,13 @@ interface UIConfig {
137
137
  toc?: {
138
138
  enabled?: boolean;
139
139
  depth?: number;
140
+ /**
141
+ * Visual style of the TOC indicator.
142
+ * - `"default"` — highlight active link text color only
143
+ * - `"directional"` — animated thumb bar that tracks active headings (fumadocs style)
144
+ * @default "default"
145
+ */
146
+ style?: "default" | "directional";
140
147
  };
141
148
  header?: {
142
149
  height?: number;
@@ -223,6 +230,8 @@ interface PageFrontmatter {
223
230
  icon?: string;
224
231
  /** Path to custom OG image for this page */
225
232
  ogImage?: string;
233
+ /** Sort order in the sidebar. Lower numbers appear first. Pages without `order` are sorted alphabetically after ordered pages. */
234
+ order?: number;
226
235
  }
227
236
  interface DocsNav {
228
237
  /**
@@ -288,6 +297,54 @@ interface BreadcrumbConfig {
288
297
  */
289
298
  component?: unknown;
290
299
  }
300
+ /**
301
+ * A leaf page in the sidebar tree.
302
+ */
303
+ interface SidebarPageNode {
304
+ type: "page";
305
+ name: string;
306
+ url: string;
307
+ icon?: unknown;
308
+ }
309
+ /**
310
+ * A folder (group) in the sidebar tree. May contain child pages
311
+ * and nested folders, forming a recursive hierarchy.
312
+ */
313
+ interface SidebarFolderNode {
314
+ type: "folder";
315
+ name: string;
316
+ icon?: unknown;
317
+ /** Index page for this folder (the folder's own landing page). */
318
+ index?: SidebarPageNode;
319
+ /** Child pages and sub-folders. */
320
+ children: SidebarNode[];
321
+ /** Whether this folder section is collapsible. */
322
+ collapsible?: boolean;
323
+ /** Whether this folder starts open. */
324
+ defaultOpen?: boolean;
325
+ }
326
+ /** A node in the sidebar tree — either a page or a folder. */
327
+ type SidebarNode = SidebarPageNode | SidebarFolderNode;
328
+ /** The full sidebar tree passed to custom sidebar components. */
329
+ interface SidebarTree {
330
+ name: string;
331
+ children: SidebarNode[];
332
+ }
333
+ /**
334
+ * Props passed to a custom sidebar component.
335
+ *
336
+ * Contains all the information needed to build a fully custom sidebar:
337
+ * the complete page tree with parent-child relationships, and the
338
+ * current sidebar configuration.
339
+ */
340
+ interface SidebarComponentProps {
341
+ /** Full page tree with all parent-child-folder relationships. */
342
+ tree: SidebarTree;
343
+ /** Whether folders are collapsible. */
344
+ collapsible: boolean;
345
+ /** Whether folders are rendered flat (Mintlify-style). */
346
+ flat: boolean;
347
+ }
291
348
  interface SidebarConfig {
292
349
  /**
293
350
  * Whether to show the sidebar.
@@ -295,17 +352,46 @@ interface SidebarConfig {
295
352
  */
296
353
  enabled?: boolean;
297
354
  /**
298
- * Custom sidebar component to completely replace the default sidebar.
299
- * Receives the page tree and config as context.
355
+ * Custom sidebar component to replace the default navigation.
300
356
  *
301
- * @example
357
+ * **Next.js** — Pass a render function that receives `SidebarComponentProps`:
302
358
  * ```tsx
303
359
  * sidebar: {
304
- * component: MySidebar,
360
+ * component: ({ tree, collapsible, flat }) => (
361
+ * <MySidebar tree={tree} />
362
+ * ),
305
363
  * }
306
364
  * ```
365
+ *
366
+ * **Astro** — Use the `sidebar` named slot on `<DocsLayout>`:
367
+ * ```astro
368
+ * <DocsLayout tree={tree} config={config}>
369
+ * <MySidebar slot="sidebar" tree={tree} />
370
+ * <slot />
371
+ * </DocsLayout>
372
+ * ```
373
+ *
374
+ * **SvelteKit** — Use the `sidebar` snippet on `<DocsLayout>`:
375
+ * ```svelte
376
+ * <DocsLayout {tree} {config}>
377
+ * {#snippet sidebar({ tree, isActive })}
378
+ * <MySidebarNav {tree} {isActive} />
379
+ * {/snippet}
380
+ * {@render children()}
381
+ * </DocsLayout>
382
+ * ```
383
+ *
384
+ * **Nuxt / Vue** — Use the `#sidebar` scoped slot on `<DocsLayout>`:
385
+ * ```vue
386
+ * <DocsLayout :tree="tree" :config="config">
387
+ * <template #sidebar="{ tree, isActive }">
388
+ * <MySidebarNav :tree="tree" :is-active="isActive" />
389
+ * </template>
390
+ * <DocsContent />
391
+ * </DocsLayout>
392
+ * ```
307
393
  */
308
- component?: unknown;
394
+ component?: (props: SidebarComponentProps) => unknown;
309
395
  /**
310
396
  * Sidebar footer content (rendered below navigation items).
311
397
  */
@@ -319,6 +405,17 @@ interface SidebarConfig {
319
405
  * @default true
320
406
  */
321
407
  collapsible?: boolean;
408
+ /**
409
+ * When true, all folder children are rendered flat in the sidebar
410
+ * (no collapsible sections). Folder index pages appear as category
411
+ * headings with all children listed directly below them.
412
+ *
413
+ * This creates a Mintlify-style sidebar where all navigation items
414
+ * are always visible.
415
+ *
416
+ * @default false
417
+ */
418
+ flat?: boolean;
322
419
  }
323
420
  /**
324
421
  * A single "Open in …" provider shown in the Open dropdown.
@@ -334,10 +431,13 @@ interface OpenDocsProvider {
334
431
  /** Icon element rendered next to the name */
335
432
  icon?: unknown;
336
433
  /**
337
- * URL template. `{url}` is replaced with the current page URL.
338
- * `{mdxUrl}` is replaced with the `.mdx` variant of the page URL.
434
+ * URL template. Placeholders:
435
+ * - `{url}` current page URL (encoded).
436
+ * - `{mdxUrl}` — page URL with `.mdx` suffix (encoded).
437
+ * - `{githubUrl}` — GitHub edit URL for the current page (same as "Edit on GitHub"). Requires `github` in config.
339
438
  *
340
439
  * @example "https://claude.ai/new?q=Read+this+doc:+{url}"
440
+ * @example "{githubUrl}" — open current page file on GitHub (edit view)
341
441
  */
342
442
  urlTemplate: string;
343
443
  }
@@ -404,6 +504,65 @@ interface PageActionsConfig {
404
504
  * @default "below-title"
405
505
  */
406
506
  position?: "above-title" | "below-title";
507
+ /**
508
+ * Horizontal alignment of page action buttons.
509
+ *
510
+ * - `"left"` — align to the left (default)
511
+ * - `"right"` — align to the right
512
+ *
513
+ * @default "left"
514
+ */
515
+ alignment?: "left" | "right";
516
+ }
517
+ /**
518
+ * Configuration for the "Last updated" date display.
519
+ *
520
+ * @example
521
+ * ```ts
522
+ * lastUpdated: { position: "below-title" }
523
+ * ```
524
+ */
525
+ /**
526
+ * Configuration for auto-generated `/llms.txt` and `/llms-full.txt` routes.
527
+ *
528
+ * @see https://llmstxt.org
529
+ */
530
+ interface LlmsTxtConfig {
531
+ /**
532
+ * Whether to enable llms.txt generation.
533
+ * @default true
534
+ */
535
+ enabled?: boolean;
536
+ /**
537
+ * Base URL for your docs site (used to build absolute links in llms.txt).
538
+ * @example "https://docs.example.com"
539
+ */
540
+ baseUrl?: string;
541
+ /**
542
+ * Site title shown at the top of llms.txt.
543
+ * Falls back to `nav.title` if not set.
544
+ */
545
+ siteTitle?: string;
546
+ /**
547
+ * Site description shown below the title.
548
+ */
549
+ siteDescription?: string;
550
+ }
551
+ interface LastUpdatedConfig {
552
+ /**
553
+ * Whether to show the "Last updated" date.
554
+ * @default true
555
+ */
556
+ enabled?: boolean;
557
+ /**
558
+ * Where to render the "Last updated" date.
559
+ *
560
+ * - `"footer"` — next to the "Edit on GitHub" link at the bottom (default)
561
+ * - `"below-title"` — below the page title/description, above the content
562
+ *
563
+ * @default "footer"
564
+ */
565
+ position?: "footer" | "below-title";
407
566
  }
408
567
  /**
409
568
  * GitHub repository configuration for "Edit on GitHub" links
@@ -487,7 +646,7 @@ interface AIConfig {
487
646
  * }
488
647
  * ```
489
648
  */
490
- mode?: "search" | "floating";
649
+ mode?: "search" | "floating" | "sidebar-icon";
491
650
  /**
492
651
  * Position of the floating chat button on screen.
493
652
  * Only used when `mode` is `"floating"`.
@@ -531,19 +690,44 @@ interface AIConfig {
531
690
  */
532
691
  floatingStyle?: "panel" | "modal" | "popover" | "full-modal";
533
692
  /**
534
- * Custom trigger component for the floating chat button.
693
+ * Custom trigger component for the floating chat button (Next.js only).
535
694
  * Only used when `mode` is `"floating"`.
536
695
  *
537
- * Pass a React element to replace the default sparkles button.
538
- * The element receives an `onClick` handler automatically.
696
+ * The click handler is attached automatically by the wrapper.
697
+ *
698
+ * - **Next.js**: Pass a JSX element via this config option.
699
+ * - **SvelteKit**: Use the `aiTrigger` snippet on `<DocsLayout>`.
700
+ * - **Nuxt / Vue**: Use the `ai-trigger` slot on `<DocsLayout>`.
701
+ * - **Astro**: Use `<MyTrigger slot="ai-trigger" />` on `<DocsLayout>`.
539
702
  *
540
703
  * @example
541
704
  * ```tsx
542
- * ai: {
543
- * enabled: true,
544
- * mode: "floating",
545
- * triggerComponent: <button className="my-chat-btn">💬 Help</button>,
546
- * }
705
+ * // Next.js — pass JSX directly in config
706
+ * triggerComponent: <button className="my-chat-btn">Ask AI</button>,
707
+ * ```
708
+ *
709
+ * ```svelte
710
+ * <!-- SvelteKit — use snippet in layout -->
711
+ * <DocsLayout {tree} {config}>
712
+ * {#snippet aiTrigger()}<AskAITrigger />{/snippet}
713
+ * {@render children()}
714
+ * </DocsLayout>
715
+ * ```
716
+ *
717
+ * ```vue
718
+ * <!-- Nuxt / Vue — use named slot in layout -->
719
+ * <DocsLayout :tree="tree" :config="config">
720
+ * <template #ai-trigger><AskAITrigger /></template>
721
+ * <DocsContent />
722
+ * </DocsLayout>
723
+ * ```
724
+ *
725
+ * ```astro
726
+ * <!-- Astro — use named slot in layout -->
727
+ * <DocsLayout tree={tree} config={config}>
728
+ * <AskAITrigger slot="ai-trigger" />
729
+ * <DocsContent />
730
+ * </DocsLayout>
547
731
  * ```
548
732
  */
549
733
  triggerComponent?: unknown;
@@ -653,11 +837,37 @@ interface AIConfig {
653
837
  */
654
838
  docsUrl?: string;
655
839
  /**
656
- * Custom loading indicator shown while the AI is generating a response.
657
- * Replaces the default "AI is thinking..." indicator.
840
+ * Loading indicator variant shown while the AI generates a response.
658
841
  *
659
- * Pass a function that receives `{ name }` (the `aiLabel` value) and
660
- * returns a React element. This way you don't need to duplicate the label.
842
+ * - `"shimmer-dots"` shimmer text + typing dots (default)
843
+ * - `"circular"` spinning ring
844
+ * - `"dots"` — bouncing dots
845
+ * - `"typing"` — typing dots
846
+ * - `"wave"` — wave bars
847
+ * - `"bars"` — thick wave bars
848
+ * - `"pulse"` — pulsing ring
849
+ * - `"pulse-dot"` — pulsing dot
850
+ * - `"terminal"` — blinking terminal cursor
851
+ * - `"text-blink"` — blinking text
852
+ * - `"text-shimmer"` — shimmer text only
853
+ * - `"loading-dots"` — "Thinking..." with animated dots
854
+ *
855
+ * @default "shimmer-dots"
856
+ *
857
+ * @example
858
+ * ```ts
859
+ * ai: {
860
+ * enabled: true,
861
+ * loader: "wave",
862
+ * }
863
+ * ```
864
+ */
865
+ loader?: "shimmer-dots" | "circular" | "dots" | "typing" | "wave" | "bars" | "pulse" | "pulse-dot" | "terminal" | "text-blink" | "text-shimmer" | "loading-dots";
866
+ /**
867
+ * Custom loading indicator that overrides the built-in `loader` variant.
868
+ * Receives `{ name }` (the `aiLabel` value) and returns a React element.
869
+ *
870
+ * Only works in Next.js. For other frameworks, use the `loader` option.
661
871
  *
662
872
  * @example
663
873
  * ```tsx
@@ -677,6 +887,30 @@ interface AIConfig {
677
887
  name: string;
678
888
  }) => unknown;
679
889
  }
890
+ /**
891
+ * A single item in the slug-based sidebar ordering.
892
+ *
893
+ * @example
894
+ * ```ts
895
+ * ordering: [
896
+ * { slug: "installation" },
897
+ * { slug: "cli" },
898
+ * { slug: "themes", children: [
899
+ * { slug: "default" },
900
+ * { slug: "darksharp" },
901
+ * { slug: "pixel-border" },
902
+ * { slug: "creating-themes" },
903
+ * ]},
904
+ * { slug: "reference" },
905
+ * ]
906
+ * ```
907
+ */
908
+ interface OrderingItem {
909
+ /** Folder name (not the full path, just the directory name at this level) */
910
+ slug: string;
911
+ /** Ordering for child pages within this folder */
912
+ children?: OrderingItem[];
913
+ }
680
914
  interface DocsConfig {
681
915
  /** Entry folder for docs (e.g. "docs" → /docs) */
682
916
  entry: string;
@@ -816,6 +1050,24 @@ interface DocsConfig {
816
1050
  * ```
817
1051
  */
818
1052
  pageActions?: PageActionsConfig;
1053
+ /**
1054
+ * Configuration for the "Last updated" date display.
1055
+ *
1056
+ * - `true` or `undefined` → shown in footer next to "Edit on GitHub" (default)
1057
+ * - `false` → hidden
1058
+ * - `{ position: "below-title" }` → shown below the page title
1059
+ * - `{ position: "footer" }` → shown next to "Edit on GitHub" (default)
1060
+ *
1061
+ * @example
1062
+ * ```ts
1063
+ * // Show below title (Mintlify style)
1064
+ * lastUpdated: { position: "below-title" }
1065
+ *
1066
+ * // Hide entirely
1067
+ * lastUpdated: false
1068
+ * ```
1069
+ */
1070
+ lastUpdated?: boolean | LastUpdatedConfig;
819
1071
  /**
820
1072
  * AI-powered "Ask AI" chat for documentation.
821
1073
  *
@@ -849,6 +1101,55 @@ interface DocsConfig {
849
1101
  * ```
850
1102
  */
851
1103
  ai?: AIConfig;
1104
+ /**
1105
+ * Sidebar ordering strategy.
1106
+ *
1107
+ * - `"alphabetical"` — sort pages alphabetically by folder name (default)
1108
+ * - `"numeric"` — sort by frontmatter `order` field (lower first, unset pages last)
1109
+ * - `OrderingItem[]` — explicit slug-based ordering with nested children
1110
+ *
1111
+ * @default "alphabetical"
1112
+ *
1113
+ * @example
1114
+ * ```ts
1115
+ * // Alphabetical (default)
1116
+ * ordering: "alphabetical",
1117
+ *
1118
+ * // Use frontmatter `order: 1`, `order: 2`, etc.
1119
+ * ordering: "numeric",
1120
+ *
1121
+ * // Explicit slug-based ordering
1122
+ * ordering: [
1123
+ * { slug: "installation" },
1124
+ * { slug: "cli" },
1125
+ * { slug: "configuration" },
1126
+ * { slug: "themes", children: [
1127
+ * { slug: "default" },
1128
+ * { slug: "darksharp" },
1129
+ * { slug: "pixel-border" },
1130
+ * { slug: "creating-themes" },
1131
+ * ]},
1132
+ * { slug: "customization" },
1133
+ * { slug: "reference" },
1134
+ * ]
1135
+ * ```
1136
+ */
1137
+ ordering?: "alphabetical" | "numeric" | OrderingItem[];
1138
+ /**
1139
+ * Auto-generate `/llms.txt` and `/llms-full.txt` routes for LLM-friendly
1140
+ * documentation. These files let AI tools quickly understand your docs.
1141
+ *
1142
+ * @example
1143
+ * ```ts
1144
+ * llmsTxt: {
1145
+ * enabled: true,
1146
+ * baseUrl: "https://docs.example.com",
1147
+ * }
1148
+ * ```
1149
+ *
1150
+ * @see https://llmstxt.org
1151
+ */
1152
+ llmsTxt?: boolean | LlmsTxtConfig;
852
1153
  /** SEO metadata - separate from theme */
853
1154
  metadata?: DocsMetadata;
854
1155
  /** Open Graph image handling */
@@ -924,4 +1225,4 @@ declare function resolveTitle(pageTitle: string, metadata?: DocsMetadata): strin
924
1225
  */
925
1226
  declare function resolveOGImage(page: PageFrontmatter, ogConfig?: OGConfig, baseUrl?: string): string | undefined;
926
1227
  //#endregion
927
- export { type AIConfig, type BreadcrumbConfig, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type PageActionsConfig, type PageFrontmatter, type SidebarConfig, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
1228
+ export { type AIConfig, type BreadcrumbConfig, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type LastUpdatedConfig, type LlmsTxtConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type OrderingItem, type PageActionsConfig, type PageFrontmatter, type SidebarComponentProps, type SidebarConfig, type SidebarFolderNode, type SidebarNode, type SidebarPageNode, type SidebarTree, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
package/dist/index.mjs CHANGED
@@ -15,7 +15,10 @@ function defineDocs(config) {
15
15
  components: config.components,
16
16
  icons: config.icons,
17
17
  pageActions: config.pageActions,
18
+ lastUpdated: config.lastUpdated,
19
+ llmsTxt: config.llmsTxt,
18
20
  ai: config.ai,
21
+ ordering: config.ordering,
19
22
  metadata: config.metadata,
20
23
  og: config.og
21
24
  };
package/package.json CHANGED
@@ -1,7 +1,20 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.0.2-beta.9",
3
+ "version": "0.0.2",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
+ "keywords": [
6
+ "docs",
7
+ "documentation",
8
+ "mdx"
9
+ ],
10
+ "license": "MIT",
11
+ "author": "Farming Labs",
12
+ "bin": {
13
+ "docs": "./dist/cli/index.mjs"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
5
18
  "type": "module",
6
19
  "main": "./dist/index.mjs",
7
20
  "module": "./dist/index.mjs",
@@ -13,19 +26,6 @@
13
26
  "default": "./dist/index.mjs"
14
27
  }
15
28
  },
16
- "bin": {
17
- "docs": "./dist/cli/index.mjs"
18
- },
19
- "files": [
20
- "dist"
21
- ],
22
- "keywords": [
23
- "docs",
24
- "mdx",
25
- "documentation"
26
- ],
27
- "author": "Farming Labs",
28
- "license": "MIT",
29
29
  "dependencies": {
30
30
  "@clack/prompts": "^0.9.1",
31
31
  "gray-matter": "^4.0.3",