@farming-labs/docs 0.0.2-beta.14 → 0.0.2-beta.15

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.
Files changed (2) hide show
  1. package/dist/cli/index.mjs +433 -20
  2. package/package.json +1 -1
@@ -16,6 +16,7 @@ function detectFramework(cwd) {
16
16
  };
17
17
  if (allDeps["next"]) return "nextjs";
18
18
  if (allDeps["@sveltejs/kit"]) return "sveltekit";
19
+ if (allDeps["astro"]) return "astro";
19
20
  return null;
20
21
  }
21
22
  function detectPackageManager(cwd) {
@@ -133,22 +134,28 @@ const THEME_INFO = {
133
134
  factory: "fumadocs",
134
135
  nextImport: "@farming-labs/theme",
135
136
  svelteImport: "@farming-labs/svelte-theme",
137
+ astroImport: "@farming-labs/astro-theme",
136
138
  nextCssImport: "default",
137
- svelteCssTheme: "fumadocs"
139
+ svelteCssTheme: "fumadocs",
140
+ astroCssTheme: "fumadocs"
138
141
  },
139
142
  darksharp: {
140
143
  factory: "darksharp",
141
144
  nextImport: "@farming-labs/theme/darksharp",
142
145
  svelteImport: "@farming-labs/svelte-theme/darksharp",
146
+ astroImport: "@farming-labs/astro-theme/darksharp",
143
147
  nextCssImport: "darksharp",
144
- svelteCssTheme: "darksharp"
148
+ svelteCssTheme: "darksharp",
149
+ astroCssTheme: "darksharp"
145
150
  },
146
151
  "pixel-border": {
147
152
  factory: "pixelBorder",
148
153
  nextImport: "@farming-labs/theme/pixel-border",
149
154
  svelteImport: "@farming-labs/svelte-theme/pixel-border",
155
+ astroImport: "@farming-labs/astro-theme/pixel-border",
150
156
  nextCssImport: "pixel-border",
151
- svelteCssTheme: "pixel-border"
157
+ svelteCssTheme: "pixel-border",
158
+ astroCssTheme: "pixel-border"
152
159
  }
153
160
  };
