@baybreezy/docd 0.0.8 → 0.0.10

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Behon Baker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @baybreezy/docd
2
+
3
+ > Build beautiful documentation sites with Nuxt, Markdown, and Vue components.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@baybreezy/docd.svg?style=flat&colorA=020420&colorB=EEEEEE)](https://npmjs.com/package/@baybreezy/docd)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@baybreezy/docd.svg?style=flat&colorA=020420&colorB=EEEEEE)](https://npm.chart.dev/@baybreezy/docd)
7
+ [![License](https://img.shields.io/npm/l/@baybreezy/docd.svg?style=flat&colorA=020420&colorB=EEEEEE)](https://npmjs.com/package/@baybreezy/docd)
8
+
9
+ ## Quick Start
10
+
11
+ Scaffold a new project in seconds:
12
+
13
+ ```bash
14
+ # Create a new docs project
15
+ npx create-docd my-docs
16
+
17
+ # Navigate to your project
18
+ cd my-docs
19
+
20
+ # Start the dev server
21
+ bun run dev
22
+ ```
23
+
24
+ Your documentation site will be running at `http://localhost:3000`.
25
+
26
+ ## What you get
27
+
28
+ A fully configured documentation site with:
29
+
30
+ - **Beautiful design** — Clean, modern theme built on [UI Thing](https://uithing.com) components
31
+ - **Theming** — 17 color themes with light/dark mode out of the box
32
+ - **Markdown enhanced** — Extended MDC syntax with interactive components and prose wrappers
33
+ - **Component API docs** — Automatic prop/slot/event documentation from Vue component metadata
34
+ - **Full-text search** — Built-in search across all your content
35
+ - **OG images** — Automatic Open Graph image generation
36
+ - **LLM-ready** — Auto-generates `llms.txt` and `llms-full.txt` for AI tool integration
37
+ - **MCP server** — Built-in Model Context Protocol server for Cursor, VS Code, Claude, and more
38
+ - **SEO** — Sitemap, robots.txt, and meta tags configured automatically
39
+ - **TypeScript** — Full type safety throughout
40
+
41
+ ## Project structure
42
+
43
+ ```
44
+ my-docs/
45
+ ├── content/ # Your Markdown content
46
+ │ ├── index.md # Homepage
47
+ │ └── docs/ # Documentation pages
48
+ ├── public/ # Static assets
49
+ └── package.json
50
+ ```
51
+
52
+ Docd is a Nuxt layer — you can extend it with any standard Nuxt feature:
53
+
54
+ ```
55
+ my-docs/
56
+ ├── nuxt.config.ts # Extra modules and Nuxt configuration
57
+ ├── app/
58
+ │ ├── app.config.ts # Theme, navigation, and feature flags
59
+ │ ├── components/ # Your own Vue components (usable in Markdown)
60
+ │ ├── layouts/ # Custom layouts
61
+ │ └── pages/ # Extra pages outside of content/
62
+ └── server/ # Server-side code
63
+ ```
64
+
65
+ ## Configuration
66
+
67
+ Most things are controlled through `app.config.ts`:
68
+
69
+ ```ts
70
+ export default defineAppConfig({
71
+ docd: {
72
+ ui: {
73
+ toc: { title: "On this page", icon: "lucide:list" },
74
+ borderType: "dashed",
75
+ transition: {
76
+ name: "fade",
77
+ duration: 0.35,
78
+ easing: "easeOut",
79
+ },
80
+ },
81
+ },
82
+ });
83
+ ```
84
+
85
+ Full configuration reference: [docd.uithing.com](https://docd.uithing.com)
86
+
87
+ ## Built with
88
+
89
+ - [Nuxt](https://nuxt.com) — web framework
90
+ - [Nuxt Content](https://content.nuxt.com) — file-based content layer
91
+ - [UI Thing](https://uithing.com) — component library
92
+ - [Tailwind CSS](https://tailwindcss.com) — utility-first CSS
93
+ - [Nuxt Image](https://image.nuxt.com) — optimised image handling
94
+ - [nuxt-og-image](https://nuxtseo.com/og-image/getting-started/installation) — OG image generation
95
+ - [nuxt-llms](https://github.com/nuxt-hub/nuxt-llms) — LLM file generation
96
+
97
+ ## License
98
+
99
+ Published under the [MIT](./LICENSE.md) license.
@@ -4,8 +4,6 @@ import { addTemplate, createResolver, defineNuxtModule, logger, updateTemplates
4
4
 
5
5
  import {
6
6
  appendComponentApiBlocks,
7
- builtInComponentApiItems,
8
- isBuiltInProseDocFile,
9
7
  projectComponentApiConfig,
10
8
  warnForMissingComponentPaths,
11
9
  withAutoTitles,
@@ -84,21 +82,6 @@ export default defineNuxtModule({
84
82
  warn: (message: string) => log.warn(message),
85
83
  };
86
84
 
87
- if (isBuiltInProseDocFile(event.content)) {
88
- const { heading, items, explicit } = builtInComponentApiItems(event.content, context);
89
-
90
- if (!items.length) {
91
- return;
92
- }
93
-
94
- if (explicit) {
95
- warnForMissingComponentPaths(event.content, items, context);
96
- }
97
-
98
- event.content = await appendComponentApiBlocks(event.content, items, heading);
99
- return;
100
- }
101
-
102
85
  const componentApi = projectComponentApiConfig(event.content);
103
86
 
104
87
  if (!componentApi || componentApi === false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baybreezy/docd",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "A Nuxt layer for building documentation sites with UI Thing.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,19 +1,12 @@
1
1
  import { existsSync } from "node:fs";
2
- import { basename, extname } from "node:path";
3
2
 
4
3
  import { parseMarkdown } from "@nuxtjs/mdc/runtime";
5
4
 
6
5
  import {
7
- BUILT_IN_PROSE_COMPONENT_API_REGISTRY,
8
6
  DEFAULT_COMPONENT_API_LAYOUT,
9
- DEFAULT_COMPONENT_API_SECTIONS,
10
7
  componentLabelFromPath,
11
8
  componentNameFromPath,
12
- inferredBuiltInProseComponentPathFromSlug,
13
9
  normalizeComponentApiConfig,
14
- normalizeComponentApiLayout,
15
- normalizeComponentApiSections,
16
- type BuiltInComponentApiRegistryItem,
17
10
  type NormalizedComponentApiItem,
18
11
  } from "./component-api";
19
12
  import { resolveComponentApiSourcePath } from "./component-api-discovery";
@@ -103,62 +96,6 @@ export function withAutoTitles(items: NormalizedComponentApiItem[]) {
103
96
  }));
104
97
  }
105
98
 
106
- function registryItemsToNormalizedItems(
107
- items: readonly BuiltInComponentApiRegistryItem[],
108
- defaults: Pick<NormalizedComponentApiItem, "layout" | "sections">
109
- ) {
110
- return items.map(
111
- (item) =>
112
- ({
113
- path: item.path,
114
- title: item.title,
115
- layout: normalizeComponentApiLayout(item.layout, defaults.layout),
116
- sections: normalizeComponentApiSections(item.sections, defaults.sections),
117
- }) satisfies NormalizedComponentApiItem
118
- );
119
- }
120
-
121
- function inferredItem(
122
- slug: string,
123
- defaults: Pick<NormalizedComponentApiItem, "layout" | "sections">,
124
- context: ComponentApiTransformerContext
125
- ) {
126
- const inferredPath = inferredBuiltInProseComponentPathFromSlug(slug);
127
- const resolvedPath = resolveComponentApiSourcePath({
128
- rootDir: context.rootDir,
129
- layerRoot: context.layerRoot,
130
- path: inferredPath,
131
- });
132
-
133
- if (!existsSync(resolvedPath.absolutePath)) {
134
- return [];
135
- }
136
-
137
- return [
138
- {
139
- path: inferredPath,
140
- layout: defaults.layout,
141
- sections: [...defaults.sections],
142
- } satisfies NormalizedComponentApiItem,
143
- ];
144
- }
145
-
146
- function defaultItemSettings(config: ReturnType<typeof normalizeComponentApiConfig>) {
147
- if (config && config !== false) {
148
- return {
149
- heading: config.heading,
150
- layout: config.layout,
151
- sections: config.sections,
152
- };
153
- }
154
-
155
- return {
156
- heading: undefined,
157
- layout: DEFAULT_COMPONENT_API_LAYOUT,
158
- sections: [...DEFAULT_COMPONENT_API_SECTIONS],
159
- };
160
- }
161
-
162
99
  function buildComponentApiBlockSource(item: NormalizedComponentApiItem, title?: string) {
163
100
  const props = [`path="${escapeMdcProp(item.path)}"`];
164
101
 
@@ -314,67 +251,10 @@ function appendTocLinks(
314
251
  };
315
252
  }
316
253
 
317
- export function isBuiltInProseDocFile(file: ComponentApiTransformerContent) {
318
- return /^docs\/4\.prose\/.+\.md$/i.test(fileId(file));
319
- }
320
-
321
- export function builtInProseDocSlug(file: ComponentApiTransformerContent) {
322
- return basename(fileId(file), extname(fileId(file)));
323
- }
324
-
325
254
  export function projectComponentApiConfig(file: ComponentApiTransformerContent) {
326
255
  return normalizeComponentApiConfig(file.componentApi);
327
256
  }
328
257
 
329
- export function builtInComponentApiItems(
330
- file: ComponentApiTransformerContent,
331
- context: ComponentApiTransformerContext
332
- ) {
333
- const config = normalizeComponentApiConfig(file.componentApi);
334
-
335
- if (config === false) {
336
- return {
337
- heading: undefined,
338
- items: [] as NormalizedComponentApiItem[],
339
- explicit: false,
340
- };
341
- }
342
-
343
- if (config?.hasExplicitComponents) {
344
- return {
345
- heading: config.heading,
346
- items: withAutoTitles(config.components),
347
- explicit: true,
348
- };
349
- }
350
-
351
- const slug = builtInProseDocSlug(file);
352
- const defaults = defaultItemSettings(config);
353
- const registryEntry = BUILT_IN_PROSE_COMPONENT_API_REGISTRY[slug];
354
-
355
- if (registryEntry === false) {
356
- return {
357
- heading: defaults.heading,
358
- items: [] as NormalizedComponentApiItem[],
359
- explicit: false,
360
- };
361
- }
362
-
363
- if (Array.isArray(registryEntry)) {
364
- return {
365
- heading: defaults.heading,
366
- items: withAutoTitles(registryItemsToNormalizedItems(registryEntry, defaults)),
367
- explicit: false,
368
- };
369
- }
370
-
371
- return {
372
- heading: defaults.heading,
373
- items: inferredItem(slug, defaults, context),
374
- explicit: false,
375
- };
376
- }
377
-
378
258
  export function warnForMissingComponentPaths(
379
259
  file: ComponentApiTransformerContent,
380
260
  items: NormalizedComponentApiItem[],
@@ -36,25 +36,25 @@ export const BUILT_IN_PROSE_COMPONENT_API_REGISTRY: Record<
36
36
  false | readonly BuiltInComponentApiRegistryItem[]
37
37
  > = {
38
38
  field: [
39
- { path: "app/components/content/prose/ProseField.global.vue" },
40
- { path: "app/components/content/prose/ProseFieldGroup.global.vue" },
39
+ { path: "app/components/content/prose/ProseField.vue" },
40
+ { path: "app/components/content/prose/ProseFieldGroup.vue" },
41
41
  ],
42
42
  images: [
43
- { path: "app/components/content/prose/ProseImg.global.vue" },
44
- { path: "app/components/content/prose/ProseColorModeImage.global.vue" },
43
+ { path: "app/components/content/prose/ProseImg.vue" },
44
+ { path: "app/components/content/prose/ProseColorModeImage.vue" },
45
45
  ],
46
46
  "icon-list": [
47
- { path: "app/components/content/prose/ProseIconList.global.vue" },
48
- { path: "app/components/content/prose/ProseLi.global.vue" },
47
+ { path: "app/components/content/prose/ProseIconList.vue" },
48
+ { path: "app/components/content/prose/ProseLi.vue" },
49
49
  ],
50
50
  "package-manager": [
51
- { path: "app/components/content/prose/ProsePmInstall.global.vue" },
52
- { path: "app/components/content/prose/ProsePmRun.global.vue" },
53
- { path: "app/components/content/prose/ProsePmX.global.vue" },
51
+ { path: "app/components/content/prose/ProsePmInstall.vue" },
52
+ { path: "app/components/content/prose/ProsePmRun.vue" },
53
+ { path: "app/components/content/prose/ProsePmX.vue" },
54
54
  ],
55
55
  steps: [
56
- { path: "app/components/content/prose/ProseSteps.global.vue" },
57
- { path: "app/components/content/prose/ProseStep.global.vue" },
56
+ { path: "app/components/content/prose/ProseSteps.vue" },
57
+ { path: "app/components/content/prose/ProseStep.vue" },
58
58
  ],
59
59
  "code-snippet": false,
60
60
  typography: false,
@@ -125,7 +125,7 @@ export function componentNameFromSlug(slug: string) {
125
125
  }
126
126
 
127
127
  export function inferredBuiltInProseComponentPathFromSlug(slug: string) {
128
- return `${BUILT_IN_PROSE_COMPONENT_ROOT}${componentNameFromSlug(slug)}.global.vue`;
128
+ return `${BUILT_IN_PROSE_COMPONENT_ROOT}${componentNameFromSlug(slug)}.vue`;
129
129
  }
130
130
 
131
131
  export function normalizeComponentApiLayout(