@doxbrix/doxloop-generator-markdoc 0.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.
package/LICENSE ADDED
@@ -0,0 +1,93 @@
1
+ DOXLOOP PROPRIETARY SOFTWARE LICENSE
2
+ Version 1.0, 21 July 2026
3
+
4
+ Copyright (c) 2026 Doxbrix. All rights reserved.
5
+
6
+ 1. Definitions
7
+
8
+ "Software" means the Doxloop software and all source code, object code,
9
+ documentation, assets, and other materials distributed with this license.
10
+
11
+ 2. Limited License to Use
12
+
13
+ Subject to your compliance with this license, Doxbrix grants you a worldwide,
14
+ royalty-free, non-exclusive, non-transferable, and non-sublicensable license to
15
+ download, install, and run unmodified copies of the Software for any lawful
16
+ personal or commercial purpose.
17
+
18
+ You may make only the copies technically necessary to download, install, run,
19
+ and back up the Software. No other rights are granted.
20
+
21
+ 3. Restrictions
22
+
23
+ Unless you first obtain explicit written permission from Doxbrix, you may not:
24
+
25
+ a. copy or reproduce the Software except as expressly permitted in Section 2;
26
+ b. modify, adapt, translate, or create derivative works of the Software;
27
+ c. distribute, publish, sublicense, sell, rent, lease, transfer, mirror,
28
+ repackage, or otherwise make the Software or any part of it available to
29
+ another person or entity;
30
+ d. incorporate any source code from the Software into another work, product,
31
+ or service;
32
+ e. remove, alter, or obscure any copyright, license, attribution, or other
33
+ proprietary notice; or
34
+ f. reverse engineer, decompile, or disassemble the Software, except to the
35
+ limited extent that applicable law expressly permits despite this
36
+ restriction.
37
+
38
+ For clarity, prohibited redistribution includes publishing a copy or fork of
39
+ the source code outside the rights that GitHub's Terms of Service require for a
40
+ public repository, and republishing any Doxloop package or a modified version
41
+ of it to a package registry.
42
+
43
+ 4. GitHub Public Repository Rights
44
+
45
+ If the Software is made available in a public repository on GitHub, GitHub and
46
+ GitHub users receive the limited rights required by GitHub's applicable Terms
47
+ of Service, including rights to view and fork the repository through GitHub's
48
+ service. Those platform rights do not grant permission to use, copy, modify, or
49
+ redistribute the Software beyond GitHub's service or beyond the permissions in
50
+ Section 2.
51
+
52
+ 5. Ownership and Reservation of Rights
53
+
54
+ The Software is licensed, not sold. Doxbrix and its licensors retain all
55
+ right, title, and interest in and to the Software. All rights not expressly
56
+ granted by this license are reserved. No patent, trademark, or other license is
57
+ granted by implication or estoppel.
58
+
59
+ 6. Third-Party Materials
60
+
61
+ Third-party software and materials included with or used by the Software remain
62
+ subject to their respective licenses. This license does not restrict any rights
63
+ granted under those third-party licenses.
64
+
65
+ 7. Termination
66
+
67
+ This license terminates automatically if you violate any of its terms. Upon
68
+ termination, you must stop using the Software and delete all copies in your
69
+ possession or control, except copies that applicable law requires you to keep.
70
+
71
+ 8. Disclaimer of Warranty
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND "AS AVAILABLE," WITHOUT WARRANTIES OR
74
+ CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WARRANTIES OF
75
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT.
76
+
77
+ 9. Limitation of Liability
78
+
79
+ TO THE MAXIMUM EXTENT PERMITTED BY LAW, DOXBRIX AND ITS LICENSORS WILL NOT BE
80
+ LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR
81
+ PUNITIVE DAMAGES, OR FOR ANY LOSS OF DATA, PROFITS, REVENUE, BUSINESS, OR
82
+ GOODWILL, ARISING FROM OR RELATED TO THE SOFTWARE OR THIS LICENSE, REGARDLESS OF
83
+ THE THEORY OF LIABILITY AND EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
84
+
85
+ 10. Severability
86
+
87
+ If any provision of this license is held unenforceable, that provision will be
88
+ enforced to the maximum extent permitted and the remaining provisions will
89
+ remain in effect.
90
+
91
+ Use of the Software indicates acceptance of this license. For permissions not
92
+ granted here, contact Doxbrix and obtain explicit written permission before
93
+ proceeding.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @doxbrix/doxloop-generator-markdoc
2
+
3
+ Markdoc support for [Doxloop](https://github.com/doxbrix/doxloop). This package
4
+ connects Doxloop to a native Markdoc documentation project and includes the
5
+ `doxloop-markdoc` authoring skill used by supported coding agents.
6
+
7
+ ## Install
8
+
9
+ Install the Doxloop CLI and this generator in your documentation project:
10
+
11
+ ```bash
12
+ npm install --save-dev \
13
+ @doxbrix/doxloop \
14
+ @doxbrix/doxloop-generator-markdoc
15
+ ```
16
+
17
+ Node.js 20.12 or later is required.
18
+
19
+ ## Create documentation
20
+
21
+ Initialize a Markdoc documentation project and connect the product source that
22
+ Doxloop should research:
23
+
24
+ ```bash
25
+ npx doxloop init . \
26
+ --source product=../my-product \
27
+ --generator markdoc
28
+
29
+ npx doxloop create
30
+ ```
31
+
32
+ Doxloop scaffolds Markdoc configuration, content, generator-native navigation,
33
+ and the project-local authoring skill.
34
+
35
+ ## Use with an existing project
36
+
37
+ Install Markdoc support in an existing Doxloop project with:
38
+
39
+ ```bash
40
+ npx doxloop generator add markdoc
41
+ ```
42
+
43
+ Adding the package does not convert existing content or change the generator
44
+ selected in `.doxloop/project.json`.
45
+
46
+ ## Preview and verify
47
+
48
+ ```bash
49
+ npx doxloop preview --open
50
+ npx doxloop test
51
+ npm run build
52
+ ```
53
+
54
+ | Detail | Value |
55
+ | --- | --- |
56
+ | Content | Markdoc (`.md`) |
57
+ | Native build | `npm run build` |
58
+ | Build output | `dist/` |
59
+
60
+ Run `npx doxloop generator info markdoc` to inspect the installed adapter.
61
+
62
+ ## License
63
+
64
+ [Doxloop Proprietary Software License](./LICENSE)
@@ -0,0 +1,31 @@
1
+ import { type GeneratorPreviewOptions, type GeneratorScaffoldContext, type GeneratorValidationContext, type ValidationIssue } from '@doxbrix/doxloop/generator-api';
2
+ declare const adapter: {
3
+ apiVersion: 1;
4
+ id: string;
5
+ displayName: string;
6
+ packageName: string;
7
+ packageVersion: string;
8
+ authoring: {
9
+ skillName: string;
10
+ skillDirectory: string;
11
+ };
12
+ project: {
13
+ defaultContentDir: string;
14
+ pageExtensions: string[];
15
+ gitignore: string[];
16
+ contentFormat: "markdown";
17
+ };
18
+ build: {
19
+ command: string;
20
+ outputDir: string;
21
+ };
22
+ scaffold: typeof scaffoldMarkdoc;
23
+ preview: typeof startMarkdocPreview;
24
+ resolveLocalAsset({ root, reference }: import("@doxbrix/doxloop/generator-api").GeneratorAssetContext): string | undefined;
25
+ validate: typeof validateMarkdoc;
26
+ };
27
+ export default adapter;
28
+ declare function scaffoldMarkdoc(context: GeneratorScaffoldContext): Promise<void>;
29
+ declare function startMarkdocPreview(options: GeneratorPreviewOptions): Promise<void>;
30
+ declare function validateMarkdoc(context: GeneratorValidationContext): Promise<ValidationIssue[]>;
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,eAAe,EACrB,MAAM,gCAAgC,CAAA;AAoBvC,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CA2BX,CAAA;AAEF,eAAe,OAAO,CAAA;AAEtB,iBAAe,eAAe,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyJ/E;AAED,iBAAe,mBAAmB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CASlF;AAED,iBAAe,eAAe,CAC5B,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,eAAe,EAAE,CAAC,CA0E5B"}
package/dist/index.js ADDED
@@ -0,0 +1,257 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { join, relative } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { DoxloopError, defineGenerator, } from '@doxbrix/doxloop/generator-api';
6
+ import { ensureNodeModule, isRecord, pathExists, readPackageJson, resolvePublicAsset, runCommand, serveStaticDirectory, slugFromTitle, writeJsonFile, } from '@doxbrix/doxloop/generator-runtime';
7
+ const PACKAGE_NAME = '@doxbrix/doxloop-generator-markdoc';
8
+ const PACKAGE_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
9
+ const adapter = defineGenerator({
10
+ apiVersion: 1,
11
+ id: 'markdoc',
12
+ displayName: 'Markdoc',
13
+ packageName: PACKAGE_NAME,
14
+ packageVersion: PACKAGE_VERSION,
15
+ authoring: {
16
+ skillName: 'doxloop-markdoc',
17
+ skillDirectory: fileURLToPath(new URL('../skills/doxloop-markdoc', import.meta.url)),
18
+ },
19
+ project: {
20
+ defaultContentDir: 'docs',
21
+ pageExtensions: ['.md'],
22
+ gitignore: ['dist/', 'node_modules/'],
23
+ contentFormat: 'markdown',
24
+ },
25
+ build: { command: 'npm run build', outputDir: 'dist' },
26
+ scaffold: scaffoldMarkdoc,
27
+ preview: startMarkdocPreview,
28
+ resolveLocalAsset({ root, reference }) {
29
+ return reference.startsWith('/assets/')
30
+ ? resolvePublicAsset(root, 'assets', reference.slice('/assets'.length))
31
+ : undefined;
32
+ },
33
+ validate: validateMarkdoc,
34
+ });
35
+ export default adapter;
36
+ async function scaffoldMarkdoc(context) {
37
+ const { root, title, contentDir } = context;
38
+ await mkdir(join(root, contentDir), { recursive: true });
39
+ await mkdir(join(root, 'scripts'), { recursive: true });
40
+ await mkdir(join(root, 'assets'), { recursive: true });
41
+ await mkdir(join(root, 'assets', 'guides'), { recursive: true });
42
+ const existing = await readPackageJson(root);
43
+ await writeJsonFile(join(root, 'package.json'), {
44
+ ...existing,
45
+ name: typeof existing.name === 'string' && existing.name
46
+ ? existing.name
47
+ : slugFromTitle(title),
48
+ private: true,
49
+ version: typeof existing.version === 'string' && existing.version
50
+ ? existing.version
51
+ : '0.0.0',
52
+ type: 'module',
53
+ scripts: {
54
+ ...(isRecord(existing.scripts) ? existing.scripts : {}),
55
+ dev: 'doxloop preview',
56
+ build: 'node scripts/build.mjs',
57
+ 'docs:test': 'doxloop test',
58
+ },
59
+ dependencies: {
60
+ ...(isRecord(existing.dependencies) ? existing.dependencies : {}),
61
+ '@markdoc/markdoc': '0.5.8',
62
+ 'gray-matter': '4.0.3',
63
+ },
64
+ devDependencies: {
65
+ ...(isRecord(existing.devDependencies) ? existing.devDependencies : {}),
66
+ [context.corePackage.name]: `^${context.corePackage.version}`,
67
+ [context.generatorPackage.name]: `^${context.generatorPackage.version}`,
68
+ },
69
+ engines: {
70
+ ...(isRecord(existing.engines) ? existing.engines : {}),
71
+ node: '>=20.12.0',
72
+ },
73
+ });
74
+ await writeFile(join(root, 'markdoc.config.mjs'), `export default {
75
+ tags: {
76
+ callout: {
77
+ render: 'aside',
78
+ attributes: {
79
+ title: { type: String },
80
+ },
81
+ },
82
+ },
83
+ }
84
+ `, { encoding: 'utf8', flag: 'wx' });
85
+ await writeJsonFile(join(root, 'navigation.json'), [
86
+ { title: title, file: 'index.md', href: '/' },
87
+ { title: 'Quickstart', file: 'quickstart.md', href: '/quickstart/' },
88
+ ]);
89
+ await writeFile(join(root, 'assets', 'site.css'), `:root { font-family: Inter, system-ui, sans-serif; --brand: #4f46e5; color: #1f2937; }
90
+ body { margin: 0; } header { border-bottom: 1px solid #e5e7eb; padding: 1rem 2rem; }
91
+ .brand { color: var(--brand); font-weight: 700; text-decoration: none; }
92
+ .markdoc-layout { display: grid; grid-template-columns: 16rem minmax(0, 48rem); gap: 3rem; max-width: 72rem; margin: 0 auto; padding: 2rem; }
93
+ nav ul { list-style: none; padding: 0; } nav a { display: block; padding: .5rem; }
94
+ .markdoc-content { line-height: 1.7; min-width: 0; } aside { border-left: 4px solid var(--brand); padding: 1rem; background: #eef2ff; }
95
+ pre { overflow: auto; padding: 1rem; background: #111827; color: #f9fafb; border-radius: .5rem; }
96
+ @media (max-width: 720px) { .markdoc-layout { grid-template-columns: 1fr; } }
97
+ `, { encoding: 'utf8', flag: 'wx' });
98
+ await writeFile(join(root, 'scripts', 'build.mjs'), `import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
99
+ import { dirname, join } from 'node:path'
100
+ import Markdoc from '@markdoc/markdoc'
101
+ import matter from 'gray-matter'
102
+ import config from '../markdoc.config.mjs'
103
+
104
+ const root = process.cwd()
105
+ const navigation = JSON.parse(await readFile(join(root, 'navigation.json'), 'utf8'))
106
+ const output = join(root, 'dist')
107
+ await rm(output, { recursive: true, force: true })
108
+ await mkdir(output, { recursive: true })
109
+
110
+ const escapeHtml = (value) => String(value).replace(/[&<>"']/g, (character) => ({
111
+ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;',
112
+ })[character])
113
+
114
+ for (const item of navigation) {
115
+ const sourcePath = join(root, ${JSON.stringify(contentDir)}, item.file)
116
+ const parsed = matter(await readFile(sourcePath, 'utf8'))
117
+ const ast = Markdoc.parse(parsed.content)
118
+ const errors = Markdoc.validate(ast, config)
119
+ if (errors.length > 0) {
120
+ throw new Error(\`\${item.file}: \${errors.map((error) => error.error?.message ?? error.type).join(', ')}\`)
121
+ }
122
+ const rendered = Markdoc.renderers.html(Markdoc.transform(ast, config))
123
+ const target = item.href === '/' ? join(output, 'index.html') : join(output, item.href, 'index.html')
124
+ await mkdir(dirname(target), { recursive: true })
125
+ const nav = navigation.map((entry) => \`<li><a href="\${entry.href}">\${escapeHtml(entry.title)}</a></li>\`).join('')
126
+ const title = parsed.data.title ?? item.title
127
+ const description = parsed.data.description ?? ''
128
+ await writeFile(target, \`<!doctype html>
129
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
130
+ <meta name="description" content="\${escapeHtml(description)}"><title>\${escapeHtml(title)}</title><link rel="stylesheet" href="/site.css"></head>
131
+ <body><header><a class="brand" href="/">${escapeForTemplate(title)}</a></header><div class="markdoc-layout">
132
+ <aside class="markdoc-sidebar"><nav aria-label="Documentation"><ul>\${nav}</ul></nav></aside>
133
+ <main class="markdoc-content"><article>\${rendered}</article></main></div></body></html>\`)
134
+ }
135
+ await cp(join(root, 'assets', 'site.css'), join(output, 'site.css'))
136
+ await cp(join(root, 'assets', 'guides'), join(output, 'assets', 'guides'), { recursive: true })
137
+ console.log(\`Built \${navigation.length} Markdoc pages in dist/\`)
138
+ `, { encoding: 'utf8', flag: 'wx' });
139
+ await writeFile(join(root, contentDir, 'index.md'), `---
140
+ title: ${JSON.stringify(title)}
141
+ description: "Understand what ${title} helps you accomplish and choose your first workflow."
142
+ ---
143
+
144
+ # ${title}
145
+
146
+ <!-- doxloop:starter-page -->
147
+
148
+ {% callout title="Starter content" %}
149
+ The authoring agent will replace this starter with an evidence-backed product overview.
150
+ {% /callout %}
151
+
152
+ [Follow the quickstart](/quickstart/) to reach your first successful result.
153
+ `, { encoding: 'utf8', flag: 'wx' });
154
+ await writeFile(join(root, contentDir, 'quickstart.md'), `---
155
+ title: "Quickstart"
156
+ description: "Reach your first successful result with verified product instructions."
157
+ ---
158
+
159
+ # Quickstart
160
+
161
+ <!-- doxloop:starter-page -->
162
+
163
+ 1. Confirm prerequisites from the configured product source.
164
+ 2. Complete the first supported workflow.
165
+ 3. Verify the observable result.
166
+ `, { encoding: 'utf8', flag: 'wx' });
167
+ }
168
+ async function startMarkdocPreview(options) {
169
+ await ensureNodeModule(options.root, '@markdoc/markdoc/package.json', 'Markdoc');
170
+ const code = await runCommand(process.execPath, [join(options.root, 'scripts', 'build.mjs')], options.root);
171
+ if (code !== 0)
172
+ throw new DoxloopError('Markdoc build failed.', 2);
173
+ await serveStaticDirectory(options, 'dist', 'Markdoc');
174
+ }
175
+ async function validateMarkdoc(context) {
176
+ const issues = [];
177
+ for (const file of [
178
+ 'package.json',
179
+ 'markdoc.config.mjs',
180
+ 'navigation.json',
181
+ 'scripts/build.mjs',
182
+ ]) {
183
+ if (!(await pathExists(join(context.root, file)))) {
184
+ issues.push({
185
+ severity: 'error',
186
+ code: 'missing-generator-file',
187
+ message: `Markdoc project is missing ${file}.`,
188
+ file,
189
+ });
190
+ }
191
+ }
192
+ const navigationPath = join(context.root, 'navigation.json');
193
+ if (!(await pathExists(navigationPath)))
194
+ return issues;
195
+ let navigation;
196
+ try {
197
+ navigation = JSON.parse(await readFile(navigationPath, 'utf8'));
198
+ }
199
+ catch (error) {
200
+ return [
201
+ ...issues,
202
+ {
203
+ severity: 'error',
204
+ code: 'generator-config',
205
+ message: `Cannot parse navigation.json: ${errorMessage(error)}`,
206
+ file: 'navigation.json',
207
+ },
208
+ ];
209
+ }
210
+ if (!Array.isArray(navigation)) {
211
+ issues.push({
212
+ severity: 'error',
213
+ code: 'generator-config',
214
+ message: 'navigation.json must contain an array.',
215
+ file: 'navigation.json',
216
+ });
217
+ return issues;
218
+ }
219
+ const navigationFiles = new Set(navigation
220
+ .filter(isRecord)
221
+ .map((item) => item.file)
222
+ .filter((file) => typeof file === 'string'));
223
+ const pageFiles = new Set(context.pages.map((page) => relative(context.contentRoot, page).split('\\').join('/')));
224
+ for (const file of navigationFiles) {
225
+ if (!pageFiles.has(file)) {
226
+ issues.push({
227
+ severity: 'error',
228
+ code: 'missing-page',
229
+ message: `Markdoc navigation references missing page "${file}".`,
230
+ file: 'navigation.json',
231
+ });
232
+ }
233
+ }
234
+ for (const file of pageFiles) {
235
+ if (!navigationFiles.has(file)) {
236
+ issues.push({
237
+ severity: 'error',
238
+ code: 'unnavigated-page',
239
+ message: `Page "${file}" is not in Markdoc navigation.`,
240
+ file,
241
+ });
242
+ }
243
+ }
244
+ return issues;
245
+ }
246
+ function escapeForTemplate(value) {
247
+ return value
248
+ .replaceAll('&', '&amp;')
249
+ .replaceAll('<', '&lt;')
250
+ .replaceAll('>', '&gt;')
251
+ .replaceAll('"', '&quot;')
252
+ .replaceAll("'", '&#39;');
253
+ }
254
+ function errorMessage(error) {
255
+ return error instanceof Error ? error.message : String(error);
256
+ }
257
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@doxbrix/doxloop-generator-markdoc",
3
+ "version": "0.1.0",
4
+ "description": "Markdoc generator adapter and authoring skill for Doxloop.",
5
+ "type": "module",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/doxbrix/doxloop.git",
10
+ "directory": "packages/generator-markdoc"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "skills"
22
+ ],
23
+ "doxloop": {
24
+ "type": "generator",
25
+ "apiVersion": 1,
26
+ "id": "markdoc",
27
+ "skill": "./skills/doxloop-markdoc"
28
+ },
29
+ "publishConfig": {
30
+ "registry": "https://registry.npmjs.org",
31
+ "access": "public"
32
+ },
33
+ "peerDependencies": {
34
+ "@doxbrix/doxloop": "^0.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.15.3",
38
+ "typescript": "^5.8.3",
39
+ "@doxbrix/doxloop": "0.1.0"
40
+ },
41
+ "engines": {
42
+ "node": ">=20.12.0"
43
+ },
44
+ "scripts": {
45
+ "build": "rm -rf dist && tsc -p tsconfig.json",
46
+ "typecheck": "tsc --noEmit -p tsconfig.json",
47
+ "validate:skill": "python3 ../../scripts/validate-skill.py skills/doxloop-markdoc"
48
+ }
49
+ }
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: doxloop-markdoc
3
+ description: Author and maintain native Markdoc documentation, including Markdown, Markdoc tags, schemas, navigation metadata, renderer-safe content, and static output. Use for Doxloop projects whose generator is markdoc.
4
+ ---
5
+
6
+ # Doxloop Markdoc
7
+
8
+ Use this skill with `$doxloop-authoring`. Use only tags, nodes, and schemas
9
+ registered by the Markdoc project.
10
+
11
+ ## Work natively
12
+
13
+ 1. Confirm `.doxloop/project.json` selects `markdoc`.
14
+ 2. Read [references/project-format.md](references/project-format.md).
15
+ 3. Inspect `markdoc.config.mjs`, `navigation.json`, the renderer, and existing
16
+ pages.
17
+ 4. Keep pages in `docs/` with `title` and outcome-focused `description`.
18
+ 5. Maintain navigation and stable routes when pages change.
19
+
20
+ Implement the semantic top/left navigation plan from `$doxloop-authoring` in
21
+ `navigation.json` and the renderer's supported header and sidebar structures.
22
+ Preserve planned labels, order, hierarchy, and routes; omit empty template
23
+ groups and verify every page is reachable exactly once.
24
+
25
+ Prefer CommonMark unless a registered tag adds meaningful semantics. Never
26
+ invent a tag without defining and testing its schema and renderer. Preserve the
27
+ parse, validate, transform, and render pipeline. Map branding through renderer
28
+ templates and shared CSS, not page-specific inline presentation.
29
+
30
+ ## Verify
31
+
32
+ Run `doxloop test`, then `npm run build`. Treat Markdoc validation diagnostics,
33
+ unknown tags, invalid attributes, unsafe rendered HTML, missing navigation, and
34
+ broken routes as failures. Inspect representative output with
35
+ `doxloop preview --open`.
36
+
37
+ Do not emit JSX, generator-specific directives, or edit `dist/`.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Markdoc"
3
+ short_description: "Author and maintain native Markdoc documentation"
4
+ default_prompt: "Use $doxloop-markdoc to author documentation using the native Markdoc project format."
@@ -0,0 +1,35 @@
1
+ # Markdoc project format
2
+
3
+ - Content root: `docs/`
4
+ - Schema/configuration: `markdoc.config.mjs`
5
+ - Navigation and routes: `navigation.json`
6
+ - Static renderer: `scripts/build.mjs`
7
+ - Required frontmatter: `title` and `description`
8
+ - Custom syntax: `{% tag attribute="value" %}...{% /tag %}`
9
+ - Use only tags registered in `markdoc.config.mjs`.
10
+ - Preserve `parse` → `validate` → `transform` → `renderers.html`.
11
+ - Build: `npm run build`; output: `dist/`
12
+
13
+ ## Navigation and routes
14
+
15
+ - Keep every reader page in `navigation.json` exactly once.
16
+ - Preserve explicit route identifiers when reorganizing labels or groups.
17
+ - Validate navigation targets against source files before building.
18
+
19
+ ## Tags and rendering
20
+
21
+ - Define attributes, types, defaults, required values, and child constraints in
22
+ `markdoc.config.mjs`.
23
+ - Prefer transform-safe data over raw HTML.
24
+ - Escape content in custom renderers and preserve semantic HTML.
25
+ - Keep theme tokens and layouts in renderer-owned assets.
26
+ - Put committed guide screenshots under `assets/guides/<guide>/`, reference
27
+ them as `/assets/guides/<guide>/<image>.png`, and preserve the scaffolded
28
+ build copy step that publishes them.
29
+
30
+ ## Common failures
31
+
32
+ - Unknown tags may parse but fail validation.
33
+ - Attribute expressions can produce unexpected types after transformation.
34
+ - Rendering without validation can publish malformed or unsafe output.
35
+ - `dist/` is generated and never a source of documentation truth.