diff --git a/.gitignore b/.gitignore
index f3f409f..0bb699c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
.bsb.lock
.astro
dist/
-tmp/
\ No newline at end of file
+tmp/
+docs/public/llm.txt
\ No newline at end of file
diff --git a/astro.config.mjs b/astro.config.mjs
index 44136c0..8c1cbb5 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -77,6 +77,14 @@ export default defineConfig({
...apiSidebarItems,
],
},
+ {
+ label: "LLM Documentation",
+ link: "./llm.txt",
+ badge: {
+ text: "New",
+ variant: "tip",
+ },
+ },
],
customCss: ["./docs/styles/fonts.css", "./docs/styles/theme.css"],
expressiveCode: {
diff --git a/docs/llm.js b/docs/llm.js
new file mode 100644
index 0000000..eaca2ca
--- /dev/null
+++ b/docs/llm.js
@@ -0,0 +1,117 @@
+import * as path from "node:path";
+import { exec } from "node:child_process";
+import { promisify } from "node:util";
+import fs from "node:fs/promises";
+
+const execAsync = promisify(exec);
+
+const bins = await import(
+ path.join(import.meta.dirname, "../node_modules/rescript/cli/common/bins.js")
+);
+const rescriptTools = bins["rescript_tools_exe"];
+
+if (!rescriptTools) {
+ throw new Error("rescript-tools not found");
+}
+
+async function getDocJson(filePath) {
+ try {
+ const command = `${rescriptTools} doc "${filePath}"`;
+ const options = { maxBuffer: 10 * 1024 * 1024 };
+ const { stdout, stderr } = await execAsync(command, options);
+
+ if (stderr) {
+ throw new Error(`Error executing command for ${filePath}: ${stderr}`);
+ }
+
+ return JSON.parse(stdout);
+ } catch (error) {
+ throw new Error(`Failed to get documentation JSON for ${filePath}:`, error);
+ }
+}
+
+async function processFile(filePath) {
+ const json = await getDocJson(filePath);
+
+ const moduleName = "WebAPI." + json.name.replace("-WebAPI", "");
+
+ const types = [];
+ const functions = [];
+
+ function mkType(item) {
+ let description = "";
+ if (item.docstrings.length > 0) {
+ description = "\n Description: " + item.docstrings.join("\n");
+ }
+ let fields = "";
+ if (item.detail && item.detail.kind === "record") {
+ fields =
+ "\n Fields:\n" +
+ item.detail.items
+ .map((field) => {
+ let fieldDoc = "";
+ if (field.docstrings.length > 0) {
+ fieldDoc = " - " + field.docstrings.join(" ");
+ }
+ return ` - ${field.name}: ${field.signature}${fieldDoc}`;
+ })
+ .join("\n");
+ }
+ return `- ${item.signature}${description}${fields}`;
+ }
+
+ function mkFunction(item) {
+ let description = "";
+ if (item.docstrings.length > 0) {
+ description = "\n Description: " + item.docstrings.join("\n");
+ }
+ return `- ${item.signature}${description}`;
+ }
+
+ for (const item of json.items) {
+ switch (item.kind) {
+ case "type":
+ types.push(mkType(item));
+ break;
+ case "value":
+ functions.push(mkFunction(item));
+ break;
+ }
+ }
+
+ let typeString = "";
+ if (types.length > 0) {
+ typeString = "\n\nTypes:\n\n" + types.join("\n\n");
+ }
+
+ let functionString = "";
+ if (functions.length > 0) {
+ functionString = "\n\nFunctions:\n\n" + functions.join("\n\n");
+ }
+
+ return `File: ${json.source.filepath}
+Module: ${moduleName}${typeString}${functionString}
+`;
+}
+
+const pattern = "../src/**/*.res"
+const files = [];
+for await (const file of fs.glob(pattern, { recursive: true, cwd: import.meta.dirname })) {
+ files.push(path.join(import.meta.dirname, file));
+}
+files.sort();
+
+const pages = await Promise.all(files.map(processFile))
+const packageJson = await fs.readFile(path.join(import.meta.dirname, "../package.json"), "utf-8");
+let version = JSON.parse(packageJson).version;
+const sha = await execAsync("git rev-parse --short HEAD").then(({ stdout }) => stdout.trim());
+const fullVersion = `${version}-${sha}`;
+const header = `Experimental Rescript WebAPI Documentation ${fullVersion}
+
+This is the API documentation for the experimental WebAPI module version ${fullVersion}.
+More information can be found on https://rescript-lang.github.io/experimental-rescript-webapi/
+
+`
+const content = pages.join("\n---\n\n");
+await fs.writeFile(path.join(import.meta.dirname, "public/llm.txt"), header + content);
+console.log("Generated llm.txt");
\ No newline at end of file
diff --git a/package.json b/package.json
index 1a4f979..dd38763 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"build": "rescript",
"format": "rescript format -all && prettier --write ./tests/index.js ./package.json ./docs/pages",
"docs": "astro dev",
+ "pre:build:docs": "node docs/llm.js",
"build:docs": "astro build"
},
"license": "MIT",