docs-ready 0.6.0 → 0.9.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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 udhaykumarbala
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,321 @@
1
+ # docs-ready
2
+
3
+ **Make your docs AI-ready. Keep them that way.**
4
+
5
+ `docs-ready` generates `llms.txt`, `llms-full.txt`, and `ai-context.md` from your existing documentation, then guards them against staleness and validates them for format compliance.
6
+
7
+ Born from real production work making [0G Labs](https://0g.ai) docs AI-ready.
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ # Run directly
15
+ npx docs-ready
16
+
17
+ # Or install globally
18
+ npm install -g docs-ready
19
+ ```
20
+
21
+ Requires Node.js 18+.
22
+
23
+ ## Quick Start
24
+
25
+ ```bash
26
+ # 1. Initialize config
27
+ docs-ready init
28
+
29
+ # 2. Generate AI-facing files
30
+ docs-ready generate
31
+
32
+ # 3. Check for staleness
33
+ docs-ready guard
34
+
35
+ # 4. Validate output
36
+ docs-ready validate
37
+ ```
38
+
39
+ `init` detects your framework and deployment platform, then writes a `.docs-ready.yaml` config file. `generate` produces the output files. `guard` monitors upstream sources for version bumps, endpoint changes, and keyword drift. `validate` lints the generated files for format, dead links, token limits, and coverage.
40
+
41
+ ---
42
+
43
+ ## Three Pillars
44
+
45
+ ### Generate
46
+
47
+ Produces three AI-facing files from your documentation source:
48
+
49
+ | File | Purpose |
50
+ |------|---------|
51
+ | `llms.txt` | Structured index of your docs with title, description, and page listing |
52
+ | `llms-full.txt` | Full content of every doc page, concatenated and cleaned |
53
+ | `ai-context.md` | Curated context page with key pages, summaries, and extra sections |
54
+
55
+ MDX components are cleaned automatically. Token counts are reported for each file.
56
+
57
+ ### Guard
58
+
59
+ Monitors upstream sources and flags when your AI docs may be stale:
60
+
61
+ - **npm monitor** -- checks if documented npm package versions are outdated
62
+ - **GitHub releases monitor** -- checks for new releases in tracked repositories
63
+ - **Endpoint monitor** -- verifies that documented API endpoints are still reachable
64
+ - **README keyword monitor** -- scans upstream READMEs for keyword drift
65
+
66
+ Results can be output as console text, JSON, or markdown. Guard checks run in parallel for speed.
67
+
68
+ ### Validate
69
+
70
+ Lints AI-facing docs for compliance:
71
+
72
+ - **Format** -- checks that `llms.txt` follows the expected structure
73
+ - **Links** -- verifies internal and external links are not dead
74
+ - **Tokens** -- ensures total token count stays within the configured limit (default: 150,000)
75
+ - **Coverage** -- checks that generated docs cover a sufficient percentage of source pages
76
+
77
+ ---
78
+
79
+ ## Configuration
80
+
81
+ `docs-ready init` generates a `.docs-ready.yaml` file. You can also use `.docs-ready.yml` or `.docs-ready.json`.
82
+
83
+ ```yaml
84
+ # --- Project metadata (required) ---
85
+ title: "My Project"
86
+ description: "Project documentation"
87
+ url: "https://docs.example.com"
88
+
89
+ # --- Documentation source ---
90
+ docs:
91
+ dir: "./docs"
92
+ include:
93
+ - "**/*.md"
94
+ - "**/*.mdx"
95
+ exclude:
96
+ - "**/node_modules/**"
97
+ - "**/_*"
98
+
99
+ # --- Generation ---
100
+ generate:
101
+ llms_txt: true
102
+ llms_full_txt: true
103
+ ai_context: true
104
+ output_dir: "./build"
105
+ sections: # optional: group pages into sections
106
+ - title: "Getting Started"
107
+ patterns: ["getting-started/**"]
108
+ ai_context_config: # optional: customize ai-context.md
109
+ key_pages:
110
+ - path: "intro.md"
111
+ section: "Overview"
112
+ extra_sections:
113
+ - title: "Architecture"
114
+ source: "architecture.md"
115
+
116
+ # --- Guard ---
117
+ guard:
118
+ npm_packages:
119
+ - name: "@0glabs/sdk"
120
+ label: "0G SDK"
121
+ github_releases:
122
+ - repo: "0glabs/0g-chain"
123
+ label: "0G Chain"
124
+ endpoints:
125
+ - url: "https://api.example.com/v1/health"
126
+ label: "API Health"
127
+ expected_status: [200]
128
+ readme_scans:
129
+ - repo: "0glabs/0g-chain"
130
+ keywords: ["install", "quickstart", "api"]
131
+ workflow:
132
+ enabled: true
133
+ schedule: "0 9 */3 * *"
134
+ create_issues: true
135
+ labels: ["ai-context-review", "documentation"]
136
+
137
+ # --- Deployment ---
138
+ deploy:
139
+ platform: "vercel" # vercel | netlify | cloudflare | none
140
+ cors:
141
+ enabled: true
142
+ origins: ["*"]
143
+
144
+ # --- Validation ---
145
+ validate:
146
+ max_tokens: 150000
147
+ check_links: true
148
+ check_coverage: true
149
+ coverage_threshold: 0.95
150
+ ```
151
+
152
+ ---
153
+
154
+ ## CLI Reference
155
+
156
+ ### Global Flags
157
+
158
+ | Flag | Description |
159
+ |------|-------------|
160
+ | `--quiet` | Only show errors |
161
+ | `--verbose` | Show debug logging |
162
+ | `--no-color` | Disable colored output |
163
+ | `--version` | Print version |
164
+ | `--help` | Show help |
165
+
166
+ ### `docs-ready init`
167
+
168
+ Initialize a `.docs-ready.yaml` config file. Auto-detects framework, docs directory, and deployment platform.
169
+
170
+ ```bash
171
+ docs-ready init
172
+ ```
173
+
174
+ ### `docs-ready generate`
175
+
176
+ Generate AI-facing documentation files based on your config.
177
+
178
+ ```bash
179
+ docs-ready generate
180
+ docs-ready generate --dry-run
181
+ docs-ready generate --only llms-txt
182
+ docs-ready generate --watch
183
+ ```
184
+
185
+ | Flag | Description |
186
+ |------|-------------|
187
+ | `--dry-run` | Show what would be generated without writing files |
188
+ | `--only <type>` | Generate only one file: `llms-txt`, `llms-full`, or `ai-context` |
189
+ | `--watch` | Watch for changes and regenerate automatically |
190
+
191
+ ### `docs-ready guard`
192
+
193
+ Run staleness checks against upstream sources.
194
+
195
+ ```bash
196
+ docs-ready guard
197
+ docs-ready guard --output json
198
+ docs-ready guard --output markdown
199
+ docs-ready guard --init-workflow
200
+ ```
201
+
202
+ | Flag | Description |
203
+ |------|-------------|
204
+ | `--output <format>` | Output format: `console` (default), `json`, or `markdown` |
205
+ | `--init-workflow` | Generate a GitHub Actions workflow at `.github/workflows/docs-ready-guard.yml` |
206
+
207
+ ### `docs-ready validate`
208
+
209
+ Lint and validate generated AI-facing docs.
210
+
211
+ ```bash
212
+ docs-ready validate
213
+ docs-ready validate --no-links
214
+ ```
215
+
216
+ | Flag | Description |
217
+ |------|-------------|
218
+ | `--no-links` | Skip link checking |
219
+
220
+ ---
221
+
222
+ ## Frameworks Supported
223
+
224
+ `docs-ready init` auto-detects the following frameworks and sets the correct docs directory:
225
+
226
+ | Framework | Docs Directory |
227
+ |-----------|---------------|
228
+ | Docusaurus | `docs/` |
229
+ | VitePress | `docs/` or custom |
230
+ | MkDocs | `docs/` |
231
+ | Starlight | `src/content/docs/` |
232
+ | Plain Markdown | `./` or custom |
233
+
234
+ Framework-specific readers handle sidebar configs, frontmatter conventions, and file organization for each.
235
+
236
+ ---
237
+
238
+ ## Deployment
239
+
240
+ `docs-ready` generates platform-specific configuration to serve AI-facing files with proper CORS headers so LLMs can fetch them.
241
+
242
+ ### Vercel
243
+
244
+ Adds rewrite rules and CORS headers to `vercel.json`:
245
+
246
+ ```json
247
+ {
248
+ "headers": [
249
+ {
250
+ "source": "/llms.txt",
251
+ "headers": [
252
+ { "key": "Access-Control-Allow-Origin", "value": "*" },
253
+ { "key": "Content-Type", "value": "text/plain; charset=utf-8" }
254
+ ]
255
+ }
256
+ ]
257
+ }
258
+ ```
259
+
260
+ ### Netlify
261
+
262
+ Adds headers to `_headers` or `netlify.toml`:
263
+
264
+ ```
265
+ /llms.txt
266
+ Access-Control-Allow-Origin: *
267
+ Content-Type: text/plain; charset=utf-8
268
+ ```
269
+
270
+ ### Cloudflare
271
+
272
+ Adds rules to `_headers` for Cloudflare Pages:
273
+
274
+ ```
275
+ /llms.txt
276
+ Access-Control-Allow-Origin: *
277
+ Content-Type: text/plain; charset=utf-8
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Comparison
283
+
284
+ | Feature | docs-ready | docusaurus-plugin-llms | afdocs |
285
+ |---------|-----------|----------------------|--------|
286
+ | `llms.txt` generation | Yes | Yes | Yes |
287
+ | `llms-full.txt` generation | Yes | Yes | Yes |
288
+ | `ai-context.md` generation | Yes | No | No |
289
+ | Staleness monitoring (guard) | Yes | No | No |
290
+ | Validation / linting | Yes | No | No |
291
+ | GitHub Actions workflow | Yes | No | No |
292
+ | Framework support | Docusaurus, VitePress, MkDocs, Starlight, plain MD | Docusaurus only | Multiple |
293
+ | Watch mode | Yes | Via Docusaurus | No |
294
+ | Deploy config generation | Vercel, Netlify, Cloudflare | No | No |
295
+ | Config format | YAML / JSON | Docusaurus plugin config | YAML |
296
+
297
+ `docusaurus-plugin-llms` is a good choice if you only use Docusaurus and only need file generation. `docs-ready` covers the full lifecycle: generate, guard against staleness, and validate compliance. If you already use `docusaurus-plugin-llms` for generation, `docs-ready init` detects it and disables duplicate generation -- you can still use guard and validate.
298
+
299
+ ---
300
+
301
+ ## Origin Story
302
+
303
+ `docs-ready` was built while making the [0G Labs](https://0g.ai) documentation AI-ready. The generate step came first, then guard was added after discovering that AI context files silently went stale when upstream SDKs released new versions. Validate was added to catch format regressions in CI. The tool was extracted into a standalone package so any docs team can use it.
304
+
305
+ ---
306
+
307
+ ## Contributing
308
+
309
+ Contributions are welcome. See the [GitHub repository](https://github.com/udhaykumarbala/docs-ready) for issues and pull requests.
310
+
311
+ ```bash
312
+ git clone https://github.com/udhaykumarbala/docs-ready.git
313
+ cd docs-ready
314
+ npm install
315
+ npm run dev
316
+ npm test
317
+ ```
318
+
319
+ ## License
320
+
321
+ [MIT](./LICENSE)
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/utils/logger.ts
4
+ import chalk from "chalk";
5
+ import ora from "ora";
6
+ var currentLevel = "normal";
7
+ function setLogLevel(level) {
8
+ currentLevel = level;
9
+ }
10
+ var log = {
11
+ info: (msg) => {
12
+ if (currentLevel !== "quiet") console.log(chalk.blue("\u2139"), msg);
13
+ },
14
+ success: (msg) => {
15
+ if (currentLevel !== "quiet") console.log(chalk.green("\u2714"), msg);
16
+ },
17
+ warn: (msg) => {
18
+ console.log(chalk.yellow("\u26A0"), msg);
19
+ },
20
+ error: (msg) => {
21
+ console.error(chalk.red("\u2716"), msg);
22
+ },
23
+ dim: (msg) => {
24
+ if (currentLevel !== "quiet") console.log(chalk.dim(msg));
25
+ },
26
+ debug: (msg) => {
27
+ if (currentLevel === "verbose") console.log(chalk.gray("[debug]"), msg);
28
+ }
29
+ };
30
+ function spinner(text) {
31
+ if (currentLevel === "quiet") {
32
+ return { start: () => ({}), stop: () => ({}), succeed: () => ({}), fail: () => ({}) };
33
+ }
34
+ return ora({ text, color: "cyan" });
35
+ }
36
+
37
+ export {
38
+ setLogLevel,
39
+ log,
40
+ spinner
41
+ };
42
+ //# sourceMappingURL=chunk-PXQN4E6K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\n\nexport type LogLevel = \"quiet\" | \"normal\" | \"verbose\";\n\nlet currentLevel: LogLevel = \"normal\";\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport const log = {\n info: (msg: string) => {\n if (currentLevel !== \"quiet\") console.log(chalk.blue(\"ℹ\"), msg);\n },\n success: (msg: string) => {\n if (currentLevel !== \"quiet\") console.log(chalk.green(\"✔\"), msg);\n },\n warn: (msg: string) => {\n console.log(chalk.yellow(\"⚠\"), msg);\n },\n error: (msg: string) => {\n console.error(chalk.red(\"✖\"), msg);\n },\n dim: (msg: string) => {\n if (currentLevel !== \"quiet\") console.log(chalk.dim(msg));\n },\n debug: (msg: string) => {\n if (currentLevel === \"verbose\") console.log(chalk.gray(\"[debug]\"), msg);\n },\n};\n\nexport function spinner(text: string): Ora {\n if (currentLevel === \"quiet\") {\n // Return a no-op spinner\n return { start: () => ({} as Ora), stop: () => ({} as Ora), succeed: () => ({} as Ora), fail: () => ({} as Ora) } as unknown as Ora;\n }\n return ora({ text, color: \"cyan\" });\n}\n"],"mappings":";;;AAAA,OAAO,WAAW;AAClB,OAAO,SAAuB;AAI9B,IAAI,eAAyB;AAEtB,SAAS,YAAY,OAAuB;AACjD,iBAAe;AACjB;AAEO,IAAM,MAAM;AAAA,EACjB,MAAM,CAAC,QAAgB;AACrB,QAAI,iBAAiB,QAAS,SAAQ,IAAI,MAAM,KAAK,QAAG,GAAG,GAAG;AAAA,EAChE;AAAA,EACA,SAAS,CAAC,QAAgB;AACxB,QAAI,iBAAiB,QAAS,SAAQ,IAAI,MAAM,MAAM,QAAG,GAAG,GAAG;AAAA,EACjE;AAAA,EACA,MAAM,CAAC,QAAgB;AACrB,YAAQ,IAAI,MAAM,OAAO,QAAG,GAAG,GAAG;AAAA,EACpC;AAAA,EACA,OAAO,CAAC,QAAgB;AACtB,YAAQ,MAAM,MAAM,IAAI,QAAG,GAAG,GAAG;AAAA,EACnC;AAAA,EACA,KAAK,CAAC,QAAgB;AACpB,QAAI,iBAAiB,QAAS,SAAQ,IAAI,MAAM,IAAI,GAAG,CAAC;AAAA,EAC1D;AAAA,EACA,OAAO,CAAC,QAAgB;AACtB,QAAI,iBAAiB,UAAW,SAAQ,IAAI,MAAM,KAAK,SAAS,GAAG,GAAG;AAAA,EACxE;AACF;AAEO,SAAS,QAAQ,MAAmB;AACzC,MAAI,iBAAiB,SAAS;AAE5B,WAAO,EAAE,OAAO,OAAO,CAAC,IAAW,MAAM,OAAO,CAAC,IAAW,SAAS,OAAO,CAAC,IAAW,MAAM,OAAO,CAAC,GAAU;AAAA,EAClH;AACA,SAAO,IAAI,EAAE,MAAM,OAAO,OAAO,CAAC;AACpC;","names":[]}
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  log,
12
12
  spinner
13
- } from "./chunk-7YN54Y4Y.js";
13
+ } from "./chunk-PXQN4E6K.js";
14
14
 
15
15
  // src/cli/commands/generate.ts
16
16
  import fs from "fs/promises";
@@ -2004,8 +2004,22 @@ async function generateCommand(options = {}) {
2004
2004
  log.success(`Generated ai-context.md (${formatTokens(estimateTokens(aiContext))})`);
2005
2005
  }
2006
2006
  }
2007
+ if (options.watch) {
2008
+ log.info("Watching for changes... (press Ctrl+C to stop)");
2009
+ const { watchDocs } = await import("./watcher-TAYSGKGV.js");
2010
+ watchDocs({
2011
+ dir: docsDir,
2012
+ patterns: config.docs.include,
2013
+ onChange: async () => {
2014
+ log.info("Changes detected, regenerating...");
2015
+ await generateCommand({ ...options, watch: false });
2016
+ }
2017
+ });
2018
+ await new Promise(() => {
2019
+ });
2020
+ }
2007
2021
  }
2008
2022
  export {
2009
2023
  generateCommand
2010
2024
  };
2011
- //# sourceMappingURL=generate-4EHDLBJX.js.map
2025
+ //# sourceMappingURL=generate-2KF6X5GF.js.map