154
161
  function getThemeInfo(theme) {
@@ -178,6 +185,17 @@ function sveltePageConfigImport(useAlias) {
178
185
  function svelteLayoutServerImport(useAlias) {
179
186
  return useAlias ? "$lib/docs.server" : "../../lib/docs.server";
180
187
  }
188
+ function astroServerConfigImport(useAlias) {
189
+ return useAlias ? "@/lib/docs.config" : "./docs.config";
190
+ }
191
+ function astroPageConfigImport(useAlias, depth) {
192
+ if (useAlias) return "@/lib/docs.config";
193
+ return `${"../".repeat(depth)}lib/docs.config`;
194
+ }
195
+ function astroPageServerImport(useAlias, depth) {
196
+ if (useAlias) return "@/lib/docs.server";
197
+ return `${"../".repeat(depth)}lib/docs.server`;
198
+ }
181
199
  function docsConfigTemplate(cfg) {
182
200
  const t = getThemeInfo(cfg.theme);
183
201
  return `\
@@ -765,6 +783,327 @@ Build your docs for production:
765
783
  pnpm build
766
784
  \`\`\`
767
785
 
786
+ Deploy to Vercel, Netlify, or any Node.js hosting platform.
787
+ `;
788
+ }
789
+ function astroDocsConfigTemplate(cfg) {
790
+ const t = getThemeInfo(cfg.theme);
791
+ return `\
792
+ import { defineDocs } from "@farming-labs/docs";
793
+ import { ${t.factory} } from "${t.astroImport}";
794
+
795
+ export default defineDocs({
796
+ entry: "${cfg.entry}",
797
+ contentDir: "${cfg.entry}",
798
+ theme: ${t.factory}({
799
+ ui: {
800
+ colors: { primary: "#6366f1" },
801
+ },
802
+ }),
803
+
804
+ nav: {
805
+ title: "${cfg.projectName}",
806
+ url: "/${cfg.entry}",
807
+ },
808
+
809
+ breadcrumb: { enabled: true },
810
+
811
+ metadata: {
812
+ titleTemplate: "%s – ${cfg.projectName}",
813
+ description: "Documentation for ${cfg.projectName}",
814
+ },
815
+ });
816
+ `;
817
+ }
818
+ function astroDocsServerTemplate(cfg) {
819
+ return `\
820
+ import { createDocsServer } from "@farming-labs/astro/server";
821
+ import config from "${astroServerConfigImport(cfg.useAlias)}";
822
+
823
+ const contentFiles = import.meta.glob("/${cfg.entry ?? "docs"}/**/*.{md,mdx}", {
824
+ query: "?raw",
825
+ import: "default",
826
+ eager: true,
827
+ }) as Record<string, string>;
828
+
829
+ export const { load, GET, POST } = createDocsServer({
830
+ ...config,
831
+ _preloadedContent: contentFiles,
832
+ });
833
+ `;
834
+ }
835
+ const ASTRO_ADAPTER_INFO = {
836
+ vercel: {
837
+ pkg: "@astrojs/vercel",
838
+ import: "@astrojs/vercel"
839
+ },
840
+ netlify: {
841
+ pkg: "@astrojs/netlify",
842
+ import: "@astrojs/netlify"
843
+ },
844
+ node: {
845
+ pkg: "@astrojs/node",
846
+ import: "@astrojs/node"
847
+ },
848
+ cloudflare: {
849
+ pkg: "@astrojs/cloudflare",
850
+ import: "@astrojs/cloudflare"
851
+ }
852
+ };
853
+ function getAstroAdapterPkg(adapter) {
854
+ return ASTRO_ADAPTER_INFO[adapter]?.pkg ?? ASTRO_ADAPTER_INFO.vercel.pkg;
855
+ }
856
+ function astroConfigTemplate(adapter = "vercel") {
857
+ const info = ASTRO_ADAPTER_INFO[adapter] ?? ASTRO_ADAPTER_INFO.vercel;
858
+ const adapterCall = adapter === "node" ? `${adapter}({ mode: "standalone" })` : `${adapter}()`;
859
+ return `\
860
+ import { defineConfig } from "astro/config";
861
+ import ${adapter} from "${info.import}";
862
+
863
+ export default defineConfig({
864
+ output: "server",
865
+ adapter: ${adapterCall},
866
+ });
867
+ `;
868
+ }
869
+ function astroDocsPageTemplate(cfg) {
870
+ return `\
871
+ ---
872
+ import DocsLayout from "@farming-labs/astro-theme/src/components/DocsLayout.astro";
873
+ import DocsContent from "@farming-labs/astro-theme/src/components/DocsContent.astro";
874
+ import SearchDialog from "@farming-labs/astro-theme/src/components/SearchDialog.astro";
875
+ import config from "${astroPageConfigImport(cfg.useAlias, 2)}";
876
+ import { load } from "${astroPageServerImport(cfg.useAlias, 2)}";
877
+ import "${`@farming-labs/astro-theme/${getThemeInfo(cfg.theme).astroCssTheme}/css`}";
878
+
879
+ const data = await load(Astro.url.pathname);
880
+ ---
881
+
882
+ <html lang="en">
883
+ <head>
884
+ <meta charset="utf-8" />
885
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
886
+ <title>{data.title} – Docs</title>
887
+ </head>
888
+ <body>
889
+ <DocsLayout tree={data.tree} config={config}>
890
+ <DocsContent data={data} config={config} />
891
+ </DocsLayout>
892
+ <SearchDialog config={config} />
893
+ </body>
894
+ </html>
895
+ `;
896
+ }
897
+ function astroDocsIndexTemplate(cfg) {
898
+ return `\
899
+ ---
900
+ import DocsLayout from "@farming-labs/astro-theme/src/components/DocsLayout.astro";
901
+ import DocsContent from "@farming-labs/astro-theme/src/components/DocsContent.astro";
902
+ import SearchDialog from "@farming-labs/astro-theme/src/components/SearchDialog.astro";
903
+ import config from "${astroPageConfigImport(cfg.useAlias, 2)}";
904
+ import { load } from "${astroPageServerImport(cfg.useAlias, 2)}";
905
+ import "${`@farming-labs/astro-theme/${getThemeInfo(cfg.theme).astroCssTheme}/css`}";
906
+
907
+ const data = await load(Astro.url.pathname);
908
+ ---
909
+
910
+ <html lang="en">
911
+ <head>
912
+ <meta charset="utf-8" />
913
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
914
+ <title>{data.title} – Docs</title>
915
+ </head>
916
+ <body>
917
+ <DocsLayout tree={data.tree} config={config}>
918
+ <DocsContent data={data} config={config} />
919
+ </DocsLayout>
920
+ <SearchDialog config={config} />
921
+ </body>
922
+ </html>
923
+ `;
924
+ }
925
+ function astroApiRouteTemplate(cfg) {
926
+ return `\
927
+ import type { APIRoute } from "astro";
928
+ import { GET as docsGET, POST as docsPOST } from "${astroPageServerImport(cfg.useAlias, 2)}";
929
+
930
+ export const GET: APIRoute = async ({ request }) => {
931
+ return docsGET({ request });
932
+ };
933
+
934
+ export const POST: APIRoute = async ({ request }) => {
935
+ return docsPOST({ request });
936
+ };
937
+ `;
938
+ }
939
+ function astroGlobalCssTemplate(theme) {
940
+ return `\
941
+ @import "@farming-labs/astro-theme/${theme}/css";
942
+ `;
943
+ }
944
+ function astroCssImportLine(theme) {
945
+ return `@import "@farming-labs/astro-theme/${theme}/css";`;
946
+ }
947
+ function injectAstroCssImport(existingContent, theme) {
948
+ const importLine = astroCssImportLine(theme);
949
+ if (existingContent.includes(importLine)) return null;
950
+ const lines = existingContent.split("\n");
951
+ const lastImportIdx = lines.reduce((acc, l, i) => l.trimStart().startsWith("@import") ? i : acc, -1);
952
+ if (lastImportIdx >= 0) lines.splice(lastImportIdx + 1, 0, importLine);
953
+ else lines.unshift(importLine);
954
+ return lines.join("\n");
955
+ }
956
+ function astroWelcomePageTemplate(cfg) {
957
+ return `\
958
+ ---
959
+ title: "Documentation"
960
+ description: "Welcome to ${cfg.projectName} documentation"
961
+ ---
962
+
963
+ # Welcome to ${cfg.projectName}
964
+
965
+ Get started with our documentation. Browse the pages on the left to learn more.
966
+
967
+ ## Overview
968
+
969
+ This documentation was generated by \`@farming-labs/docs\`. Edit the markdown files in \`${cfg.entry}/\` to customize.
970
+
971
+ ## Features
972
+
973
+ - **Markdown Support** — Write docs with standard Markdown
974
+ - **Syntax Highlighting** — Code blocks with automatic highlighting
975
+ - **Dark Mode** — Built-in theme switching
976
+ - **Search** — Full-text search across all pages
977
+ - **Responsive** — Works on any screen size
978
+
979
+ ---
980
+
981
+ ## Next Steps
982
+
983
+ Start by reading the [Installation](/${cfg.entry}/installation) guide, then follow the [Quickstart](/${cfg.entry}/quickstart) to build something.
984
+ `;
985
+ }
986
+ function astroInstallationPageTemplate(cfg) {
987
+ const t = getThemeInfo(cfg.theme);
988
+ return `\
989
+ ---
990
+ title: "Installation"
991
+ description: "How to install and set up ${cfg.projectName}"
992
+ ---
993
+
994
+ # Installation
995
+
996
+ Follow these steps to install and configure ${cfg.projectName}.
997
+
998
+ ## Prerequisites
999
+
1000
+ - Node.js 18+
1001
+ - A package manager (pnpm, npm, or yarn)
1002
+
1003
+ ## Install Dependencies
1004
+
1005
+ \\\`\\\`\\\`bash
1006
+ pnpm add @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme
1007
+ \\\`\\\`\\\`
1008
+
1009
+ ## Configuration
1010
+
1011
+ Your project includes a \\\`docs.config.ts\\\` in \\\`src/lib/\\\`:
1012
+
1013
+ \\\`\\\`\\\`ts title="src/lib/docs.config.ts"
1014
+ import { defineDocs } from "@farming-labs/docs";
1015
+ import { ${t.factory} } from "${t.astroImport}";
1016
+
1017
+ export default defineDocs({
1018
+ entry: "${cfg.entry}",
1019
+ contentDir: "${cfg.entry}",
1020
+ theme: ${t.factory}({
1021
+ ui: { colors: { primary: "#6366f1" } },
1022
+ }),
1023
+ });
1024
+ \\\`\\\`\\\`
1025
+
1026
+ ## Project Structure
1027
+
1028
+ \\\`\\\`\\\`
1029
+ ${cfg.entry}/ # Markdown content
1030
+ page.md # /${cfg.entry}
1031
+ installation/
1032
+ page.md # /${cfg.entry}/installation
1033
+ quickstart/
1034
+ page.md # /${cfg.entry}/quickstart
1035
+ src/
1036
+ lib/
1037
+ docs.config.ts # Docs configuration
1038
+ docs.server.ts # Server-side docs loader
1039
+ pages/
1040
+ ${cfg.entry}/
1041
+ index.astro # Docs index page
1042
+ [...slug].astro # Dynamic doc page
1043
+ api/
1044
+ ${cfg.entry}.ts # Search/AI API route
1045
+ \\\`\\\`\\\`
1046
+
1047
+ ## What's Next?
1048
+
1049
+ Head to the [Quickstart](/${cfg.entry}/quickstart) guide to start writing your first page.
1050
+ `;
1051
+ }
1052
+ function astroQuickstartPageTemplate(cfg) {
1053
+ const t = getThemeInfo(cfg.theme);
1054
+ return `\
1055
+ ---
1056
+ title: "Quickstart"
1057
+ description: "Get up and running in minutes"
1058
+ ---
1059
+
1060
+ # Quickstart
1061
+
1062
+ This guide walks you through creating your first documentation page.
1063
+
1064
+ ## Creating a Page
1065
+
1066
+ Create a new folder under \\\`${cfg.entry}/\\\` with a \\\`page.md\\\` file:
1067
+
1068
+ \\\`\\\`\\\`bash
1069
+ mkdir -p ${cfg.entry}/my-page
1070
+ \\\`\\\`\\\`
1071
+
1072
+ Then create \\\`${cfg.entry}/my-page/page.md\\\`:
1073
+
1074
+ \\\`\\\`\\\`md
1075
+ ---
1076
+ title: "My Page"
1077
+ description: "A custom documentation page"
1078
+ ---
1079
+
1080
+ # My Page
1081
+
1082
+ Write your content here using **Markdown**.
1083
+ \\\`\\\`\\\`
1084
+
1085
+ Your page is now available at \\\`/${cfg.entry}/my-page\\\`.
1086
+
1087
+ ## Customizing the Theme
1088
+
1089
+ Edit \\\`src/lib/docs.config.ts\\\` to change colors, typography, and component defaults:
1090
+
1091
+ \\\`\\\`\\\`ts title="src/lib/docs.config.ts"
1092
+ theme: ${t.factory}({
1093
+ ui: {
1094
+ colors: { primary: "#22c55e" },
1095
+ },
1096
+ }),
1097
+ \\\`\\\`\\\`
1098
+
1099
+ ## Deploying
1100
+
1101
+ Build your docs for production:
1102
+
1103
+ \\\`\\\`\\\`bash
1104
+ pnpm build
1105
+ \\\`\\\`\\\`
1106
+
768
1107
  Deploy to Vercel, Netlify, or any Node.js hosting platform.
769
1108
  `;
770
1109
  }
@@ -776,21 +1115,29 @@ async function init() {
776
1115
  p.intro(pc.bgCyan(pc.black(" @farming-labs/docs ")));
777
1116
  let framework = detectFramework(cwd);
778
1117
  if (framework) {
779
- const frameworkName = framework === "nextjs" ? "Next.js" : "SvelteKit";
1118
+ const frameworkName = framework === "nextjs" ? "Next.js" : framework === "sveltekit" ? "SvelteKit" : "Astro";
780
1119
  p.log.success(`Detected framework: ${pc.cyan(frameworkName)}`);
781
1120
  } else {
782
1121
  p.log.warn("Could not auto-detect a framework from " + pc.cyan("package.json") + ".");
783
1122
  const picked = await p.select({
784
1123
  message: "Which framework are you using?",
785
- options: [{
786
- value: "nextjs",
787
- label: "Next.js",
788
- hint: "React framework with App Router"
789
- }, {
790
- value: "sveltekit",
791
- label: "SvelteKit",
792
- hint: "Svelte framework with file-based routing"
793
- }]
1124
+ options: [
1125
+ {
1126
+ value: "nextjs",
1127
+ label: "Next.js",
1128
+ hint: "React framework with App Router"
1129
+ },
1130
+ {
1131
+ value: "sveltekit",
1132
+ label: "SvelteKit",
1133
+ hint: "Svelte framework with file-based routing"
1134
+ },
1135
+ {
1136
+ value: "astro",
1137
+ label: "Astro",
1138
+ hint: "Content-focused framework with island architecture"
1139
+ }
1140
+ ]
794
1141
  });
795
1142
  if (p.isCancel(picked)) {
796
1143
  p.outro(pc.red("Init cancelled."));
@@ -822,7 +1169,7 @@ async function init() {
822
1169
  p.outro(pc.red("Init cancelled."));
823
1170
  process.exit(0);
824
1171
  }
825
- const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : `Uses ${pc.cyan("$lib/")} prefix (SvelteKit built-in)`;
1172
+ const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : framework === "sveltekit" ? `Uses ${pc.cyan("$lib/")} prefix (SvelteKit built-in)` : `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)`;
826
1173
  const useAlias = await p.confirm({
827
1174
  message: `Use path aliases for imports? ${pc.dim(aliasHint)}`,
828
1175
  initialValue: false
@@ -831,6 +1178,37 @@ async function init() {
831
1178
  p.outro(pc.red("Init cancelled."));
832
1179
  process.exit(0);
833
1180
  }
1181
+ let astroAdapter;
1182
+ if (framework === "astro") {
1183
+ const adapter = await p.select({
1184
+ message: "Where will you deploy?",
1185
+ options: [
1186
+ {
1187
+ value: "vercel",
1188
+ label: "Vercel",
1189
+ hint: "Recommended for most projects"
1190
+ },
1191
+ {
1192
+ value: "netlify",
1193
+ label: "Netlify"
1194
+ },
1195
+ {
1196
+ value: "cloudflare",
1197
+ label: "Cloudflare Pages"
1198
+ },
1199
+ {
1200
+ value: "node",
1201
+ label: "Node.js / Docker",
1202
+ hint: "Self-hosted standalone server"
1203
+ }
1204
+ ]
1205
+ });
1206
+ if (p.isCancel(adapter)) {
1207
+ p.outro(pc.red("Init cancelled."));
1208
+ process.exit(0);
1209
+ }
1210
+ astroAdapter = adapter;
1211
+ }
834
1212
  const entry = await p.text({
835
1213
  message: "Where should your docs live?",
836
1214
  placeholder: "docs",
@@ -848,7 +1226,7 @@ async function init() {
848
1226
  const entryPath = entry;
849
1227
  const detectedCssFiles = detectGlobalCssFiles(cwd);
850
1228
  let globalCssRelPath;
851
- const defaultCssPath = framework === "sveltekit" ? "src/app.css" : "app/globals.css";
1229
+ const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : "app/globals.css";
852
1230
  if (detectedCssFiles.length === 1) {
853
1231
  globalCssRelPath = detectedCssFiles[0];
854
1232
  p.log.info(`Found global CSS at ${pc.cyan(globalCssRelPath)}`);
@@ -888,7 +1266,8 @@ async function init() {
888
1266
  theme,
889
1267
  projectName: pkgJson.name || "My Project",
890
1268
  framework,
891
- useAlias
1269
+ useAlias,
1270
+ astroAdapter
892
1271
  };
893
1272
  const s = p.spinner();
894
1273
  s.start("Scaffolding docs files");
@@ -899,6 +1278,7 @@ async function init() {
899
1278
  else skipped.push(rel);
900
1279
  }
901
1280
  if (framework === "sveltekit") scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written);
1281
+ else if (framework === "astro") scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written);
902
1282
  else scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written);
903
1283
  s.stop("Files scaffolded");
904
1284
  if (written.length > 0) p.log.success(`Created ${written.length} file${written.length > 1 ? "s" : ""}:\n` + written.map((f) => ` ${pc.green("+")} ${f}`).join("\n"));
@@ -909,7 +1289,10 @@ async function init() {
909
1289
  s2.start("Installing dependencies");
910
1290
  try {
911
1291
  if (framework === "sveltekit") exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme`, cwd);
912
- else {
1292
+ else if (framework === "astro") {
1293
+ const adapterPkg = getAstroAdapterPkg(cfg.astroAdapter ?? "vercel");
1294
+ exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme ${adapterPkg}`, cwd);
1295
+ } else {
913
1296
  exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/next @farming-labs/theme`, cwd);
914
1297
  const devDeps = [
915
1298
  "@tailwindcss/postcss",
@@ -948,6 +1331,10 @@ async function init() {
948
1331
  cmd: "npx",
949
1332
  args: ["vite", "dev"],
950
1333
  waitFor: "ready"
1334
+ } : framework === "astro" ? {
1335
+ cmd: "npx",
1336
+ args: ["astro", "dev"],
1337
+ waitFor: "ready"
951
1338
  } : {
952
1339
  cmd: "npx",
953
1340
  args: [
@@ -957,7 +1344,7 @@ async function init() {
957
1344
  ],
958
1345
  waitFor: "Ready"
959
1346
  };
960
- const defaultPort = framework === "sveltekit" ? "5173" : "3000";
1347
+ const defaultPort = framework === "sveltekit" ? "5173" : framework === "astro" ? "4321" : "3000";
961
1348
  try {
962
1349
  const child = await spawnAndWaitFor(devCommand.cmd, devCommand.args, cwd, devCommand.waitFor, 6e4);
963
1350
  const url = `http://localhost:${defaultPort}/${entryPath}`;
@@ -976,7 +1363,7 @@ async function init() {
976
1363
  });
977
1364
  });
978
1365
  } catch (err) {
979
- const manualCmd = framework === "sveltekit" ? "npx vite dev" : "npx next dev --webpack";
1366
+ const manualCmd = framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : "npx next dev --webpack";
980
1367
  p.log.error(`Could not start dev server. Try running manually:
981
1368
  ${pc.cyan(manualCmd)}`);
982
1369
  p.outro(pc.yellow("Setup complete. Start the server manually."));
@@ -1037,6 +1424,32 @@ function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written)
1037
1424
  write(`${cfg.entry}/installation/page.md`, svelteInstallationPageTemplate(cfg));
1038
1425
  write(`${cfg.entry}/quickstart/page.md`, svelteQuickstartPageTemplate(cfg));
1039
1426
  }
1427
+ function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
1428
+ write("src/lib/docs.config.ts", astroDocsConfigTemplate(cfg));
1429
+ write("src/lib/docs.server.ts", astroDocsServerTemplate(cfg));
1430
+ if (!fileExists(path.join(cwd, "astro.config.mjs")) && !fileExists(path.join(cwd, "astro.config.ts"))) write("astro.config.mjs", astroConfigTemplate(cfg.astroAdapter ?? "vercel"));
1431
+ write(`src/pages/${cfg.entry}/index.astro`, astroDocsIndexTemplate(cfg));
1432
+ write(`src/pages/${cfg.entry}/[...slug].astro`, astroDocsPageTemplate(cfg));
1433
+ write(`src/pages/api/${cfg.entry}.ts`, astroApiRouteTemplate(cfg));
1434
+ const globalCssAbsPath = path.join(cwd, globalCssRelPath);
1435
+ const existingGlobalCss = readFileSafe(globalCssAbsPath);
1436
+ const cssTheme = {
1437
+ fumadocs: "fumadocs",
1438
+ darksharp: "darksharp",
1439
+ "pixel-border": "pixel-border",
1440
+ default: "fumadocs"
1441
+ }[cfg.theme] || "fumadocs";
1442
+ if (existingGlobalCss) {
1443
+ const injected = injectAstroCssImport(existingGlobalCss, cssTheme);
1444
+ if (injected) {
1445
+ writeFileSafe(globalCssAbsPath, injected, true);
1446
+ written.push(globalCssRelPath + " (updated)");
1447
+ } else skipped.push(globalCssRelPath + " (already configured)");
1448
+ } else write(globalCssRelPath, astroGlobalCssTemplate(cssTheme));
1449
+ write(`${cfg.entry}/page.md`, astroWelcomePageTemplate(cfg));
1450
+ write(`${cfg.entry}/installation/page.md`, astroInstallationPageTemplate(cfg));
1451
+ write(`${cfg.entry}/quickstart/page.md`, astroQuickstartPageTemplate(cfg));
1452
+ }
1040
1453
 
1041
1454
  //#endregion
1042
1455
  //#region src/cli/index.ts
@@ -1063,7 +1476,7 @@ ${pc.dim("Commands:")}
1063
1476
  ${pc.cyan("init")} Scaffold docs in your project (default)
1064
1477
 
1065
1478
  ${pc.dim("Supported frameworks:")}
1066
- Next.js, SvelteKit
1479
+ Next.js, SvelteKit, Astro
1067
1480
 
1068
1481
  ${pc.dim("Options:")}
1069
1482
  ${pc.cyan("-h, --help")} Show this help message
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.0.2-beta.14",
3
+ "version": "0.0.2-beta.15",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",