--- template/app/scripts/generate-llms-txt.mjs
+++ opensaas-sh/app/scripts/generate-llms-txt.mjs
@@ -0,0 +1,94 @@
+import { readdir, readFile, writeFile } from "node:fs/promises";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const APP_ROOT = path.resolve(__dirname, "..");
+const BLOG_POSTS_DIR = path.resolve(
+  APP_ROOT,
+  "../blog/src/content/docs/blog",
+);
+const OUTPUT_FILE = path.join(APP_ROOT, "public/llms.txt");
+
+const DOCS_SITE = "https://docs.opensaas.sh";
+
+function parseFrontmatter(source) {
+  const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---/);
+  if (!match) return {};
+  const out = {};
+  for (const line of match[1].split(/\r?\n/)) {
+    const m = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
+    if (!m) continue;
+    const [, key, rawValue] = m;
+    let value = rawValue.trim();
+    if (
+      (value.startsWith('"') && value.endsWith('"')) ||
+      (value.startsWith("'") && value.endsWith("'"))
+    ) {
+      value = value.slice(1, -1);
+    }
+    out[key] = value;
+  }
+  return out;
+}
+
+async function collectBlogPosts() {
+  const entries = await readdir(BLOG_POSTS_DIR);
+  const posts = [];
+  for (const file of entries) {
+    if (!file.endsWith(".mdx") && !file.endsWith(".md")) continue;
+    const slug = file.replace(/\.(mdx|md)$/, "");
+    const source = await readFile(path.join(BLOG_POSTS_DIR, file), "utf8");
+    const fm = parseFrontmatter(source);
+    if (!fm.title) {
+      console.warn(`Skipping ${file}: no title in frontmatter`);
+      continue;
+    }
+    posts.push({
+      title: fm.title,
+      date: fm.date ?? "",
+      url: `${DOCS_SITE}/blog/${slug}/`,
+    });
+  }
+  posts.sort((a, b) => b.date.localeCompare(a.date));
+  return posts;
+}
+
+function renderLlmsTxt(posts) {
+  const lines = [
+    "# Open SaaS",
+    "",
+    "> Open SaaS is a free, open-source, full-stack SaaS boilerplate starter kit built on the Wasp framework (React, Node.js, Prisma). It ships with auth, Stripe/Lemon Squeezy/Polar payments, an OpenAI demo app, AWS S3 file uploads, an admin dashboard, email sending, and AI agent rules and skills.",
+    "",
+    "## Site",
+    "- [Homepage](https://opensaas.sh): product overview, features, demo, FAQ, etc.",
+    "- [GitHub repository](https://github.com/wasp-lang/open-saas): source code, issues, and releases",
+    "",
+    "## Documentation",
+    `- [Documentation site](${DOCS_SITE}/)`,
+    `- [LLM-formatted docs index](${DOCS_SITE}/llms.txt): per-guide links to raw markdown sources`,
+    `- [Full LLM-formatted docs](${DOCS_SITE}/llms-full.txt): every guide concatenated into one file`,
+    "",
+    "## Blog",
+  ];
+  for (const post of posts) {
+    const datePart = post.date ? ` — ${post.date}` : "";
+    lines.push(`- [${post.title}](${post.url})${datePart}`);
+  }
+  lines.push("");
+  return lines.join("\n");
+}
+
+async function main() {
+  const posts = await collectBlogPosts();
+  const content = renderLlmsTxt(posts);
+  await writeFile(OUTPUT_FILE, content, "utf8");
+  console.log(
+    `Wrote ${OUTPUT_FILE} with ${posts.length} blog post${posts.length === 1 ? "" : "s"}.`,
+  );
+}
+
+main().catch((err) => {
+  console.error(err);
+  process.exit(1);
+});
