create-fumadocs-app 15.1.3 → 15.2.1
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/dist/{chunk-K4QGKCVK.js → chunk-LCUIXVWC.js} +159 -68
- package/dist/create-app.js +1 -1
- package/dist/index.js +48 -24
- package/package.json +2 -2
- package/template/react-router/README.md +12 -0
- package/template/react-router/app/app.css +6 -0
- package/template/react-router/app/docs/page.tsx +63 -0
- package/template/react-router/app/docs/search.ts +18 -0
- package/template/react-router/app/root.tsx +78 -0
- package/template/react-router/app/routes/home.tsx +34 -0
- package/template/react-router/app/routes.ts +7 -0
- package/template/react-router/app/source.ts +60 -0
- package/template/react-router/content/docs/index.mdx +32 -0
- package/template/react-router/content/docs/test.mdx +8 -0
- package/template/react-router/example.gitignore +6 -0
- package/template/react-router/public/favicon.ico +0 -0
- package/template/react-router/react-router.config.ts +9 -0
- package/template/react-router/tsconfig.json +27 -0
- package/template/react-router/vite.config.ts +13 -0
- package/template/tanstack-start/README.md +12 -0
- package/template/tanstack-start/app/api.ts +6 -0
- package/template/tanstack-start/app/app.css +6 -0
- package/template/tanstack-start/app/client.tsx +7 -0
- package/template/tanstack-start/app/router.tsx +15 -0
- package/template/tanstack-start/app/routes/__root.tsx +49 -0
- package/template/tanstack-start/app/routes/api/search.ts +20 -0
- package/template/tanstack-start/app/routes/docs/$.tsx +71 -0
- package/template/tanstack-start/app/routes/index.tsx +25 -0
- package/template/tanstack-start/app/ssr.tsx +13 -0
- package/template/tanstack-start/app.config.ts +43 -0
- package/template/tanstack-start/content/docs/index.mdx +35 -0
- package/template/tanstack-start/example.gitignore +4 -0
- package/template/tanstack-start/lib/source.ts +70 -0
- package/template/tanstack-start/tsconfig.json +15 -0
- /package/template/{+shared → +next}/README.md +0 -0
- /package/template/{+shared → +next}/app/(home)/layout.tsx +0 -0
- /package/template/{+shared → +next}/app/(home)/page.tsx +0 -0
- /package/template/{+shared → +next}/app/api/search/route.ts +0 -0
- /package/template/{+shared → +next}/app/docs/layout.tsx +0 -0
- /package/template/{+shared → +next}/app/layout.config.tsx +0 -0
- /package/template/{+shared → +next}/app/layout.tsx +0 -0
- /package/template/{+shared → +next}/content/docs/index.mdx +0 -0
- /package/template/{+shared → +next}/content/docs/test.mdx +0 -0
- /package/template/{+shared → +next}/example.gitignore +0 -0
- /package/template/{content-collections → +next+content-collections}/app/docs/[[...slug]]/page.tsx +0 -0
- /package/template/{content-collections → +next+content-collections}/content-collections.ts +0 -0
- /package/template/{content-collections → +next+content-collections}/lib/source.ts +0 -0
- /package/template/{content-collections → +next+content-collections}/next.config.mjs +0 -0
- /package/template/{content-collections → +next+content-collections}/tsconfig.json +0 -0
- /package/template/{+eslint → +next+eslint}/.eslintrc.json +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/app/docs/[[...slug]]/page.tsx +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/lib/source.ts +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/next.config.mjs +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/source.config.ts +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/tsconfig.json +0 -0
- /package/template/{+tailwindcss → +next+tailwindcss}/app/(home)/page.tsx +0 -0
- /package/template/{+tailwindcss → +next+tailwindcss}/app/global.css +0 -0
- /package/template/{+tailwindcss → +next+tailwindcss}/app/layout.tsx +0 -0
- /package/template/{+tailwindcss → +next+tailwindcss}/postcss.config.mjs +0 -0
|
@@ -60,7 +60,7 @@ function tryGitInit(root) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// src/versions.js
|
|
63
|
-
var versions = { "fumadocs-core": "15.1
|
|
63
|
+
var versions = { "fumadocs-core": "15.2.1", "fumadocs-ui": "15.2.1", "fumadocs-mdx": "11.5.7", "@fumadocs/mdx-remote": "1.3.0", "@fumadocs/content-collections": "1.1.8" };
|
|
64
64
|
|
|
65
65
|
// ../create-app-versions/package.json
|
|
66
66
|
var package_default = {
|
|
@@ -73,17 +73,33 @@ var package_default = {
|
|
|
73
73
|
"@content-collections/core": "^0.8.2",
|
|
74
74
|
"@content-collections/mdx": "^0.2.2",
|
|
75
75
|
"@content-collections/next": "^0.2.6",
|
|
76
|
-
"@
|
|
76
|
+
"@react-router/dev": "^7.4.1",
|
|
77
|
+
"@react-router/node": "^7.4.1",
|
|
78
|
+
"@react-router/serve": "^7.4.1",
|
|
79
|
+
"@tailwindcss/postcss": "^4.0.17",
|
|
80
|
+
"@tailwindcss/vite": "^4.0.17",
|
|
77
81
|
"@types/mdx": "^2.0.13",
|
|
78
|
-
"@types/node": "22.13.
|
|
82
|
+
"@types/node": "22.13.14",
|
|
79
83
|
"@types/react": "^19.0.12",
|
|
80
84
|
"@types/react-dom": "^19.0.4",
|
|
81
|
-
|
|
85
|
+
"gray-matter": "^4.0.3",
|
|
86
|
+
isbot: "^5.1.17",
|
|
87
|
+
next: "15.2.4",
|
|
82
88
|
postcss: "^8.5.3",
|
|
83
|
-
react: "^19.
|
|
84
|
-
"react-dom": "^19.
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
react: "^19.1.0",
|
|
90
|
+
"react-dom": "^19.1.0",
|
|
91
|
+
"react-router": "^7.4.1",
|
|
92
|
+
"react-router-devtools": "^1.1.8",
|
|
93
|
+
shiki: "^3.2.1",
|
|
94
|
+
tailwindcss: "^4.0.17",
|
|
95
|
+
typescript: "^5.8.2",
|
|
96
|
+
vite: "^6.2.3",
|
|
97
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
98
|
+
"@tanstack/react-router": "^1.114.29",
|
|
99
|
+
"@tanstack/react-start": "^1.114.29",
|
|
100
|
+
"fast-glob": "^3.3.3",
|
|
101
|
+
vinxi: "^0.5.3",
|
|
102
|
+
"@vitejs/plugin-react": "^4.3.4"
|
|
87
103
|
}
|
|
88
104
|
};
|
|
89
105
|
|
|
@@ -137,9 +153,10 @@ async function create(options) {
|
|
|
137
153
|
} = options;
|
|
138
154
|
const projectName = path.basename(options.outputDir);
|
|
139
155
|
const dest = path.resolve(cwd, options.outputDir);
|
|
156
|
+
const isNext = options.template.startsWith("+next");
|
|
140
157
|
function defaultRename(file) {
|
|
141
158
|
file = file.replace("example.gitignore", ".gitignore");
|
|
142
|
-
if (!options.useSrcDir) {
|
|
159
|
+
if (!options.useSrcDir || !isNext) {
|
|
143
160
|
return file;
|
|
144
161
|
}
|
|
145
162
|
for (const dir of ["app", "lib"]) {
|
|
@@ -150,25 +167,38 @@ async function create(options) {
|
|
|
150
167
|
}
|
|
151
168
|
return file;
|
|
152
169
|
}
|
|
153
|
-
|
|
170
|
+
if (isNext) {
|
|
171
|
+
await copy(path.join(sourceDir, `template/+next`), dest, defaultRename);
|
|
172
|
+
}
|
|
154
173
|
await copy(
|
|
155
174
|
path.join(sourceDir, `template/${options.template}`),
|
|
156
175
|
dest,
|
|
157
176
|
defaultRename
|
|
158
177
|
);
|
|
159
|
-
if (options.tailwindcss) {
|
|
178
|
+
if (isNext && options.tailwindcss) {
|
|
160
179
|
await copy(
|
|
161
|
-
path.join(sourceDir, `template/+tailwindcss`),
|
|
180
|
+
path.join(sourceDir, `template/+next+tailwindcss`),
|
|
162
181
|
dest,
|
|
163
182
|
defaultRename
|
|
164
183
|
);
|
|
184
|
+
if (options.useSrcDir) {
|
|
185
|
+
const cssPath = path.join(dest, "src/app/global.css");
|
|
186
|
+
await fs.writeFile(
|
|
187
|
+
cssPath,
|
|
188
|
+
(await fs.readFile(cssPath)).toString().replace("../", "../../")
|
|
189
|
+
);
|
|
190
|
+
}
|
|
165
191
|
log("Configured Tailwind CSS");
|
|
166
192
|
}
|
|
167
|
-
if (options.eslint) {
|
|
168
|
-
await copy(
|
|
193
|
+
if (isNext && options.eslint) {
|
|
194
|
+
await copy(
|
|
195
|
+
path.join(sourceDir, `template/+next+eslint`),
|
|
196
|
+
dest,
|
|
197
|
+
defaultRename
|
|
198
|
+
);
|
|
169
199
|
log("Configured ESLint");
|
|
170
200
|
}
|
|
171
|
-
if (options.useSrcDir) {
|
|
201
|
+
if (isNext && options.useSrcDir) {
|
|
172
202
|
const tsconfigPath = path.join(dest, "tsconfig.json");
|
|
173
203
|
const content = (await fs.readFile(tsconfigPath)).toString();
|
|
174
204
|
const config = JSON.parse(content);
|
|
@@ -178,16 +208,12 @@ async function create(options) {
|
|
|
178
208
|
});
|
|
179
209
|
}
|
|
180
210
|
await fs.writeFile(tsconfigPath, JSON.stringify(config, null, 2));
|
|
181
|
-
if (options.tailwindcss) {
|
|
182
|
-
const cssPath = path.join(dest, "src/app/global.css");
|
|
183
|
-
await fs.writeFile(
|
|
184
|
-
cssPath,
|
|
185
|
-
(await fs.readFile(cssPath)).toString().replace("../", "../../")
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
211
|
}
|
|
189
212
|
const packageJson = createPackageJson(projectName, options);
|
|
190
|
-
await fs.writeFile(
|
|
213
|
+
await fs.writeFile(
|
|
214
|
+
path.join(dest, "package.json"),
|
|
215
|
+
JSON.stringify(packageJson, null, 2)
|
|
216
|
+
);
|
|
191
217
|
const readMe = await getReadme(dest, projectName);
|
|
192
218
|
await fs.writeFile(path.join(dest, "README.md"), readMe);
|
|
193
219
|
if (installDeps) {
|
|
@@ -219,65 +245,130 @@ async function copy(from, to, rename = (s) => s) {
|
|
|
219
245
|
}
|
|
220
246
|
}
|
|
221
247
|
function createPackageJson(projectName, options) {
|
|
222
|
-
|
|
248
|
+
if (options.template === "react-router") {
|
|
249
|
+
return {
|
|
250
|
+
name: projectName,
|
|
251
|
+
private: true,
|
|
252
|
+
type: "module",
|
|
253
|
+
scripts: {
|
|
254
|
+
build: "react-router build",
|
|
255
|
+
dev: "react-router dev",
|
|
256
|
+
start: "react-router-serve ./build/server/index.js",
|
|
257
|
+
typecheck: "react-router typegen && tsc"
|
|
258
|
+
},
|
|
259
|
+
dependencies: {
|
|
260
|
+
...pick(versions, [
|
|
261
|
+
"@fumadocs/mdx-remote",
|
|
262
|
+
"fumadocs-core",
|
|
263
|
+
"fumadocs-ui"
|
|
264
|
+
]),
|
|
265
|
+
...pick(package_default.dependencies, [
|
|
266
|
+
"@react-router/node",
|
|
267
|
+
"@react-router/serve",
|
|
268
|
+
"gray-matter",
|
|
269
|
+
"isbot",
|
|
270
|
+
"react",
|
|
271
|
+
"react-dom",
|
|
272
|
+
"react-router",
|
|
273
|
+
"shiki"
|
|
274
|
+
])
|
|
275
|
+
},
|
|
276
|
+
devDependencies: pick(package_default.dependencies, [
|
|
277
|
+
"@react-router/dev",
|
|
278
|
+
"@tailwindcss/vite",
|
|
279
|
+
"@types/node",
|
|
280
|
+
"@types/react",
|
|
281
|
+
"@types/react-dom",
|
|
282
|
+
"react-router-devtools",
|
|
283
|
+
"tailwindcss",
|
|
284
|
+
"typescript",
|
|
285
|
+
"vite",
|
|
286
|
+
"vite-tsconfig-paths"
|
|
287
|
+
])
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
if (options.template === "tanstack-start") {
|
|
291
|
+
return {
|
|
292
|
+
name: projectName,
|
|
293
|
+
type: "module",
|
|
294
|
+
scripts: {
|
|
295
|
+
dev: "vinxi dev",
|
|
296
|
+
build: "NODE_ENV=production vinxi build",
|
|
297
|
+
start: "vinxi start"
|
|
298
|
+
},
|
|
299
|
+
private: true,
|
|
300
|
+
dependencies: {
|
|
301
|
+
...pick(versions, [
|
|
302
|
+
"@fumadocs/mdx-remote",
|
|
303
|
+
"fumadocs-ui",
|
|
304
|
+
"fumadocs-core"
|
|
305
|
+
]),
|
|
306
|
+
...pick(package_default.dependencies, [
|
|
307
|
+
"@tanstack/react-router",
|
|
308
|
+
"@tanstack/react-start",
|
|
309
|
+
"fast-glob",
|
|
310
|
+
"gray-matter",
|
|
311
|
+
"react",
|
|
312
|
+
"react-dom",
|
|
313
|
+
"vinxi"
|
|
314
|
+
])
|
|
315
|
+
},
|
|
316
|
+
devDependencies: pick(package_default.dependencies, [
|
|
317
|
+
"@tailwindcss/vite",
|
|
318
|
+
"@types/react",
|
|
319
|
+
"@types/react-dom",
|
|
320
|
+
"@vitejs/plugin-react",
|
|
321
|
+
"tailwindcss",
|
|
322
|
+
"typescript",
|
|
323
|
+
"vite",
|
|
324
|
+
"vite-tsconfig-paths"
|
|
325
|
+
])
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
223
329
|
name: projectName,
|
|
224
330
|
version: "0.0.0",
|
|
225
331
|
private: true,
|
|
226
332
|
scripts: {
|
|
227
333
|
build: "next build",
|
|
228
334
|
dev: "next dev",
|
|
229
|
-
start: "next start"
|
|
335
|
+
start: "next start",
|
|
336
|
+
...options.template === "+next+fuma-docs-mdx" ? {
|
|
337
|
+
postinstall: "fumadocs-mdx"
|
|
338
|
+
} : null
|
|
230
339
|
},
|
|
231
340
|
dependencies: {
|
|
232
341
|
...pick(package_default.dependencies, ["next", "react", "react-dom"]),
|
|
233
|
-
...pick(versions, ["fumadocs-ui", "fumadocs-core"])
|
|
342
|
+
...pick(versions, ["fumadocs-ui", "fumadocs-core"]),
|
|
343
|
+
...options.template === "+next+content-collections" ? {
|
|
344
|
+
...pick(package_default.dependencies, [
|
|
345
|
+
"@content-collections/mdx",
|
|
346
|
+
"@content-collections/core",
|
|
347
|
+
"@content-collections/next"
|
|
348
|
+
]),
|
|
349
|
+
...pick(versions, ["@fumadocs/content-collections"])
|
|
350
|
+
} : null,
|
|
351
|
+
...options.template === "+next+fuma-docs-mdx" ? pick(versions, ["fumadocs-mdx"]) : null
|
|
234
352
|
},
|
|
235
|
-
devDependencies:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (options.template === "content-collections") {
|
|
243
|
-
Object.assign(
|
|
244
|
-
packageJson.dependencies,
|
|
245
|
-
pick(package_default.dependencies, [
|
|
246
|
-
"@content-collections/mdx",
|
|
247
|
-
"@content-collections/core",
|
|
248
|
-
"@content-collections/next"
|
|
353
|
+
devDependencies: {
|
|
354
|
+
...pick(package_default.dependencies, [
|
|
355
|
+
"@types/node",
|
|
356
|
+
"@types/react",
|
|
357
|
+
"@types/react-dom",
|
|
358
|
+
"typescript",
|
|
359
|
+
"@types/mdx"
|
|
249
360
|
]),
|
|
250
|
-
pick(
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
if (options.template === "fuma-docs-mdx") {
|
|
254
|
-
packageJson.scripts.postinstall = "fumadocs-mdx";
|
|
255
|
-
Object.assign(
|
|
256
|
-
packageJson.dependencies,
|
|
257
|
-
pick(versions, ["fumadocs-mdx"])
|
|
258
|
-
);
|
|
259
|
-
Object.assign(
|
|
260
|
-
packageJson.devDependencies,
|
|
261
|
-
pick(package_default.dependencies, ["@types/mdx"])
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
if (options.tailwindcss) {
|
|
265
|
-
Object.assign(
|
|
266
|
-
packageJson.devDependencies,
|
|
267
|
-
pick(package_default.dependencies, [
|
|
361
|
+
...options.tailwindcss ? pick(package_default.dependencies, [
|
|
268
362
|
"@tailwindcss/postcss",
|
|
269
363
|
"tailwindcss",
|
|
270
364
|
"postcss"
|
|
271
|
-
])
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
return JSON.stringify(packageJson, void 0, 2);
|
|
365
|
+
]) : null,
|
|
366
|
+
...options.eslint ? {
|
|
367
|
+
eslint: "^8",
|
|
368
|
+
"eslint-config-next": package_default.dependencies.next
|
|
369
|
+
} : null
|
|
370
|
+
}
|
|
371
|
+
};
|
|
281
372
|
}
|
|
282
373
|
function pick(obj, keys) {
|
|
283
374
|
const result = {};
|
package/dist/create-app.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,10 +3,9 @@ import {
|
|
|
3
3
|
create,
|
|
4
4
|
cwd,
|
|
5
5
|
getPackageManager
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LCUIXVWC.js";
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import { existsSync } from "node:fs";
|
|
10
9
|
import fs from "node:fs/promises";
|
|
11
10
|
import path from "node:path";
|
|
12
11
|
import {
|
|
@@ -32,23 +31,43 @@ async function main() {
|
|
|
32
31
|
defaultValue: "my-app"
|
|
33
32
|
}),
|
|
34
33
|
template: () => select({
|
|
35
|
-
message: "Choose a
|
|
36
|
-
initialValue: "fuma-docs-mdx",
|
|
34
|
+
message: "Choose a template",
|
|
35
|
+
initialValue: "+next+fuma-docs-mdx",
|
|
37
36
|
options: [
|
|
38
37
|
{
|
|
39
|
-
value: "fuma-docs-mdx",
|
|
40
|
-
label: "Fumadocs MDX",
|
|
38
|
+
value: "+next+fuma-docs-mdx",
|
|
39
|
+
label: "Next.js: Fumadocs MDX",
|
|
41
40
|
hint: "recommended"
|
|
42
41
|
},
|
|
43
|
-
{
|
|
42
|
+
{
|
|
43
|
+
value: "+next+content-collections",
|
|
44
|
+
label: "Next.js: Content Collections"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
value: "react-router",
|
|
48
|
+
label: "React Router: MDX Remote"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
value: "tanstack-start",
|
|
52
|
+
label: "Tanstack Start: MDX Remote",
|
|
53
|
+
hint: "Experimental"
|
|
54
|
+
}
|
|
44
55
|
]
|
|
45
56
|
}),
|
|
46
|
-
src: () =>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
src: (v) => {
|
|
58
|
+
if (!v.results.template?.startsWith("+next")) return;
|
|
59
|
+
return confirm({
|
|
60
|
+
message: "Use `/src` directory?",
|
|
61
|
+
initialValue: false
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
eslint: (v) => {
|
|
65
|
+
if (!v.results.template?.startsWith("+next")) return;
|
|
66
|
+
return confirm({
|
|
67
|
+
message: "Add default ESLint configuration?",
|
|
68
|
+
initialValue: false
|
|
69
|
+
});
|
|
70
|
+
},
|
|
52
71
|
installDeps: () => confirm({
|
|
53
72
|
message: `Do you want to install packages automatically? (detected as ${manager})`
|
|
54
73
|
})
|
|
@@ -62,9 +81,10 @@ async function main() {
|
|
|
62
81
|
);
|
|
63
82
|
const projectName = options.name.toLowerCase().replace(/\s/, "-");
|
|
64
83
|
const dest = path.resolve(cwd, projectName);
|
|
65
|
-
|
|
84
|
+
const destDir = await fs.readdir(dest).catch(() => null);
|
|
85
|
+
if (destDir && destDir.length > 0) {
|
|
66
86
|
const del = await confirm({
|
|
67
|
-
message:
|
|
87
|
+
message: `directory ${projectName} already exists, do you want to delete its files?`
|
|
68
88
|
});
|
|
69
89
|
if (isCancel(del)) {
|
|
70
90
|
cancel();
|
|
@@ -72,24 +92,28 @@ async function main() {
|
|
|
72
92
|
}
|
|
73
93
|
if (del) {
|
|
74
94
|
const info2 = spinner();
|
|
75
|
-
info2.start(`Deleting ${projectName}`);
|
|
76
|
-
await
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
info2.start(`Deleting files in ${projectName}`);
|
|
96
|
+
await Promise.all(
|
|
97
|
+
destDir.map((item) => {
|
|
98
|
+
return fs.rm(path.join(dest, item), {
|
|
99
|
+
recursive: true,
|
|
100
|
+
force: true
|
|
101
|
+
});
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
info2.stop(`Deleted files in ${projectName}`);
|
|
81
105
|
}
|
|
82
106
|
}
|
|
83
107
|
const info = spinner();
|
|
84
108
|
info.start(`Generating Project`);
|
|
85
109
|
await create({
|
|
86
110
|
packageManager: manager,
|
|
87
|
-
tailwindcss:
|
|
111
|
+
tailwindcss: true,
|
|
88
112
|
template: options.template,
|
|
89
113
|
outputDir: dest,
|
|
90
114
|
installDeps: options.installDeps,
|
|
91
|
-
eslint: options.eslint,
|
|
92
|
-
useSrcDir: options.src,
|
|
115
|
+
eslint: options.eslint === true,
|
|
116
|
+
useSrcDir: options.src === true,
|
|
93
117
|
log: (message) => {
|
|
94
118
|
info.message(message);
|
|
95
119
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fumadocs-app",
|
|
3
|
-
"version": "15.1
|
|
3
|
+
"version": "15.2.1",
|
|
4
4
|
"description": "Create a new documentation site with Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/cross-spawn": "^6.0.6",
|
|
28
|
-
"@types/node": "22.13.
|
|
28
|
+
"@types/node": "22.13.14",
|
|
29
29
|
"fast-glob": "^3.3.3",
|
|
30
30
|
"eslint-config-custom": "0.0.0",
|
|
31
31
|
"tsconfig": "0.0.0"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Route } from './+types/page';
|
|
2
|
+
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
|
3
|
+
import {
|
|
4
|
+
DocsBody,
|
|
5
|
+
DocsDescription,
|
|
6
|
+
DocsPage,
|
|
7
|
+
DocsTitle,
|
|
8
|
+
} from 'fumadocs-ui/page';
|
|
9
|
+
import { source } from '@/source';
|
|
10
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
11
|
+
import { executeMdxSync } from '@fumadocs/mdx-remote/client';
|
|
12
|
+
import type { PageTree } from 'fumadocs-core/server';
|
|
13
|
+
import { createCompiler } from '@fumadocs/mdx-remote';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
|
|
16
|
+
export function meta({}: Route.MetaArgs) {
|
|
17
|
+
return [
|
|
18
|
+
{ title: 'New React Router App' },
|
|
19
|
+
{ name: 'description', content: 'Welcome to React Router!' },
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
const compiler = createCompiler({
|
|
23
|
+
development: false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export async function loader({ params }: Route.LoaderArgs) {
|
|
27
|
+
const slugs = params['*'].split('/').filter((v) => v.length > 0);
|
|
28
|
+
const page = source.getPage(slugs);
|
|
29
|
+
if (!page) throw new Error('Not found');
|
|
30
|
+
|
|
31
|
+
const compiled = await compiler.compileFile({
|
|
32
|
+
path: path.resolve('content/docs', page.file.path),
|
|
33
|
+
value: page.data.content,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
page,
|
|
38
|
+
compiled: compiled.toString(),
|
|
39
|
+
tree: source.pageTree,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default function Page(props: Route.ComponentProps) {
|
|
44
|
+
const { page, compiled, tree } = props.loaderData;
|
|
45
|
+
const { default: Mdx, toc } = executeMdxSync(compiled);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<DocsLayout
|
|
49
|
+
nav={{
|
|
50
|
+
title: 'React Router',
|
|
51
|
+
}}
|
|
52
|
+
tree={tree as PageTree.Root}
|
|
53
|
+
>
|
|
54
|
+
<DocsPage toc={toc}>
|
|
55
|
+
<DocsTitle>{page.data.title}</DocsTitle>
|
|
56
|
+
<DocsDescription>{page.data.description}</DocsDescription>
|
|
57
|
+
<DocsBody>
|
|
58
|
+
<Mdx components={defaultMdxComponents} />
|
|
59
|
+
</DocsBody>
|
|
60
|
+
</DocsPage>
|
|
61
|
+
</DocsLayout>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Route } from './+types/search';
|
|
2
|
+
import { createSearchAPI } from 'fumadocs-core/search/server';
|
|
3
|
+
import { source } from '@/source';
|
|
4
|
+
import { structure } from 'fumadocs-core/mdx-plugins';
|
|
5
|
+
|
|
6
|
+
const server = createSearchAPI('advanced', {
|
|
7
|
+
indexes: source.getPages().map((page) => ({
|
|
8
|
+
id: page.url,
|
|
9
|
+
url: page.url,
|
|
10
|
+
title: page.data.title ?? '',
|
|
11
|
+
description: page.data.description,
|
|
12
|
+
structuredData: structure(page.data.content),
|
|
13
|
+
})),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
17
|
+
return server.GET(request);
|
|
18
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRouteErrorResponse,
|
|
3
|
+
Links,
|
|
4
|
+
Meta,
|
|
5
|
+
Outlet,
|
|
6
|
+
Scripts,
|
|
7
|
+
ScrollRestoration,
|
|
8
|
+
} from 'react-router';
|
|
9
|
+
import { RootProvider } from 'fumadocs-ui/provider/base';
|
|
10
|
+
import { ReactRouterProvider } from 'fumadocs-core/framework/react-router';
|
|
11
|
+
import type { Route } from './+types/root';
|
|
12
|
+
import './app.css';
|
|
13
|
+
|
|
14
|
+
export const links: Route.LinksFunction = () => [
|
|
15
|
+
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
|
16
|
+
{
|
|
17
|
+
rel: 'preconnect',
|
|
18
|
+
href: 'https://fonts.gstatic.com',
|
|
19
|
+
crossOrigin: 'anonymous',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
rel: 'stylesheet',
|
|
23
|
+
href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export function Layout({ children }: { children: React.ReactNode }) {
|
|
28
|
+
return (
|
|
29
|
+
<html lang="en" suppressHydrationWarning>
|
|
30
|
+
<head>
|
|
31
|
+
<meta charSet="utf-8" />
|
|
32
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
33
|
+
<Meta />
|
|
34
|
+
<Links />
|
|
35
|
+
</head>
|
|
36
|
+
<body>
|
|
37
|
+
<ReactRouterProvider>
|
|
38
|
+
<RootProvider>{children}</RootProvider>
|
|
39
|
+
</ReactRouterProvider>
|
|
40
|
+
<ScrollRestoration />
|
|
41
|
+
<Scripts />
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default function App() {
|
|
48
|
+
return <Outlet />;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
|
52
|
+
let message = 'Oops!';
|
|
53
|
+
let details = 'An unexpected error occurred.';
|
|
54
|
+
let stack: string | undefined;
|
|
55
|
+
|
|
56
|
+
if (isRouteErrorResponse(error)) {
|
|
57
|
+
message = error.status === 404 ? '404' : 'Error';
|
|
58
|
+
details =
|
|
59
|
+
error.status === 404
|
|
60
|
+
? 'The requested page could not be found.'
|
|
61
|
+
: error.statusText || details;
|
|
62
|
+
} else if (import.meta.env.DEV && error && error instanceof Error) {
|
|
63
|
+
details = error.message;
|
|
64
|
+
stack = error.stack;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<main className="pt-16 p-4 container mx-auto">
|
|
69
|
+
<h1>{message}</h1>
|
|
70
|
+
<p>{details}</p>
|
|
71
|
+
{stack && (
|
|
72
|
+
<pre className="w-full p-4 overflow-x-auto">
|
|
73
|
+
<code>{stack}</code>
|
|
74
|
+
</pre>
|
|
75
|
+
)}
|
|
76
|
+
</main>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Route } from './+types/home';
|
|
2
|
+
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
|
3
|
+
import { Link } from 'react-router';
|
|
4
|
+
|
|
5
|
+
export function meta({}: Route.MetaArgs) {
|
|
6
|
+
return [
|
|
7
|
+
{ title: 'New React Router App' },
|
|
8
|
+
{ name: 'description', content: 'Welcome to React Router!' },
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default function Home() {
|
|
13
|
+
return (
|
|
14
|
+
<HomeLayout
|
|
15
|
+
className="text-center"
|
|
16
|
+
nav={{
|
|
17
|
+
title: 'React Router',
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
<div className="py-12">
|
|
21
|
+
<h1 className="text-xl font-bold mb-2">Fumadocs on React Router.</h1>
|
|
22
|
+
<p className="text-fd-muted-foreground mb-8">
|
|
23
|
+
The truly flexible docs framework on React.js.
|
|
24
|
+
</p>
|
|
25
|
+
<Link
|
|
26
|
+
className="text-sm bg-fd-primary text-fd-primary-foreground rounded-full font-medium px-4 py-2.5"
|
|
27
|
+
to="/docs"
|
|
28
|
+
>
|
|
29
|
+
Open Docs
|
|
30
|
+
</Link>
|
|
31
|
+
</div>
|
|
32
|
+
</HomeLayout>
|
|
33
|
+
);
|
|
34
|
+
}
|